9.1 KiB
OpenClaw on TrueNAS SCALE
Self-hosted AI agent gateway that connects LLMs to messaging platforms (Telegram, Discord, WhatsApp). Runs as a persistent daemon — can message proactively, execute shell commands, manage files, and automate tasks.
- Previously known as: ClawdBot, MoltBot
- GitHub: https://github.com/openclaw/openclaw
- Docs: https://docs.openclaw.ai
Prerequisites
- TrueNAS SCALE (24.10 Electric Eel or newer recommended — native Docker support)
- Dockge running on TrueNAS for Docker Compose management
- A dataset for OpenClaw storage:
tank/configs/openclaw - NanoGPT API key from https://nano-gpt.com (or OpenRouter key from https://openrouter.ai)
- Telegram bot token from @BotFather
1. Create Storage Datasets
In TrueNAS web UI, create two datasets under your apps pool:
tank/configs/openclaw/config # maps to ~/.openclaw
tank/configs/openclaw/workspace # maps to ~/openclaw/workspace
Set permissions to UID 1000 (the container runs as node uid 1000):
sudo chown -R 1000:1000 /mnt/tank/configs/openclaw/config
sudo chown -R 1000:1000 /mnt/tank/configs/openclaw/workspace
Important: If you skip this step, onboarding will fail with
EACCES: permission deniedwhen writingopenclaw.json.
2. Create the Telegram Bot
- Open Telegram, search for
@BotFather - Send
/newbot - Choose a name and username (username must end in
bot) - Save the bot token (format:
123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
3. Deploy via Dockge
In Dockge, create a new stack called openclaw.
Compose YAML
Two services are required: openclaw-gateway runs the persistent gateway, and openclaw-cli is used for one-off CLI commands (onboarding, channel setup, diagnostics). The cli profile prevents it from starting automatically.
services:
openclaw-gateway:
image: ghcr.io/openclaw/openclaw:latest
container_name: openclaw
restart: unless-stopped
ports:
- "18789:18789"
volumes:
- /mnt/tank/configs/openclaw/config:/home/node/.openclaw
- /mnt/tank/configs/openclaw/workspace:/home/node/workspace
environment:
- NANO_GPT_API_KEY=${NANO_GPT_API_KEY}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
command: ["node", "openclaw.mjs", "gateway", "--allow-unconfigured", "--bind", "lan"]
openclaw-cli:
image: ghcr.io/openclaw/openclaw:latest
volumes:
- /mnt/tank/configs/openclaw/config:/home/node/.openclaw
- /mnt/tank/configs/openclaw/workspace:/home/node/workspace
environment:
- NANO_GPT_API_KEY=${NANO_GPT_API_KEY}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
entrypoint: ["node", "openclaw.mjs"]
profiles:
- cli
Why two services? The Docker image's default entrypoint runs
node openclaw.mjs gateway. If you try to run CLI commands (likeonboard) via the gateway service, it fails withCannot find module '/app/onboard'because the entrypoint tries to execute the argument as a standalone script. Theopenclaw-cliservice overridesentrypointto["node", "openclaw.mjs"]so subcommands work correctly.
Why
--bind lan? The gateway defaults to binding on127.0.0.1(loopback) inside the container. Docker port mapping requires the process to listen on0.0.0.0, so--bind lanis mandatory for the port forwarding to work.
Environment Variables
In the Dockge .env section, add:
NANO_GPT_API_KEY=your-nanogpt-key-here
OPENROUTER_API_KEY=your-openrouter-key-here
First Run
Before starting the stack normally, run the onboarding wizard via SSH:
cd /mnt/tank/stacks/openclaw
sudo docker compose run --rm openclaw-cli onboard --no-install-daemon
The --no-install-daemon flag is required in Docker since the gateway runs as a separate container, not as a system daemon.
After onboarding completes, start the stack from the Dockge UI (or sudo docker compose up -d openclaw-gateway).
4. Configure OpenClaw
After the container is running, the config file lives at:
/mnt/tank/configs/openclaw/config/openclaw.json
The onboarding wizard writes this file. Key settings to verify:
gateway.bindshould be"lan"(not"loopback")gateway.auth.modeshould be"token"with a generated tokenchannels.telegram.enabledshould betrue
NanoGPT as Provider (OpenAI-compatible)
NanoGPT exposes an OpenAI-compatible API at https://nano-gpt.com/api/v1. Configure it as a custom provider:
{
"agents": {
"defaults": {
"model": {
"primary": "nanogpt/claude-sonnet-4.5",
"fallbacks": ["openrouter/anthropic/claude-sonnet-4.5"]
}
}
},
"env": {
"NANO_GPT_API_KEY": "your-nanogpt-key",
"OPENROUTER_API_KEY": "sk-or-your-openrouter-key"
}
}
Note: If NanoGPT is not natively supported as a provider, configure it as a custom provider with base URL
https://nano-gpt.com/api/v1. Check the custom providers docs for exact syntax.
OpenRouter as Provider (alternative)
{
"agents": {
"defaults": {
"model": {
"primary": "openrouter/anthropic/claude-sonnet-4.5"
}
}
},
"env": {
"OPENROUTER_API_KEY": "sk-or-your-key"
}
}
5. Connect Telegram
From SSH on TrueNAS, use the CLI service:
cd /mnt/tank/stacks/openclaw
sudo docker compose run --rm openclaw-cli channels add --channel telegram --token "YOUR_BOT_TOKEN"
Then approve the pairing. Send a message to your bot in Telegram — it will reply with a pairing code. Approve it:
sudo docker compose run --rm openclaw-cli pairing approve telegram <CODE>
6. Access the Control UI
The Control UI requires HTTPS or localhost (browser secure context requirement). Direct access via LAN IP will not work.
Step 1: SSH tunnel
ssh -L 18789:localhost:18789 truenas_admin@192.168.178.189
Step 2: Get the dashboard URL with token
The gateway uses token-based authentication. The token is embedded in the URL fragment (#token=...). Get the full URL:
cd /mnt/tank/stacks/openclaw
sudo docker compose run --rm openclaw-cli dashboard --no-open
This prints a URL like:
http://172.16.10.3:18789/#token=your-gateway-token-here
Step 3: Open in browser
Replace the IP with localhost and open:
http://localhost:18789/#token=your-gateway-token-here
Do not access via
http://192.168.178.189:18789directly — the gateway rejects non-localhost, non-HTTPS WebSocket connections withcode=4008 reason=connect failed.
7. Verify
- Check gateway status:
sudo docker compose run --rm openclaw-cli gateway status - View logs:
sudo docker logs -f openclaw - Run diagnostics:
sudo docker compose run --rm openclaw-cli doctor
8. Security Considerations
- Do not expose port 18789 to the public internet. Use Tailscale, WireGuard, or VPN to access the Control UI remotely.
- Enable explicit consent mode to require approval before OpenClaw executes write/exec commands.
- Treat the
/mnt/tank/configs/openclaw/configdirectory as sensitive — it contains API keys and session data. - The container runs as non-root (uid 1000), which is good practice.
- Consider network isolation: create a dedicated Docker network or VLAN if your TrueNAS hosts other services.
Useful Commands
All CLI commands below assume you are in /mnt/tank/stacks/openclaw.
| Command | Description |
|---|---|
sudo docker compose run --rm openclaw-cli gateway status |
Check if gateway is running |
sudo docker compose restart openclaw-gateway |
Restart the gateway |
sudo docker compose run --rm openclaw-cli doctor |
Automated health checks |
sudo docker compose run --rm openclaw-cli dashboard --no-open |
Get Control UI URL with token |
sudo docker logs -f openclaw |
Stream live logs |
sudo docker compose run --rm openclaw-cli channels list |
List connected channels |
sudo docker compose pull && sudo docker compose up -d openclaw-gateway |
Update to latest version |
Troubleshooting
Cannot find module '/app/onboard': You ran a CLI subcommand via the gateway service. Useopenclaw-cliservice instead (it has the correct entrypoint).EACCES: permission deniedon config files: Host directories not owned by UID 1000. Runsudo chown -R 1000:1000 /mnt/tank/configs/openclaw/config.Bind: loopbackin doctor output: The onboarding wizard set bind to loopback in the config file, overriding the--bind lancommand flag. Editopenclaw.jsonand setgateway.bindto"lan", then restart the gateway.- Browser shows "connection reset" or blank page: You are accessing via LAN IP instead of localhost. Use the SSH tunnel and open
http://localhost:18789/#token=.... code=4008 reason=connect failedin logs: The browser is connecting without the required token or via a non-secure origin. Get the full URL withdashboard --no-open.- Gateway Bridge errors: Try
network_mode: hostin the compose file if bridge networking causes issues. - Container won't start: Check
sudo docker logs openclawfor config validation errors — OpenClaw rejects malformed JSON5.