Skip to main content

Fly.io Deployment

Goal: Clawdia Gateway running on a Fly.io machine with persistent storage, automatic HTTPS, and Discord/channel access.

What you need

  • flyctl CLI installed
  • Fly.io account (free tier works)
  • Model auth: Anthropic API key (or other provider keys)
  • Channel credentials: Discord bot token, Telegram token, etc.

Beginner quick path

  1. Clone repo → customize fly.toml
  2. Create app + volume → set secrets
  3. Deploy with fly deploy
  4. SSH in to create config or use Control UI

1) Create the Fly app

Tip: Choose a region close to you. Common options: lhr (London), iad (Virginia), sjc (San Jose).

2) Configure fly.toml

Edit fly.toml to match your app name and requirements:
Key settings:

3) Set secrets

Notes:
  • Non-loopback binds (--bind lan) require CLAWDIA_GATEWAY_TOKEN for security.
  • Treat these tokens like passwords.

4) Deploy

First deploy builds the Docker image (~2-3 minutes). Subsequent deploys are faster. After deployment, verify:
You should see:

5) Create config file

SSH into the machine to create a proper config:
Create the config directory and file:
Note: With CLAWDIA_STATE_DIR=/data, the config path is /data/clawdia.json. Note: The Discord token can come from either:
  • Environment variable: DISCORD_BOT_TOKEN (recommended for secrets)
  • Config file: channels.discord.token
If using env var, no need to add token to config. The gateway reads DISCORD_BOT_TOKEN automatically. Restart to apply:

6) Access the Gateway

Control UI

Open in browser:
Or visit https://my-clawdia.fly.dev/ Paste your gateway token (the one from CLAWDIA_GATEWAY_TOKEN) to authenticate.

Logs

SSH Console

Troubleshooting

”App is not listening on expected address”

The gateway is binding to 127.0.0.1 instead of 0.0.0.0. Fix: Add --bind lan to your process command in fly.toml.

Health checks failing / connection refused

Fly can’t reach the gateway on the configured port. Fix: Ensure internal_port matches the gateway port (set --port 3000 or CLAWDIA_GATEWAY_PORT=3000).

OOM / Memory Issues

Container keeps restarting or getting killed. Signs: SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration, or silent restarts. Fix: Increase memory in fly.toml:
Or update an existing machine:
Note: 512MB is too small. 1GB may work but can OOM under load or with verbose logging. 2GB is recommended.

Gateway Lock Issues

Gateway refuses to start with “already running” errors. This happens when the container restarts but the PID lock file persists on the volume. Fix: Delete the lock file:
The lock file is at /data/gateway.*.lock (not in a subdirectory).

Config Not Being Read

If using --allow-unconfigured, the gateway creates a minimal config. Your custom config at /data/clawdia.json should be read on restart. Verify the config exists:

Writing Config via SSH

The fly ssh console -C command doesn’t support shell redirection. To write a config file:
Note: fly sftp may fail if the file already exists. Delete first:

State Not Persisting

If you lose credentials or sessions after a restart, the state dir is writing to the container filesystem. Fix: Ensure CLAWDIA_STATE_DIR=/data is set in fly.toml and redeploy.

Updates

Updating Machine Command

If you need to change the startup command without a full redeploy:
Note: After fly deploy, the machine command may reset to what’s in fly.toml. If you made manual changes, re-apply them after deploy.

Notes

  • Fly.io uses x86 architecture (not ARM)
  • The Dockerfile is compatible with both architectures
  • For WhatsApp/Telegram onboarding, use fly ssh console
  • Persistent data lives on the volume at /data
  • Signal requires Java + signal-cli; use a custom image and keep memory at 2GB+.

Cost

With the recommended config (shared-cpu-2x, 2GB RAM):
  • ~$10-15/month depending on usage
  • Free tier includes some allowance
See Fly.io pricing for details.