This commit is contained in:
Leopere 2026-02-24 16:14:53 -05:00
parent eb3f3d4134
commit 99e7df77ba
Signed by: colin
SSH Key Fingerprint: SHA256:nRPCQTeMFLdGytxRQmPVK9VXY3/ePKQ5lGRyJhT5DY8
7 changed files with 295 additions and 19 deletions

View File

@ -2,6 +2,14 @@
Welcome to Clawtainer! This desktop has OpenClaw Gateway pre-installed and running on port 18789.
## Container layout
- **Desktop (VNC):** http://localhost:6901 (via nginx proxy)
- **OpenClaw Gateway:** http://localhost:18789
- **Gateway token:** `clawtainer` (enter in Settings → token)
- **Config:** `~/.openclaw/openclaw.json` (inside the container; `/home/kasm-user/.openclaw/`)
- **Env vars:** Project `.env` is loaded by Docker Compose; `GROQ_API_KEY`, `TELEGRAM_BOT_TOKEN`, etc. are passed into the container.
## What is OpenClaw?
OpenClaw is an open-source AI agent orchestration platform that connects to AI provider APIs. The Gateway is already running in the background, but you need to configure it with your API keys.
@ -30,32 +38,20 @@ This will guide you through:
### Option 3: Manual Configuration
Create or edit `~/.openclaw/openclaw.json`:
Create or edit `~/.openclaw/openclaw.json` inside the desktop (or merge config and `docker cp` it in). For **built-in providers** (Anthropic, OpenAI, Google, Groq), you can also use environment variables: add keys to the project `.env` and ensure they're in `docker-compose.yml` `environment` so they reach the container.
Example manual `models.providers`:
```json
{
"models": {
"providers": {
"anthropic": {
"apiKey": "sk-ant-your-key-here"
},
"openai": {
"apiKey": "sk-your-key-here"
},
"google": {
"apiKey": "AIza-your-key-here"
"anthropic": { "apiKey": "sk-ant-your-key-here" },
"openai": { "apiKey": "sk-your-key-here" },
"google": { "apiKey": "AIza-your-key-here" }
}
}
}
}
```
Or use environment variables in `~/.bashrc`:
```bash
export ANTHROPIC_API_KEY="sk-ant-your-key-here"
export OPENAI_API_KEY="sk-your-key-here"
export GOOGLE_API_KEY="AIza-your-key-here"
```
## Get API Keys
@ -78,6 +74,61 @@ You'll need API keys from at least one provider:
- Best for: Access to multiple models through one API
- Pricing: Varies by model selected
- **Groq**: https://console.groq.com/keys
- Best for: Very fast inference (Llama 3.x, GPT-OSS). OpenAI-compatible API.
- Pricing: Low cost per token, free tier available.
### Using Groq with Clawtainer
Put `GROQ_API_KEY` in the project `.env`. Docker Compose passes it into the container.
**Option A: Script (recommended)**
From the project root, after `docker compose up -d`:
```bash
./scripts/configure-groq.sh
docker exec clawtainer openclaw gateway restart
```
> **Note:** The script **overwrites** `~/.openclaw/openclaw.json` with a Groq-only config. If you have other providers or channels, run the script first, then add them manually to `openclaw.json`.
**Option B: Manual config**
Inside the desktop, edit `~/.openclaw/openclaw.json`. Add under `models.providers` (merge with existing providers if present):
```json
"groq": {
"baseUrl": "https://api.groq.com/openai/v1",
"api": "openai-completions",
"apiKey": "your-groq-api-key",
"models": [
{ "id": "llama-3.3-70b-versatile", "name": "Llama 3.3 70B", "contextWindow": 131072 },
{ "id": "llama-3.1-8b-instant", "name": "Llama 3.1 8B", "contextWindow": 131072 }
]
}
```
Use `"api": "openai-completions"` (not `"openai"`). Wrong API type can cause **Verification failed: status 404**.
**Groq model IDs**
| Model ID | Notes |
|----------|-------|
| `groq/llama-3.3-70b-versatile` | Best quality, 280 tok/s |
| `groq/llama-3.1-8b-instant` | Faster, cheaper |
| `groq/openai/gpt-oss-120b` | OpenAI OSS 120B |
Set default: add `"agents": { "defaults": { "model": { "primary": "groq/llama-3.3-70b-versatile" } } }` to `openclaw.json`.
**Verify your Groq key**
```bash
curl -s "https://api.groq.com/openai/v1/models" -H "Authorization: Bearer $GROQ_API_KEY" | head -20
```
If you get JSON back, the key works. If 401, the key is invalid. If 404, the URL is wrong.
## Verify Setup
After adding keys, test the connection:
@ -88,6 +139,107 @@ openclaw gateway status
Or visit `http://localhost:18789` to see the Gateway control panel.
## Messaging Channels (WhatsApp, Telegram, Discord, Signal, …)
You can add WhatsApp, Telegram, Discord, **Signal**, and other channels so the agent is reachable from your phone or team chat. Config lives in `~/.openclaw/openclaw.json` under `channels`. Restart the gateway after changes: `openclaw gateway restart`.
**Install all channel plugins (no container rebuild):** Run `./scripts/install-channel-clients.sh` to add Mattermost, Teams, Matrix, Nostr, Zalo, and signal-cli into the running container via `docker exec`. Then restart: `docker exec clawtainer openclaw gateway restart`.
### Telegram
1. In Telegram, open a chat with **@BotFather**, run `/newbot`, and copy the bot token.
2. Add the token to `.env` as `TELEGRAM_BOT_TOKEN=...` (Clawtainer passes it into the container), or put it in `openclaw.json` under `channels.telegram.botToken`.
3. Add a `channels.telegram` block in `~/.openclaw/openclaw.json` (merge with existing `channels` if present):
```json
"channels": {
"telegram": {
"enabled": true,
"dmPolicy": "pairing",
"groups": { "*": { "requireMention": true } }
}
}
```
4. Restart the gateway, then approve DMs: `openclaw pairing list telegram` and `openclaw pairing approve telegram <CODE>`.
- Docs: https://docs.openclaw.ai/channels/telegram
### Discord
1. In the [Discord Developer Portal](https://discord.com/developers/applications), create an application, add a Bot, and copy the bot token.
2. Add to `.env` as `DISCORD_BOT_TOKEN=...` (Clawtainer passes it in), or set `channels.discord.token` in `openclaw.json`.
3. Add a `channels.discord` block:
```json
"channels": {
"discord": {
"enabled": true,
"dmPolicy": "pairing",
"allowFrom": ["YOUR_DISCORD_USER_ID"]
}
}
```
4. Invite the bot to your server (OAuth2 → URL Generator, scopes: bot; permissions as needed). Restart the gateway.
- Docs: https://docs.openclaw.ai/gateway/configuration-reference (Discord section)
### WhatsApp
WhatsApp uses the gateways web channel (Baileys). A linked session must exist before WhatsApp will start.
1. In `~/.openclaw/openclaw.json`, ensure the web channel and WhatsApp are enabled:
```json
"channels": {
"whatsapp": {
"dmPolicy": "pairing",
"allowFrom": ["+15555550123"],
"groups": { "*": { "requireMention": true } }
}
},
"web": { "enabled": true }
```
2. **Link a session once** (from a terminal inside the Clawtainer desktop, or via the Control UI if it supports pairing):
- Run `openclaw channels login` and complete the QR/linking flow for WhatsApp.
3. Restart the gateway. WhatsApp will start when the linked session exists.
- Docs: https://docs.openclaw.ai/gateway/configuration-reference (WhatsApp section)
### Signal
OpenClaw supports **Signal** (E2E encrypted) via the external CLI **signal-cli**. You get DMs, groups, reactions, read receipts, and media. Use a **dedicated bot number** (recommended) or link an existing account with QR.
**Requirements:** `signal-cli` must be installed where the gateway runs (inside the Clawtainer container if you use Docker). The native Linux build is preferred (no JVM).
1. **Path A (QR link)** Link an existing Signal account: run `signal-cli link -n "OpenClaw"` and scan the QR in Signal.
2. **Path B (dedicated number)** Register a new number: `signal-cli -a +1… register` (and `--captcha` if required; see [Signal captcha](https://signalcaptchas.org/registration/generate.html)), then `signal-cli -a +1… verify <CODE>`.
3. Add a `channels.signal` block in `~/.openclaw/openclaw.json`:
```json
"channels": {
"signal": {
"enabled": true,
"account": "+15551234567",
"cliPath": "signal-cli",
"dmPolicy": "pairing",
"allowFrom": ["+15557654321"]
}
}
```
4. Restart the gateway. Approve DMs with `openclaw pairing list signal` and `openclaw pairing approve signal <CODE>`.
**Clawtainer note:** The stock image does not include `signal-cli`. Run `./scripts/install-channel-clients.sh` to install it in the running container, or add it in a custom Dockerfile.
- Docs: https://docs.openclaw.ai/channels/signal
### Other channels
OpenClaw also supports **iMessage** (macOS only; uses `imsg` and Messages DB), **Slack** (bot + app tokens), **Google Chat** (service account), and **Mattermost** (plugin: `openclaw plugins install @openclaw/mattermost`). See the [configuration reference](https://docs.openclaw.ai/gateway/configuration-reference) for each.
## Pre-installed Tools
This desktop includes:
@ -108,6 +260,13 @@ You can change this by setting the `OPENCLAW_GATEWAY_TOKEN` environment variable
## Troubleshooting
**"Health offline" in the Control UI?**
The UI connects to the gateway over WebSocket. You must **enter the gateway token** so it can authenticate:
1. Open http://localhost:18789
2. Open **Settings** (gear or settings panel)
3. Enter token: **`clawtainer`** (or whatever you set in `OPENCLAW_GATEWAY_TOKEN`)
4. Save / connect. Health should show online once the WebSocket connects with the token.
**Gateway not responding?**
```bash
# Check if gateway is running
@ -122,6 +281,11 @@ openclaw gateway restart
- Verify billing is enabled on the provider's platform
- Check for typos in the key
**Groq: "Verification failed: status 404"?**
- Ensure `baseUrl` is exactly `https://api.groq.com/openai/v1` (no trailing slash)
- Use `"api": "openai-completions"` (not `"openai"`)
- Re-run `./scripts/configure-groq.sh` and restart the gateway, or verify your manual config matches the template
**Need help?**
- OpenClaw Docs: https://docs.openclaw.ai/
- OpenClaw GitHub: https://github.com/openclaw/openclaw

View File

@ -23,7 +23,9 @@ docker compose up -d
```
- **Desktop**: **http://localhost:6901** (no password required)
- **OpenClaw Control UI**: http://localhost:18789 (token: `clawtainer`)
- **OpenClaw Control UI**: http://127.0.0.1:18789 (token: `clawtainer`)
**If localhost:18789 fails** (common on macOS): use **http://127.0.0.1:18789** instead. Run `./scripts/configure-groq.sh` to set API keys and start the gateway.
The nginx proxy strips TLS from the VNC connection for easy browser access.

View File

@ -8,6 +8,11 @@ services:
- "18789:18789" # OpenClaw gateway Control UI
environment:
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-clawtainer}
GROQ_API_KEY: ${GROQ_API_KEY:-}
TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN:-}
DISCORD_BOT_TOKEN: ${DISCORD_BOT_TOKEN:-}
volumes:
- openclaw-data:/home/kasm-user/.openclaw
restart: unless-stopped
networks:
- clawtainer-net
@ -28,3 +33,6 @@ services:
networks:
clawtainer-net:
driver: bridge
volumes:
openclaw-data:

29
scripts/configure-groq.sh Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Writes OpenClaw Groq provider config into the running clawtainer container
# using GROQ_API_KEY from project .env. Run after: docker compose up -d
set -e
cd "$(dirname "$0")/.."
if [ ! -f .env ]; then
echo "No .env found. Add GROQ_API_KEY=your-key to .env"
exit 1
fi
# shellcheck source=/dev/null
source .env
if [ -z "${GROQ_API_KEY}" ]; then
echo "Set GROQ_API_KEY in .env"
exit 1
fi
# Escape for JSON: \ and "
key_esc="${GROQ_API_KEY//\\/\\\\}"
key_esc="${key_esc//\"/\\\"}"
tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT
sed "s|GROQ_API_KEY_PLACEHOLDER|$key_esc|g" scripts/openclaw-groq.json.template > "$tmp"
docker exec clawtainer mkdir -p /home/kasm-user/.openclaw/canvas /home/kasm-user/.openclaw/cron /home/kasm-user/.openclaw/workspace
docker cp "$tmp" clawtainer:"/home/kasm-user/.openclaw/openclaw.json"
docker exec -u root clawtainer chown -R 1000:1000 /home/kasm-user/.openclaw
if ! docker exec clawtainer pgrep -x openclaw >/dev/null 2>&1; then
docker exec clawtainer bash -c 'nohup openclaw gateway --bind lan --allow-unconfigured >/tmp/openclaw.log 2>&1 &'
echo "Gateway started."
fi
echo "OpenClaw configured for Groq. Control UI: http://localhost:18789 (token: clawtainer)"

View File

@ -0,0 +1,71 @@
#!/usr/bin/env bash
# Install all OpenClaw channel plugins + signal-cli into the RUNNING clawtainer
# container via docker exec. No image rebuild or container replace.
# Run after: docker compose up -d
set -e
cd "$(dirname "$0")/.."
CONTAINER="${CLAWTAINER_CONTAINER:-clawtainer}"
OPENCLAW_USER=1000
SIGNAL_CLI_VER="0.13.24"
# Channel plugins from npm (official @openclaw)
PLUGINS=(
"@openclaw/mattermost"
"@openclaw/msteams"
"@openclaw/matrix"
"@openclaw/nostr"
"@openclaw/zalo"
"@openclaw/zalouser"
)
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
echo "Container ${CONTAINER} is not running. Start with: docker compose up -d"
exit 1
fi
echo "Installing OpenClaw channel plugins..."
for pkg in "${PLUGINS[@]}"; do
echo " -> $pkg"
docker exec -u "$OPENCLAW_USER" "$CONTAINER" \
openclaw --yes plugins install "$pkg" || true
done
echo "Installing signal-cli..."
docker exec -u root "$CONTAINER" bash -c '
set -e
VER='"$SIGNAL_CLI_VER"'
ARCH=$(uname -m)
INSTALL_DIR=/usr/local
cd /tmp
if command -v signal-cli >/dev/null 2>&1 && signal-cli --version 2>/dev/null | grep -q "$VER"; then
echo " signal-cli $VER already installed"
exit 0
fi
mkdir -p "$INSTALL_DIR/bin"
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
echo " Using native binary (x86_64)"
curl -fsSL -o signal-cli.tar.gz \
"https://github.com/AsamK/signal-cli/releases/download/v${VER}/signal-cli-${VER}-Linux-native.tar.gz"
tar xzf signal-cli.tar.gz
mv signal-cli "$INSTALL_DIR/bin/"
else
echo " Using JVM build (${ARCH})"
apt-get update -qq && apt-get install -y -qq openjdk-21-jre-headless
curl -fsSL -o signal-cli.tar.gz \
"https://github.com/AsamK/signal-cli/releases/download/v${VER}/signal-cli-${VER}.tar.gz"
tar xzf signal-cli.tar.gz
cp -a signal-cli-${VER} /opt/signal-cli
ln -sf /opt/signal-cli/bin/signal-cli "$INSTALL_DIR/bin/signal-cli"
fi
chmod +x "$INSTALL_DIR/bin/signal-cli"
rm -rf /tmp/signal-cli*
echo " signal-cli installed"
'
echo ""
echo "Done. Installed:"
echo " - Plugins: ${PLUGINS[*]}"
echo " - signal-cli (for Signal channel)"
echo ""
echo "Restart the gateway to load plugins: docker exec $CONTAINER openclaw gateway restart"

View File

@ -0,0 +1 @@
{"agents":{"defaults":{"model":{"primary":"groq/llama-3.3-70b-versatile"}}}}

View File

@ -0,0 +1 @@
{"gateway":{"controlUi":{"dangerouslyAllowHostHeaderOriginFallback":true}},"agents":{"defaults":{"model":{"primary":"groq/llama-3.3-70b-versatile"}}},"models":{"mode":"merge","providers":{"groq":{"baseUrl":"https://api.groq.com/openai/v1","api":"openai-completions","apiKey":"GROQ_API_KEY_PLACEHOLDER","models":[{"id":"llama-3.3-70b-versatile","name":"Llama 3.3 70B","contextWindow":131072},{"id":"llama-3.1-8b-instant","name":"Llama 3.1 8B","contextWindow":131072}]}}}}