Deploy Moltbot To Fly
Deploy Moltbot to Fly.io with persistent storage, secure token authentication, environment secrets, and approved device pairing for web UI access.
Deploy Moltbot to Fly.io with persistent storage, secure token authentication, environment secrets, and approved device pairing for web UI access.
Real data. Real impact.
Emerging
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
Deploy Moltbot (Clawdbot) to Fly.io with proper configuration, persistent storage, and device pairing.
Deploying Moltbot to Fly.io requires:
Before starting:
brew install flyctl or curl -L https://fly.io/install.sh | sh)fly auth login)git clone https://github.com/clawdbot/clawdbot.git moltbot-deploy cd moltbot-deploy
Generate a secure token for authentication:
openssl rand -hex 32
IMPORTANT: Save this token - you'll need it for:
Create
fly.toml with the correct configuration:
app = 'your-app-name' primary_region = 'iad'[build] dockerfile = 'Dockerfile'
[env] NODE_ENV = 'production' CLAWDBOT_PREFER_PNPM = '1' CLAWDBOT_STATE_DIR = '/data' NODE_OPTIONS = '--max-old-space-size=1536'
[processes] app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"
[http_service] internal_port = 3000 force_https = true auto_stop_machines = false auto_start_machines = true min_machines_running = 1 processes = ["app"]
[[vm]] size = 'shared-cpu-2x' memory = '2048mb'
[mounts] source = 'moltbot_data' destination = '/data'
CRITICAL Settings:
CLAWDBOT_STATE_DIR = '/data' - Required for proper config persistence--bind lan - Allows Fly's proxy to reach the gatewayhttp_service - Newer Fly format (not [[services]])memory = '2048mb' - 512MB is too small; 2GB recommendedfly apps create your-app-name fly volumes create moltbot_data --region iad --size 1 -a your-app-name -y
Choose a region close to you:
iad - Virginia (US East)lhr - Londonsjc - San Jose (US West)# Set your generated token fly secrets set CLAWDBOT_GATEWAY_TOKEN="YOUR-TOKEN-HERE" -a your-app-nameSet API keys
fly secrets set ANTHROPIC_API_KEY="sk-ant-xxxxx" -a your-app-name fly secrets set OPENAI_API_KEY="sk-xxxxx" -a your-app-name # Optional
Note: Secrets are deployed on first
fly deploy, not immediately.
Deploy the application:
fly deploy -a your-app-name
First deployment takes ~3-5 minutes (building Docker image).
Wait for gateway to start:
fly logs -a your-app-name --no-tail | grep "listening on"
You should see:
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
CRITICAL: The config file must include the same token as the env var for authentication to work.
fly ssh console -a your-app-name
cat > /data/moltbot.json << 'EOF' { "gateway": { "mode": "local", "bind": "lan", "auth": { "mode": "token", "token": "YOUR-TOKEN-HERE" } }, "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-5" } } }, "auth": { "profiles": { "anthropic:default": { "mode": "token", "provider": "anthropic" } } } } EOF
Replace
with your actual token!YOUR-TOKEN-HERE
exit fly machine restart <machine-id> -a your-app-name
Get machine ID with:
fly machines list -a your-app-name
DNS may take 2-5 minutes to propagate. Check status:
nslookup your-app-name.fly.dev 8.8.8.8
If DNS isn't resolving on your machine, flush your DNS cache:
macOS:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
Linux:
sudo systemd-resolve --flush-caches
Open in browser with the tokenized URL:
https://your-app-name.fly.dev/?token=YOUR-TOKEN-HERE
You'll see "disconnected (1008): pairing required" - this is normal!
While the browser is open and attempting to connect, approve the pairing:
fly ssh console -a your-app-name
Then run:
node -e " const fs = require('fs'); const pending = JSON.parse(fs.readFileSync('/data/devices/pending.json')); const paired = JSON.parse(fs.readFileSync('/data/devices/paired.json') || '{}'); const requestId = Object.keys(pending)[0]; if (requestId) { const device = pending[requestId]; paired[device.deviceId] = { deviceId: device.deviceId, publicKey: device.publicKey, platform: device.platform, clientId: device.clientId, role: device.role, roles: device.roles, scopes: device.scopes, approvedAt: Date.now(), approvedBy: 'cli' }; delete pending[requestId]; fs.writeFileSync('/data/devices/pending.json', JSON.stringify(pending, null, 2)); fs.writeFileSync('/data/devices/paired.json', JSON.stringify(paired, null, 2)); console.log('Approved device:', device.deviceId); } else { console.log('No pending devices'); } "
After approval, refresh your browser. You should now be connected! 🎉
Symptoms:
unauthorized: gateway token mismatch
Fix: Token in config file must match the env var:
# Check env var token fly ssh console -a your-app-name -C "printenv CLAWDBOT_GATEWAY_TOKEN"Update config file to match
fly ssh console -a your-app-name
Edit /data/moltbot.json and update gateway.auth.token
Symptoms:
instance refused connection or not listening on expected address
Fix: Ensure
--bind lan in fly.toml and gateway is fully started:
fly logs -a your-app-name --no-tail | tail -50
Wait 30-60 seconds after deploy for gateway to initialize.
Symptoms:
Could not resolve host
Fix:
8.8.8.8 or 1.1.1.1Symptoms: Gateway exits with "Invalid input" or validation errors
Fix: Check config syntax:
fly ssh console -a your-app-name -C "cat /data/moltbot.json"
Common issues:
auth.mode: Only "token" is valid (not "off")Symptoms: Config/devices reset after restart
Fix: Ensure
CLAWDBOT_STATE_DIR=/data is set in fly.toml [env] section.
Symptoms: Machine keeps restarting or won't stabilize
Nuclear option (fastest):
fly apps destroy your-app-name -y # Then re-run Phase 2 onwards with fresh setup
If you see proxy warnings in logs, add trusted proxies:
fly ssh console -a your-app-name
node -e " const fs = require('fs'); const config = JSON.parse(fs.readFileSync('/data/moltbot.json')); config.gateway.trustedProxies = [ '172.16.0.0/12', '10.0.0.0/8' ]; fs.writeFileSync('/data/moltbot.json', JSON.stringify(config, null, 2)); console.log('Trusted proxies configured'); "
Restart machine after changes.
# Check status fly status -a APPView logs
fly logs -a APP --no-tail | tail -50
SSH into machine
fly ssh console -a APP
Restart machine
fly machines list -a APP # Get machine ID fly machine restart <machine-id> -a APP
Check secrets
fly secrets list -a APP
Get gateway token
fly ssh console -a APP -C "printenv CLAWDBOT_GATEWAY_TOKEN"
Redeploy
fly deploy -a APP
To update Moltbot:
cd moltbot-deploy git pull fly deploy -a your-app-name
Config and paired devices persist on the volume across updates.
CLAWDBOT_STATE_DIR=/data is critical - without it, config location is wronghttp_service not [[services]] (newer Fly format)No automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.