{
  "title": "Channel tokens",
  "content": "fly secrets set DISCORD_BOT_TOKEN=MTQ...\nbash theme={null}\nfly deploy\nbash theme={null}\nfly status\nfly logs\n\n[gateway] listening on ws://0.0.0.0:3000 (PID xxx)\n[discord] logged in to discord as xxx\nbash theme={null}\nfly ssh console\nbash theme={null}\nmkdir -p /data\ncat > /data/openclaw.json << 'EOF'\n{\n  \"agents\": {\n    \"defaults\": {\n      \"model\": {\n        \"primary\": \"anthropic/claude-opus-4-5\",\n        \"fallbacks\": [\"anthropic/claude-sonnet-4-5\", \"openai/gpt-4o\"]\n      },\n      \"maxConcurrent\": 4\n    },\n    \"list\": [\n      {\n        \"id\": \"main\",\n        \"default\": true\n      }\n    ]\n  },\n  \"auth\": {\n    \"profiles\": {\n      \"anthropic:default\": { \"mode\": \"token\", \"provider\": \"anthropic\" },\n      \"openai:default\": { \"mode\": \"token\", \"provider\": \"openai\" }\n    }\n  },\n  \"bindings\": [\n    {\n      \"agentId\": \"main\",\n      \"match\": { \"channel\": \"discord\" }\n    }\n  ],\n  \"channels\": {\n    \"discord\": {\n      \"enabled\": true,\n      \"groupPolicy\": \"allowlist\",\n      \"guilds\": {\n        \"YOUR_GUILD_ID\": {\n          \"channels\": { \"general\": { \"allow\": true } },\n          \"requireMention\": false\n        }\n      }\n    }\n  },\n  \"gateway\": {\n    \"mode\": \"local\",\n    \"bind\": \"auto\"\n  },\n  \"meta\": {\n    \"lastTouchedVersion\": \"2026.1.29\"\n  }\n}\nEOF\nbash theme={null}\nexit\nfly machine restart <machine-id>\nbash theme={null}\nfly open\nbash theme={null}\nfly logs              # Live logs\nfly logs --no-tail    # Recent logs\nbash theme={null}\nfly ssh console\ntoml theme={null}\n[[vm]]\n  memory = \"2048mb\"\nbash theme={null}\nfly machine update <machine-id> --vm-memory 2048 -y\nbash theme={null}\nfly ssh console --command \"rm -f /data/gateway.*.lock\"\nfly machine restart <machine-id>\nbash theme={null}\nfly ssh console --command \"cat /data/openclaw.json\"\nbash theme={null}",
  "code_samples": [
    {
      "code": "**Notes:**\n\n* Non-loopback binds (`--bind lan`) require `OPENCLAW_GATEWAY_TOKEN` for security.\n* Treat these tokens like passwords.\n* **Prefer env vars over config file** for all API keys and tokens. This keeps secrets out of `openclaw.json` where they could be accidentally exposed or logged.\n\n## 4) Deploy",
      "language": "unknown"
    },
    {
      "code": "First deploy builds the Docker image (\\~2-3 minutes). Subsequent deploys are faster.\n\nAfter deployment, verify:",
      "language": "unknown"
    },
    {
      "code": "You should see:",
      "language": "unknown"
    },
    {
      "code": "## 5) Create config file\n\nSSH into the machine to create a proper config:",
      "language": "unknown"
    },
    {
      "code": "Create the config directory and file:",
      "language": "unknown"
    },
    {
      "code": "**Note:** With `OPENCLAW_STATE_DIR=/data`, the config path is `/data/openclaw.json`.\n\n**Note:** The Discord token can come from either:\n\n* Environment variable: `DISCORD_BOT_TOKEN` (recommended for secrets)\n* Config file: `channels.discord.token`\n\nIf using env var, no need to add token to config. The gateway reads `DISCORD_BOT_TOKEN` automatically.\n\nRestart to apply:",
      "language": "unknown"
    },
    {
      "code": "## 6) Access the Gateway\n\n### Control UI\n\nOpen in browser:",
      "language": "unknown"
    },
    {
      "code": "Or visit `https://my-openclaw.fly.dev/`\n\nPaste your gateway token (the one from `OPENCLAW_GATEWAY_TOKEN`) to authenticate.\n\n### Logs",
      "language": "unknown"
    },
    {
      "code": "### SSH Console",
      "language": "unknown"
    },
    {
      "code": "## Troubleshooting\n\n### \"App is not listening on expected address\"\n\nThe gateway is binding to `127.0.0.1` instead of `0.0.0.0`.\n\n**Fix:** Add `--bind lan` to your process command in `fly.toml`.\n\n### Health checks failing / connection refused\n\nFly can't reach the gateway on the configured port.\n\n**Fix:** Ensure `internal_port` matches the gateway port (set `--port 3000` or `OPENCLAW_GATEWAY_PORT=3000`).\n\n### OOM / Memory Issues\n\nContainer keeps restarting or getting killed. Signs: `SIGABRT`, `v8::internal::Runtime_AllocateInYoungGeneration`, or silent restarts.\n\n**Fix:** Increase memory in `fly.toml`:",
      "language": "unknown"
    },
    {
      "code": "Or update an existing machine:",
      "language": "unknown"
    },
    {
      "code": "**Note:** 512MB is too small. 1GB may work but can OOM under load or with verbose logging. **2GB is recommended.**\n\n### Gateway Lock Issues\n\nGateway refuses to start with \"already running\" errors.\n\nThis happens when the container restarts but the PID lock file persists on the volume.\n\n**Fix:** Delete the lock file:",
      "language": "unknown"
    },
    {
      "code": "The lock file is at `/data/gateway.*.lock` (not in a subdirectory).\n\n### Config Not Being Read\n\nIf using `--allow-unconfigured`, the gateway creates a minimal config. Your custom config at `/data/openclaw.json` should be read on restart.\n\nVerify the config exists:",
      "language": "unknown"
    },
    {
      "code": "### Writing Config via SSH\n\nThe `fly ssh console -C` command doesn't support shell redirection. To write a config file:",
      "language": "unknown"
    }
  ],
  "headings": [
    {
      "level": "h2",
      "text": "4) Deploy",
      "id": "4)-deploy"
    },
    {
      "level": "h2",
      "text": "5) Create config file",
      "id": "5)-create-config-file"
    },
    {
      "level": "h2",
      "text": "6) Access the Gateway",
      "id": "6)-access-the-gateway"
    },
    {
      "level": "h3",
      "text": "Control UI",
      "id": "control-ui"
    },
    {
      "level": "h3",
      "text": "Logs",
      "id": "logs"
    },
    {
      "level": "h3",
      "text": "SSH Console",
      "id": "ssh-console"
    },
    {
      "level": "h2",
      "text": "Troubleshooting",
      "id": "troubleshooting"
    },
    {
      "level": "h3",
      "text": "\"App is not listening on expected address\"",
      "id": "\"app-is-not-listening-on-expected-address\""
    },
    {
      "level": "h3",
      "text": "Health checks failing / connection refused",
      "id": "health-checks-failing-/-connection-refused"
    },
    {
      "level": "h3",
      "text": "OOM / Memory Issues",
      "id": "oom-/-memory-issues"
    },
    {
      "level": "h3",
      "text": "Gateway Lock Issues",
      "id": "gateway-lock-issues"
    },
    {
      "level": "h3",
      "text": "Config Not Being Read",
      "id": "config-not-being-read"
    },
    {
      "level": "h3",
      "text": "Writing Config via SSH",
      "id": "writing-config-via-ssh"
    }
  ],
  "url": "llms-txt#channel-tokens",
  "links": []
}