Move OpenClaw, Palmr, MinIO, JSX publishing, MCP configs, and migration candidates into dedicated docs/ files. Keep only DevOps-essential content inline (deployment rules, DNS, router, credentials, troubleshooting). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.1 KiB
OpenClaw (AI Assistant Gateway)
Self-hosted AI assistant gateway running on the NUC via Docker Compose. Connects to messaging platforms (WhatsApp, Telegram, Discord, etc.) and routes messages through Claude.
Access
| Property | Value |
|---|---|
| Control UI (HTTPS) | https://alezmad-nuc.tail58f5ad.ts.net:8443 |
| Gateway WS | ws://192.168.1.3:18789 |
| Gateway Token | 3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee |
| Model | anthropic/claude-sonnet-4-5-20250929 |
| Repo on NUC | ~/openclaw/ |
| Config | ~/.openclaw/openclaw.json |
| Version | 2026.2.10 |
HTTPS Required: The Control UI requires a secure context (HTTPS or localhost). Access via Tailscale Serve on port 8443.
Tailscale Serve (HTTPS access)
The gateway is exposed via Tailscale Serve (not Funnel - tailnet only, not public):
# Start HTTPS proxy (requires sudo, must run from NUC terminal)
ssh nuc
sudo tailscale serve --bg --https=8443 http://localhost:18789
# Password: 7vXHpSTD
The --bg flag makes it persistent. Without it, Ctrl+C stops the proxy.
Docker Compose Management
# Start gateway
ssh nuc "cd ~/openclaw && docker compose up -d openclaw-gateway"
# Restart gateway
ssh nuc "cd ~/openclaw && docker compose restart openclaw-gateway"
# View logs
ssh nuc "docker logs openclaw-openclaw-gateway-1 2>&1 | tail -30"
# Run CLI commands (use docker exec for commands that need gateway connection)
ssh nuc "docker exec openclaw-openclaw-gateway-1 node dist/index.js <command> --token 3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee --url ws://127.0.0.1:18789"
# Run CLI commands that don't need gateway (use docker compose run)
ssh nuc "cd ~/openclaw && script -qc 'docker compose run --rm openclaw-cli <command>' /dev/null"
Device Pairing
When the Control UI shows "pairing required", approve the pending device:
# List pending devices
ssh nuc "docker exec openclaw-openclaw-gateway-1 node dist/index.js devices list --token 3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee --url ws://127.0.0.1:18789"
# Approve a device (use requestId from the list)
ssh nuc "docker exec openclaw-openclaw-gateway-1 node dist/index.js devices approve <requestId> --token 3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee --url ws://127.0.0.1:18789"
Dashboard URL with embedded token (auto-authenticates):
https://alezmad-nuc.tail58f5ad.ts.net:8443/#token=3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee
Channel Plugins
Channels are plugins that must be enabled before use. 35 available, 4 loaded by default.
# List all plugins
ssh nuc "script -qc 'cd ~/openclaw && docker compose run --rm openclaw-cli plugins list' /dev/null"
# Enable a channel plugin
ssh nuc "script -qc 'cd ~/openclaw && docker compose run --rm openclaw-cli plugins enable <plugin-id>' /dev/null"
# Then restart gateway
ssh nuc "cd ~/openclaw && docker compose restart openclaw-gateway"
Currently enabled channels: WhatsApp (linked and active)
Available channel plugins:
| Plugin ID | Channel |
|---|---|
whatsapp |
|
telegram |
Telegram |
discord |
Discord |
slack |
Slack |
signal |
Signal |
matrix |
Matrix |
msteams |
Microsoft Teams |
googlechat |
Google Chat |
imessage |
iMessage |
irc |
IRC |
Setting Up Channels That Require QR Codes (WhatsApp, etc.)
The CLI needs a TTY for QR display. Cannot run directly via ssh nuc "command". Use script to fake a TTY and capture output:
# Step 1: Enable the plugin
ssh nuc "script -qc 'cd ~/openclaw && docker compose run --rm openclaw-cli plugins enable whatsapp' /dev/null"
# Step 2: Restart gateway
ssh nuc "cd ~/openclaw && docker compose restart openclaw-gateway"
# Step 3: Run login with TTY capture (captures QR to file)
ssh nuc "script -q /tmp/openclaw-qr.txt -c 'cd ~/openclaw && docker compose run --rm openclaw-cli channels login'"
# Step 4: If QR needs to be viewed remotely, copy and render as image
scp nuc:/tmp/openclaw-qr.txt /tmp/
# Then use Python + Pillow to convert Unicode block chars to PNG
QR to PNG conversion (run locally on Mac):
from PIL import Image
import re
with open("/tmp/openclaw-qr.txt", "rb") as f:
content = f.read().decode("utf-8", errors="replace")
lines = content.split("\n")
qr_lines = []
for l in lines:
clean = re.sub(r"\x1b\[[0-9;]*[a-zA-Z]", "", l).replace(chr(0), "")
if any(c in clean for c in ["\u2584", "\u2588", "\u2580"]):
qr_lines.append(clean)
scale = 10
width = max(len(l) for l in qr_lines)
height = len(qr_lines) * 2
img = Image.new("RGB", (width * scale, height * scale), "white")
for row_idx, line in enumerate(qr_lines):
for col_idx, ch in enumerate(line):
top_black = ch in ["\u2588", "\u2580"]
bot_black = ch in ["\u2588", "\u2584"]
for dy in range(scale):
for dx in range(scale):
if top_black:
img.putpixel((col_idx*scale+dx, row_idx*2*scale+dy), (0,0,0))
if bot_black:
img.putpixel((col_idx*scale+dx, (row_idx*2+1)*scale+dy), (0,0,0))
img.save("/tmp/qr.png")
Anthropic Authentication
Uses a Claude Code OAuth token (valid 1 year). Set in both config and docker-compose env:
Config (~/.openclaw/openclaw.json):
{
"env": {
"ANTHROPIC_API_KEY": "sk-ant-oat01-..."
}
}
Docker env (~/openclaw/.env):
ANTHROPIC_API_KEY=sk-ant-oat01-...
To regenerate token (run on Mac where claude CLI is installed):
claude setup-token
# Copy the output token and update both config + .env on NUC
Config Schema (current)
{
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-sonnet-4-5-20250929"
}
}
},
"gateway": {
"port": 18789,
"mode": "local",
"bind": "lan",
"auth": {
"mode": "token"
}
}
}
Config gotchas:
agent.modelis legacy — useagents.defaults.model.primaryinstead- Run
docker exec openclaw-openclaw-gateway-1 node dist/index.js doctor --fixto migrate legacy keys - The
gateway.pairingkey does NOT exist — device pairing is managed via thedevicesCLI, not config
Troubleshooting
-
"control ui requires HTTPS or localhost": Access via
https://alezmad-nuc.tail58f5ad.ts.net:8443(Tailscale Serve), NOThttp://192.168.1.3:18789 -
"pairing required": Approve the device via
devices approvecommand (see Device Pairing section above) -
"unauthorized: gateway token missing": Use the dashboard URL with
#token=...hash to auto-authenticate -
CLI commands fail with "gateway closed": Use
docker execinto the running gateway container instead ofdocker compose run(the CLI container can't reach the gateway on its internal Docker IP) -
Config "invalid" after edit: Run
doctor --fixinside the gateway container to clean up -
Channel "unsupported": Enable the plugin first with
plugins enable <id>, then restart gateway -
CLAUDE_AI_SESSION_KEY warnings: Harmless — these are for Claude web session auth which isn't used when using API key