I wanted a self-hosted OpenClaw deployment on Proxmox, reachable on my LAN, with:
- Gemini API key support
- Gemini CLI OAuth (Google AI Pro)
- Telegram bot integration
- Brave Search API integration
- Browser tool support in an LXC
- OpenRouter free model option (without Gemini CLI install)
- A second LXC that reuses the same working OpenClaw state/config
This post is the full reproducible path I used, including fixes and gotchas.
All secrets are shown as placeholders.
Replace values like<GEMINI_API_KEY>,<TELEGRAM_BOT_TOKEN>, and<OPENCLAW_GATEWAY_TOKEN>.
- Architecture and End State
- Prerequisites
- Build the First OpenClaw LXC (
101) - Configure OpenClaw Gateway + Model
- Add Telegram, Brave Search, and Gemini CLI OAuth
- Move to LXC
361(DHCP + SLAAC) - Enable Browser Tool in LXC
- Clone the Setup to LXC
362with OpenClawv2026.2.9 - Upgrade Existing LXC
361(2026.1.29to2026.2.9) - Upgrade LXC
361to2026.2.12and rotate Gemini CLI account - Upgrade LXC
361to2026.2.19and fix Telegram after update - Deploy LXC
363with OpenClaw2026.2.15+ OpenRouter Free (No Gemini CLI) - Deploy LXC
365with OpenClaw2026.2.26and Google Primary Model - Troubleshooting + Security
- Proxmox host runs Debian 13 LXCs.
- Primary OpenClaw LXC eventually became
361(DHCP/SLAAC). - Later, I deployed OpenClaw
v2026.2.9into a new362using the same OpenClaw config/state pattern. 361was later upgraded in place through2026.2.12and2026.2.19, with a Telegram post-update network tweak.363was deployed with OpenClaw2026.2.15, but using OpenRouter free model routing instead of Gemini CLI.365was later deployed with OpenClaw2026.2.26, reusing API-key based routing (Google primary + OpenRouter fallbacks).- OpenClaw gateway listens on
0.0.0.0:18789with token auth. - Control UI is accessed via:
http://<LAN_IP>:18789/?token=<OPENCLAW_GATEWAY_TOKEN>for older non-secure-context flowshttps://<YOUR_HOSTNAME>/?token=<OPENCLAW_GATEWAY_TOKEN>for secure browser device-identity flows
- Proxmox VE node with
pct,pveam,pvesh - Bridge network (e.g.
vmbr0) with DHCP/IPv6 RA available if using DHCP/SLAAC - Enough disk for Chromium + Playwright (browser tooling can add substantial footprint)
pveam update
pveam available --section system | grep debian-13
pveam download local debian-13-standard_13.1-2_amd64.tar.zstI initially created 101 with a static IP, then later cloned/migrated to 361.
# Optional: find next available VMID
pvesh get /cluster/nextid
# Generate and store initial root password
PW=$(openssl rand -base64 24)
printf '%s\n' "$PW" > /root/openclaw-ct101-password.txt
chmod 600 /root/openclaw-ct101-password.txt
pct create 101 local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst \
--hostname openclaw \
--password "$PW" \
--cores 2 --memory 2048 --swap 512 \
--rootfs local-lvm:8 \
--net0 name=eth0,bridge=vmbr0,ip=192.168.31.120/24,gw=192.168.31.1 \
--features keyctl=1,nesting=1 \
--unprivileged 1 \
--onboot 1 \
--nameserver 192.168.31.1
pct start 101pct exec 101 -- bash -lc '
apt-get update &&
apt-get install -y ca-certificates curl gnupg git &&
mkdir -p /etc/apt/keyrings &&
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg &&
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" \
> /etc/apt/sources.list.d/nodesource.list &&
apt-get update &&
apt-get install -y nodejs
'pct exec 101 -- bash -lc "npm install -g openclaw@2026.1.29"Create /etc/openclaw/openclaw.env:
GEMINI_API_KEY=<GEMINI_API_KEY>
OPENCLAW_GATEWAY_TOKEN=<RANDOM_TOKEN>
BRAVE_API_KEY=<BRAVE_API_KEY> # added laterPermissions:
install -d -m 700 /etc/openclaw
chmod 600 /etc/openclaw/openclaw.envCreate /root/.openclaw/openclaw.json:
{
"agents": {
"defaults": {
"model": {
"primary": "google/gemini-flash-latest"
}
}
},
"gateway": {
"port": 18789,
"mode": "local",
"bind": "lan",
"auth": {
"mode": "token"
},
"controlUi": {
"allowInsecureAuth": true
}
}
}Why allowInsecureAuth: true?
Because we were exposing HTTP on LAN and needed token-based access without HTTPS/Tailscale at this stage.
Create /etc/systemd/system/openclaw-gateway.service:
[Unit]
Description=OpenClaw Gateway
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
EnvironmentFile=/etc/openclaw/openclaw.env
WorkingDirectory=/root
ExecStart=/usr/bin/openclaw gateway run --bind lan --port 18789 --auth token
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetEnable and start:
systemctl daemon-reload
systemctl enable --now openclaw-gateway.serviceUse token in query string:
http://<LAN_IP>:18789/?token=<OPENCLAW_GATEWAY_TOKEN>
Quick probe from host:
curl -I http://<LAN_IP>:18789Docs reference: https://docs.openclaw.ai/channels/telegram
Update config:
{
"channels": {
"telegram": {
"enabled": true,
"botToken": "<TELEGRAM_BOT_TOKEN>",
"dmPolicy": "pairing"
}
}
}Then restart gateway:
systemctl restart openclaw-gateway.serviceIf using pairing mode:
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>OpenClaw web search uses BRAVE_API_KEY in /etc/openclaw/openclaw.env.
After adding/updating key:
systemctl restart openclaw-gateway.servicenpm install -g @google/gemini-cliopenclaw plugins enable google-gemini-cli-auth
systemctl restart openclaw-gateway.service
openclaw models auth login --provider google-gemini-cli --method oauthIn remote/VPS mode, OpenClaw prints a login URL. You:
- Open it locally
- Sign in with Google
- Paste the callback URL (
http://localhost:8085/oauth2callback?...) back into the prompt
The OAuth profile is stored under:
/root/.openclaw/agents/main/agent/auth-profiles.json
Set:
{
"agents": {
"defaults": {
"model": {
"primary": "google-gemini-cli/gemini-3-pro-preview"
},
"models": {
"google-gemini-cli/gemini-3-pro-preview": {}
}
}
}
}Verify:
openclaw models status --plainI switched from static to DHCP/SLAAC by cloning and reconfiguring networking.
pct shutdown 101
pct clone 101 361 --full --hostname openclaw
pct set 361 --net0 name=eth0,bridge=vmbr0,ip=dhcp,ip6=auto
pct start 361Verify addresses:
pct exec 361 -- ip -4 addr show dev eth0
pct exec 361 -- ip -6 addr show dev eth0Remove old container:
pct destroy 101Docs reference: https://docs.openclaw.ai/tools/browser
{
"browser": {
"enabled": true,
"defaultProfile": "openclaw",
"headless": true,
"noSandbox": true
}
}headless: true + noSandbox: true is important for many LXC setups.
apt-get update
apt-get install -y chromium
npm install -g playwrightopenclaw browser start
openclaw browser status --jsonExpected:
running: truecdpReady: truechosenBrowser: chromium
Later, I created 362 and reused the working setup pattern from 361.
# inside 362
apt-get update
apt-get install -y ca-certificates curl gnupg git chromium
mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" \
> /etc/apt/sources.list.d/nodesource.list
apt-get update
apt-get install -y nodejs
npm install -g openclaw@2026.2.9 playwright @google/gemini-cliFrom Proxmox host:
pct exec 361 -- bash -lc "tar -C / -cf - \
root/.openclaw \
etc/openclaw/openclaw.env \
etc/systemd/system/openclaw-gateway.service" > /root/openclaw-361-sync.tar
pct push 362 /root/openclaw-361-sync.tar /root/openclaw-361-sync.tar
pct exec 362 -- bash -lc "tar -C / -xf /root/openclaw-361-sync.tar && rm -f /root/openclaw-361-sync.tar"pct exec 362 -- bash -lc "
systemctl daemon-reload &&
systemctl enable --now openclaw-gateway.service &&
systemctl restart openclaw-gateway.service
"pct exec 362 -- openclaw --version
pct exec 362 -- openclaw models status --plain
pct exec 362 -- systemctl status openclaw-gateway.service
curl -I http://<LXC_362_IP>:18789This is the exact update flow I used later, after 361 had already been running.
pct snapshot 361 pre-openclaw-2026-2-9pct exec 361 -- sh -lc "openclaw update --tag 2026.2.9 --yes"In my run, the package upgrade itself succeeded, but the updater reported a daemon restart issue:
Daemon restart failed: SyntaxError: The requested module './entry.js' does not provide an export named 'ut'
The fix was just a manual service restart.
pct exec 361 -- sh -lc "systemctl restart openclaw-gateway.service"pct exec 361 -- sh -lc "openclaw --version"
pct exec 361 -- sh -lc "systemctl --no-pager --full status openclaw-gateway.service"
pct exec 361 -- sh -lc "openclaw models status --plain"Expected:
- OpenClaw version is
2026.2.9 - Gateway is
active (running) - Model remains the configured default (in this setup:
google-gemini-cli/gemini-3-pro-preview)
pct exec 361 -- sh -lc "npm install -g openclaw@2026.2.9 && systemctl restart openclaw-gateway.service"This captures the later follow-up where 361 moved from 2026.2.9 to 2026.2.12, and Gemini CLI OAuth switched to guituyu38@gmail.com.
pct exec 361 -- sh -lc "openclaw update --tag 2026.2.12 --yes"In this run, package update succeeded, but the updater ended with a service-check warning:
Gateway service check failed: Error: systemctl --user unavailable: Failed to connect to user scope bus via local transport: No such file or directory
As before, a manual service restart fixed runtime state.
pct exec 361 -- sh -lc "systemctl restart openclaw-gateway.service"
pct exec 361 -- sh -lc "openclaw --version"
pct exec 361 -- sh -lc "systemctl --no-pager --full status openclaw-gateway.service"
pct exec 361 -- sh -lc "openclaw models status --plain"Expected:
- OpenClaw version is
2026.2.12 - Gateway is
active (running) - Model remains
google-gemini-cli/gemini-3-pro-preview
Run this from an interactive shell in container 361:
pct enter 361
openclaw models auth login --provider google-gemini-cli --method oauthThen:
- Open the Google URL shown by the CLI in your local browser.
- Sign in as
guituyu38@gmail.com. - Paste the full callback URL (
http://localhost:8085/oauth2callback?...) back into the prompt.
After success, exit container shell:
exitPin auth selection to the new profile:
pct exec 361 -- sh -lc "openclaw models auth order set --provider google-gemini-cli 'google-gemini-cli:guituyu38@gmail.com'"
pct exec 361 -- sh -lc "openclaw models auth order get --provider google-gemini-cli"Remove old profile (yujingzzzz@gmail.com) from auth store:
pct exec 361 -- sh -lc "python3 - <<'PY'
import json
p='/root/.openclaw/agents/main/agent/auth-profiles.json'
with open(p,'r') as f:
data=json.load(f)
profiles=data.setdefault('profiles',{})
profiles.pop('google-gemini-cli:yujingzzzz@gmail.com', None)
data.setdefault('order', {})['google-gemini-cli']=['google-gemini-cli:guituyu38@gmail.com']
with open(p,'w') as f:
json.dump(data,f,indent=2)
f.write('\\n')
PY"Quick verification:
pct exec 361 -- sh -lc "python3 - <<'PY'
import json
p='/root/.openclaw/agents/main/agent/auth-profiles.json'
with open(p,'r') as f:
data=json.load(f)
print(list(data.get('profiles',{}).keys()))
print(data.get('order',{}).get('google-gemini-cli'))
PY"Expected output should only include google-gemini-cli:guituyu38@gmail.com.
This section captures the later upgrade from 2026.2.12 to 2026.2.19, including a Telegram regression fix.
pct exec 361 -- sh -lc 'ts=$(date +%Y%m%d-%H%M%S); \
mkdir -p "/root/.openclaw/backups/$ts" && \
cp /root/.openclaw/openclaw.json "/root/.openclaw/backups/$ts/openclaw.json" && \
cp /root/.openclaw/agents/main/agent/auth-profiles.json "/root/.openclaw/backups/$ts/auth-profiles.json" && \
cp /etc/openclaw/openclaw.env "/root/.openclaw/backups/$ts/openclaw.env" && \
echo "backup_dir=/root/.openclaw/backups/$ts"'I used --no-restart and then restarted systemd manually. This avoids the updater's service-check quirks in this LXC environment.
pct exec 361 -- sh -lc "openclaw update --tag 2026.2.19 --yes --no-restart"
pct exec 361 -- sh -lc "systemctl restart openclaw-gateway.service"pct exec 361 -- sh -lc "openclaw --version"
pct exec 361 -- sh -lc "systemctl --no-pager --full status openclaw-gateway.service"
pct exec 361 -- sh -lc "openclaw update status --json"Expected:
- OpenClaw version is
2026.2.19 - Gateway is
active (running) - Update channel remains
stable
After this upgrade, Telegram startup logged command-sync network failures in this environment (setMyCommands / deleteMyCommands).
The fix was to explicitly set:
channels.telegram.network.autoSelectFamily = false
Apply fix:
pct exec 361 -- sh -lc "python3 - <<'PY'
import json
p='/root/.openclaw/openclaw.json'
with open(p,'r') as f:
cfg=json.load(f)
tele=cfg.setdefault('channels',{}).setdefault('telegram',{})
tele.setdefault('network',{})['autoSelectFamily']=False
with open(p,'w') as f:
json.dump(cfg,f,indent=2)
f.write('\\n')
PY"
pct exec 361 -- sh -lc "systemctl restart openclaw-gateway.service"# Confirm log now shows "autoSelectFamily=false (config)" for Telegram startup
pct exec 361 -- sh -lc "journalctl -u openclaw-gateway.service -n 120 --no-pager"
# Verify Telegram API reachability from inside the container
pct exec 361 -- sh -lc "python3 - <<'PY'
import json, urllib.request
cfg=json.load(open('/root/.openclaw/openclaw.json'))
token=((cfg.get('channels') or {}).get('telegram') or {}).get('botToken')
for method in ('getMe','getWebhookInfo','getMyCommands'):
with urllib.request.urlopen('https://api.telegram.org/bot'+token+'/'+method, timeout=20) as r:
data=json.loads(r.read().decode())
print(method, data.get('ok'))
PY"If all return True, Telegram connectivity is healthy again.
This reproduces the same working node pattern on a fresh Debian 13 container (363), with one key difference:
- Do not install Gemini CLI
- Use OpenRouter with
openrouter/openrouter/freeas the default model
Important distinction:
- "No Gemini CLI" means you do not install
@google/gemini-cliand do not use Gemini CLI OAuth plugin flows. - You can still use Google API models (for example
google/gemini-2.5-flash-lite) withGEMINI_API_KEY.
pct exec 363 -- bash -lc '
apt-get update &&
apt-get install -y ca-certificates curl gnupg git chromium &&
mkdir -p /etc/apt/keyrings &&
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg &&
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" \
> /etc/apt/sources.list.d/nodesource.list &&
apt-get update &&
apt-get install -y nodejs &&
npm install -g openclaw@2026.2.15 playwright
'Verify:
pct exec 363 -- sh -lc "node -v && npm -v"
pct exec 363 -- sh -lc "openclaw --version"pct exec 363 -- bash -lc '
TOKEN=$(openssl rand -hex 24)
install -d -m 700 /etc/openclaw
cat > /etc/openclaw/openclaw.env <<EOF
GEMINI_API_KEY=<GEMINI_API_KEY>
OPENROUTER_API_KEY=<OPENROUTER_API_KEY>
OPENCLAW_GATEWAY_TOKEN=${TOKEN}
BRAVE_API_KEY=<BRAVE_API_KEY>
EOF
chmod 600 /etc/openclaw/openclaw.env
'Use your real OpenRouter key (starts with
sk-or-v1-...).
Keep this file root-only.Keep
GEMINI_API_KEYwhen your primary model is undergoogle/*.
Create /root/.openclaw/openclaw.json:
{
"agents": {
"defaults": {
"model": {
"primary": "openrouter/openrouter/free"
},
"models": {
"openrouter/openrouter/free": {}
}
}
},
"gateway": {
"port": 18789,
"mode": "local",
"bind": "lan",
"auth": {
"mode": "token",
"token": "<OPENCLAW_GATEWAY_TOKEN>"
},
"remote": {
"token": "<OPENCLAW_GATEWAY_TOKEN>"
},
"controlUi": {
"allowInsecureAuth": true
}
},
"channels": {
"telegram": {
"enabled": true,
"botToken": "<TELEGRAM_BOT_TOKEN>",
"dmPolicy": "pairing",
"network": {
"autoSelectFamily": false
}
}
},
"browser": {
"enabled": true,
"defaultProfile": "openclaw",
"headless": true,
"noSandbox": true
}
}If /etc/systemd/system/openclaw-gateway.service does not exist yet on 363, create it (same unit as Step 6):
pct exec 363 -- bash -lc "cat > /etc/systemd/system/openclaw-gateway.service <<'EOF'
[Unit]
Description=OpenClaw Gateway
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
EnvironmentFile=/etc/openclaw/openclaw.env
WorkingDirectory=/root
ExecStart=/usr/bin/openclaw gateway run --bind lan --port 18789 --auth token
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF"Then enable/start/restart:
pct exec 363 -- sh -lc "
systemctl daemon-reload &&
systemctl enable --now openclaw-gateway.service &&
systemctl restart openclaw-gateway.service
"pct exec 363 -- sh -lc "openclaw --version"
pct exec 363 -- sh -lc "systemctl --no-pager --full status openclaw-gateway.service"
pct exec 363 -- sh -lc "openclaw models status --plain"
curl -I http://<LXC_363_IP>:18789Probe model auth from env:
pct exec 363 -- sh -lc "set -a; . /etc/openclaw/openclaw.env; set +a; openclaw models status --probe --json"Expected:
- version is
2026.2.15 - default model is
openrouter/openrouter/free - probe result for provider
openroutershowsstatus: ok
pct exec 363 -- sh -lc "gemini --version"Expected: gemini: not found
If google/gemini-2.5-flash-lite works well for you, this is valid without Gemini CLI.
Use Google API key auth for primary and OpenRouter for fallbacks:
{
"agents": {
"defaults": {
"model": {
"primary": "google/gemini-2.5-flash-lite",
"fallbacks": [
"openrouter/stepfun/step-3.5-flash:free",
"openrouter/openrouter/free"
]
},
"models": {
"google/gemini-2.5-flash-lite": {},
"openrouter/stepfun/step-3.5-flash:free": {},
"openrouter/openrouter/free": {}
}
}
}
}Notes:
- When
agents.defaults.modelsexists, it acts as an allowlist. - Include the primary model and all fallback models in that map.
- This still does not require Gemini CLI installation.
This reproduces the API-key model setup onto a new Debian 13 container (365) and sets:
- Primary model:
google/gemini-3.1-pro-preview - OpenRouter fallbacks for resilience
- Control UI compatibility setting required by
2026.2.26on non-loopback bind
pct exec 365 -- bash -lc '
apt-get update &&
apt-get install -y ca-certificates curl gnupg git chromium &&
mkdir -p /etc/apt/keyrings &&
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg &&
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" \
> /etc/apt/sources.list.d/nodesource.list &&
apt-get update &&
apt-get install -y nodejs &&
npm install -g openclaw@2026.2.26 playwright
'Verify:
pct exec 365 -- sh -lc "node -v && npm -v"
pct exec 365 -- sh -lc "openclaw --version"pct exec 365 -- bash -lc '
TOKEN=$(openssl rand -hex 24)
install -d -m 700 /etc/openclaw
cat > /etc/openclaw/openclaw.env <<EOF
GEMINI_API_KEY=<GEMINI_API_KEY_FROM_363>
OPENROUTER_API_KEY=<OPENROUTER_API_KEY_FROM_363>
OPENCLAW_GATEWAY_TOKEN=${TOKEN}
BRAVE_API_KEY=<BRAVE_API_KEY_FROM_363>
EOF
chmod 600 /etc/openclaw/openclaw.env
'{
"agents": {
"defaults": {
"model": {
"primary": "google/gemini-3.1-pro-preview",
"fallbacks": [
"openrouter/stepfun/step-3.5-flash:free",
"openrouter/arcee-ai/trinity-large-preview:free",
"openrouter/openrouter/free"
]
},
"models": {
"google/gemini-3.1-pro-preview": {},
"google/gemini-2.5-flash-lite": {},
"openrouter/openrouter/free": {},
"openrouter/arcee-ai/trinity-large-preview:free": {},
"openrouter/stepfun/step-3.5-flash:free": {}
}
}
},
"gateway": {
"port": 18789,
"mode": "local",
"bind": "lan",
"auth": {
"mode": "token",
"token": "<OPENCLAW_GATEWAY_TOKEN>"
},
"remote": {
"token": "<OPENCLAW_GATEWAY_TOKEN>"
},
"controlUi": {
"allowInsecureAuth": true,
"dangerouslyAllowHostHeaderOriginFallback": true
}
},
"channels": {
"telegram": {
"enabled": true,
"botToken": "<TELEGRAM_BOT_TOKEN>",
"dmPolicy": "pairing",
"network": {
"autoSelectFamily": false
}
}
},
"browser": {
"enabled": true,
"defaultProfile": "openclaw",
"headless": true,
"noSandbox": true
}
}
dangerouslyAllowHostHeaderOriginFallback: trueis required for this release when Control UI is exposed on non-loopback bind without explicitallowedOrigins.
If /etc/systemd/system/openclaw-gateway.service does not exist yet on 365, create it (same unit as Step 6), then:
pct exec 365 -- sh -lc "
systemctl daemon-reload &&
systemctl enable --now openclaw-gateway.service &&
systemctl restart openclaw-gateway.service
"pct exec 365 -- sh -lc "openclaw --version"
pct exec 365 -- sh -lc "systemctl --no-pager --full status openclaw-gateway.service"
pct exec 365 -- sh -lc "openclaw models status --plain"
pct exec 365 -- sh -lc "set -a; . /etc/openclaw/openclaw.env; set +a; openclaw models status --probe --json"
curl -I http://<LXC_365_IP>:18789Expected:
- version is
2026.2.26 - service is
active (running) - default model is
google/gemini-3.1-pro-preview - providers probe with valid
okstatus for configured keys
In this release line:
https://<LXC_365_IP>:18789fails (port serves plain HTTP, not TLS)http://<LXC_365_IP>:18789may fail browser identity checks in non-secure context
Use HTTPS hostname via reverse proxy/tunnel:
https://<YOUR_HOSTNAME>/?token=<OPENCLAW_GATEWAY_TOKEN>
If UI shows pairing required, approve pending device:
pct exec 365 -- sh -lc "openclaw devices list --json"
pct exec 365 -- sh -lc "openclaw devices approve --latest --json"
pct exec 365 -- sh -lc "openclaw devices list --json"Confirm successful connect:
pct exec 365 -- sh -lc "journalctl -u openclaw-gateway.service -n 120 --no-pager"Look for webchat connected.
If multiple LXCs use the same Telegram bot token simultaneously, one may get:
409 Conflict: terminated by other getUpdates request
Keep only one active poller per token, or use separate bot tokens per LXC.
Typical symptoms:
http://<LAN_IP>:18789/?token=<OPENCLAW_GATEWAY_TOKEN>->control ui requires device identity (use HTTPS or localhost secure context)https://<LAN_IP>:18789/?token=<OPENCLAW_GATEWAY_TOKEN>->ERR_SSL_PROTOCOL_ERROR
This is expected in this release line (:18789 serves plain HTTP, while browser identity checks prefer secure context).
Use HTTPS hostname access (or localhost workflows). Full commands and flow are in Step 19.6.
If two gateways run with the same Telegram bot token (e.g. 361 + 362, or 361 + 363), one will conflict:
Conflict: terminated by other getUpdates request
Fix:
- Run only one active poller for that bot token, or
- Use different bot tokens per instance.
- See Step 19.7 for the same issue in the
365deployment context.
If browser fails to start:
- Ensure
chromiumis installed - Ensure
playwrightis installed - Set
browser.headless: trueandbrowser.noSandbox: true
Symptom in logs right after gateway start:
deleteMyCommands failed: Network request for 'deleteMyCommands' failed!setMyCommands failed: Network request for 'setMyCommands' failed!
Fix used on this node:
- Set
channels.telegram.network.autoSelectFamilytofalsein/root/.openclaw/openclaw.json - Restart
openclaw-gateway.service
On first HTTPS hostname login, the Control UI device can stay pending until explicitly approved.
Use the openclaw devices list/approve --latest workflow and log verification from Step 19.6.
- Keep
/etc/openclaw/openclaw.envmode600. - Treat
OPENCLAW_GATEWAY_TOKEN, Telegram bot tokens, and API keys as secrets. - Prefer private network exposure or Tailscale for remote access.
- Rotate tokens if shared accidentally.
- OpenClaw config:
/root/.openclaw/openclaw.json - OpenClaw env secrets:
/etc/openclaw/openclaw.env - OAuth profiles:
/root/.openclaw/agents/main/agent/auth-profiles.json - Service unit:
/etc/systemd/system/openclaw-gateway.service - Logs:
journalctl -u openclaw-gateway.service -f- OpenClaw runtime logs under
/tmp/openclaw/
Run these after any change:
openclaw --version
openclaw models status --plain
openclaw browser status --json
systemctl is-active openclaw-gateway.service
curl -I http://127.0.0.1:18789If all pass, your OpenClaw node is healthy and ready.