Fly.io Deployment
Ziel: OpenClaw Gateway läuft auf einer Fly.io Machine mit persistentem Speicher, automatischem HTTPS und Discord/Channel-Zugriff.
Was du brauchst
- flyctl CLI installiert
- Fly.io Account (Free Tier reicht)
- Model Auth: Anthropic API Key (oder andere Provider Keys)
- Channel Credentials: Discord Bot Token, Telegram Token, etc.
Schnelleinstieg für Anfänger
- Repo clonen →
fly.tomlanpassen - App + Volume erstellen → Secrets setzen
- Mit
fly deploydeployen - Per SSH Config erstellen oder Control UI nutzen
1) Fly App erstellen
# Repo clonen
git clone https://github.com/openclaw/openclaw.git
cd openclaw
# Neue Fly App erstellen (wähle deinen eigenen Namen)
fly apps create my-openclaw
# Persistentes Volume erstellen (1GB reicht normalerweise)
fly volumes create openclaw_data --size 1 --region iad
Tipp: Wähle eine Region in deiner Nähe. Gängige Optionen: lhr (London), iad (Virginia), sjc (San Jose).
2) fly.toml konfigurieren
Bearbeite fly.toml und passe App-Name und Anforderungen an.
Sicherheitshinweis: Die Standard-Config macht dein Gateway öffentlich erreichbar. Für ein abgesichertes Deployment ohne öffentliche IP siehe Private Deployment oder nutze fly.private.toml.
app = "my-openclaw" # Dein App-Name
primary_region = "iad"
[build]
dockerfile = "Dockerfile"
[env]
NODE_ENV = "production"
OPENCLAW_PREFER_PNPM = "1"
OPENCLAW_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 = "openclaw_data"
destination = "/data"
Wichtige Einstellungen:
| Einstellung | Warum |
|---|---|
--bind lan | Bindet an 0.0.0.0, damit Fly’s Proxy das Gateway erreichen kann |
--allow-unconfigured | Startet ohne Config-Datei (die erstellst du später) |
internal_port = 3000 | Muss mit --port 3000 (oder OPENCLAW_GATEWAY_PORT) für Fly Health Checks passen |
memory = "2048mb" | 512MB ist zu wenig; 2GB empfohlen |
OPENCLAW_STATE_DIR = "/data" | Speichert State persistent auf dem Volume |
3) Secrets setzen
# Erforderlich: Gateway Token (für Non-Loopback Binding)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)
# Model Provider API Keys
fly secrets set ANTHROPIC_API_KEY=sk-ant-...
# Optional: Andere Provider
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...
# Channel Tokens
fly secrets set DISCORD_BOT_TOKEN=MTQ...
Hinweise:
- Non-Loopback Binds (
--bind lan) benötigenOPENCLAW_GATEWAY_TOKENaus Sicherheitsgründen. - Behandle diese Tokens wie Passwörter.
- Nutze Umgebungsvariablen statt Config-Datei für alle API Keys und Tokens. So bleiben Secrets aus
openclaw.jsonraus, wo sie versehentlich exponiert oder geloggt werden könnten.
4) Deployen
fly deploy
Beim ersten Deploy wird das Docker Image gebaut (~2-3 Minuten). Spätere Deploys gehen schneller.
Nach dem Deployment prüfen:
fly status
fly logs
Du solltest sehen:
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx
5) Config-Datei erstellen
Per SSH auf die Machine verbinden und eine richtige Config erstellen:
fly ssh console
Config-Verzeichnis und -Datei erstellen:
mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-opus-4-5",
"fallbacks": ["anthropic/claude-sonnet-4-5", "openai/gpt-4o"]
},
"maxConcurrent": 4
},
"list": [
{
"id": "main",
"default": true
}
]
},
"auth": {
"profiles": {
"anthropic:default": { "mode": "token", "provider": "anthropic" },
"openai:default": { "mode": "token", "provider": "openai" }
}
},
"bindings": [
{
"agentId": "main",
"match": { "channel": "discord" }
}
],
"channels": {
"discord": {
"enabled": true,
"groupPolicy": "allowlist",
"guilds": {
"YOUR_GUILD_ID": {
"channels": { "general": { "allow": true } },
"requireMention": false
}
}
}
},
"gateway": {
"mode": "local",
"bind": "auto"
},
"meta": {
"lastTouchedVersion": "2026.1.29"
}
}
EOF
Hinweis: Mit OPENCLAW_STATE_DIR=/data liegt die Config unter /data/openclaw.json.
Hinweis: Der Discord Token kann aus zwei Quellen kommen:
- Umgebungsvariable:
DISCORD_BOT_TOKEN(empfohlen für Secrets) - Config-Datei:
channels.discord.token
Wenn du die Umgebungsvariable nutzt, brauchst du den Token nicht in die Config einzutragen. Das Gateway liest DISCORD_BOT_TOKEN automatisch.
Neustart zum Anwenden:
exit
fly machine restart <machine-id>
6) Gateway aufrufen
Control UI
Im Browser öffnen:
fly open
Oder besuche https://my-openclaw.fly.dev/
Füge deinen Gateway Token (den aus OPENCLAW_GATEWAY_TOKEN) ein, um dich zu authentifizieren.
Logs
fly logs # Live Logs
fly logs --no-tail # Letzte Logs
SSH Console
fly ssh console
Troubleshooting
”App is not listening on expected address”
Das Gateway bindet an 127.0.0.1 statt an 0.0.0.0.
Fix: Füge --bind lan zum Process-Command in fly.toml hinzu.
Health Checks schlagen fehl / Connection refused
Fly kann das Gateway auf dem konfigurierten Port nicht erreichen.
Fix: Stelle sicher, dass internal_port mit dem Gateway Port übereinstimmt (setze --port 3000 oder OPENCLAW_GATEWAY_PORT=3000).
OOM / Memory Issues
Container startet ständig neu oder wird gekillt. Anzeichen: SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration, oder stille Neustarts.
Fix: Erhöhe den Speicher in fly.toml:
[[vm]]
memory = "2048mb"
Oder update eine bestehende Machine:
fly machine update <machine-id> --vm-memory 2048 -y
Hinweis: 512MB ist zu wenig. 1GB kann funktionieren, aber bei Last oder verbose Logging zu OOM führen. 2GB ist empfohlen.
Gateway Lock Issues
Gateway verweigert den Start mit “already running” Fehlern.
Das passiert, wenn der Container neu startet, aber die PID Lock-Datei auf dem Volume bestehen bleibt.
Fix: Lösche die Lock-Datei:
fly ssh console --command "rm -f /data/gateway.*.lock"
fly machine restart <machine-id>
Die Lock-Datei liegt unter /data/gateway.*.lock (nicht in einem Unterverzeichnis).
Config wird nicht gelesen
Bei --allow-unconfigured erstellt das Gateway eine minimale Config. Deine eigene Config unter /data/openclaw.json sollte beim Neustart gelesen werden.
Prüfe, ob die Config existiert:
fly ssh console --command "cat /data/openclaw.json"
Config per SSH schreiben
Der Befehl fly ssh console -C unterstützt keine Shell-Redirection. Um eine Config-Datei zu schreiben:
# echo + tee nutzen (pipe von lokal zu remote)
echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"
# Oder sftp nutzen
fly sftp shell
> put /local/path/config.json /data/openclaw.json
Hinweis: fly sftp kann fehlschlagen, wenn die Datei bereits existiert. Erst löschen:
fly ssh console --command "rm /data/openclaw.json"
State wird nicht persistent gespeichert
Wenn du Credentials oder Sessions nach einem Neustart verlierst, schreibt das State-Verzeichnis ins Container-Dateisystem.
Fix: Stelle sicher, dass OPENCLAW_STATE_DIR=/data in fly.toml gesetzt ist und deploye neu.
Updates
# Neueste Änderungen pullen
git pull
# Neu deployen
fly deploy
# Health checken
fly status
fly logs
Machine Command updaten
Wenn du den Startup-Command ohne vollständiges Redeploy ändern musst:
# Machine ID holen
fly machines list
# Command updaten
fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y
# Oder mit Memory-Erhöhung
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y
Hinweis: Nach fly deploy kann der Machine Command auf das zurückgesetzt werden, was in fly.toml steht. Wenn du manuelle Änderungen gemacht hast, wende sie nach dem Deploy erneut an.
Private Deployment (Hardened)
Standardmäßig vergibt Fly öffentliche IPs, wodurch dein Gateway unter https://your-app.fly.dev erreichbar ist. Das ist praktisch, bedeutet aber auch, dass dein Deployment von Internet-Scannern (Shodan, Censys, etc.) gefunden werden kann.
Für ein abgesichertes Deployment ohne öffentliche Erreichbarkeit nutze das Private Template.
Wann Private Deployment nutzen
- Du machst nur ausgehende Calls/Nachrichten (keine eingehenden Webhooks)
- Du nutzt ngrok oder Tailscale Tunnel für Webhook-Callbacks
- Du greifst auf das Gateway per SSH, Proxy oder WireGuard statt Browser zu
- Du willst das Deployment vor Internet-Scannern verstecken
Setup
Nutze fly.private.toml statt der Standard-Config:
# Mit Private Config deployen
fly deploy -c fly.private.toml
Oder konvertiere ein bestehendes Deployment:
# Aktuelle IPs auflisten
fly ips list -a my-openclaw
# Öffentliche IPs freigeben
fly ips release <public-ipv4> -a my-openclaw
fly ips release <public-ipv6> -a my-openclaw
# Zu Private Config wechseln, damit zukünftige Deploys keine öffentlichen IPs neu vergeben
# (entferne [http_service] oder deploye mit dem Private Template)
fly deploy -c fly.private.toml
# Private-Only IPv6 zuweisen
fly ips allocate-v6 --private -a my-openclaw
Danach sollte fly ips list nur noch eine IP vom Typ private zeigen:
VERSION IP TYPE REGION
v6 fdaa:x:x:x:x::x private global
Private Deployment aufrufen
Da es keine öffentliche URL gibt, nutze eine dieser Methoden:
Option 1: Local Proxy (am einfachsten)
# Lokalen Port 3000 zur App forwarden
fly proxy 3000:3000 -a my-openclaw
# Dann http://localhost:3000 im Browser öffnen
Option 2: WireGuard VPN
# WireGuard Config erstellen (einmalig)
fly wireguard create
# In WireGuard Client importieren, dann per interner IPv6 zugreifen
# Beispiel: http://[fdaa:x:x:x:x::x]:3000
Option 3: Nur SSH
fly ssh console -a my-openclaw
Webhooks mit Private Deployment
Wenn du Webhook-Callbacks (Twilio, Telnyx, etc.) ohne öffentliche Erreichbarkeit brauchst:
- ngrok Tunnel - ngrok im Container oder als Sidecar laufen lassen
- Tailscale Funnel - Bestimmte Pfade per Tailscale exponieren
- Nur ausgehend - Manche Provider (Twilio) funktionieren für ausgehende Calls auch ohne Webhooks
Beispiel Voice-Call Config mit ngrok:
{
"plugins": {
"entries": {
"voice-call": {
"enabled": true,
"config": {
"provider": "twilio",
"tunnel": { "provider": "ngrok" }
}
}
}
}
}
Der ngrok Tunnel läuft im Container und stellt eine öffentliche Webhook-URL bereit, ohne die Fly App selbst zu exponieren.
Sicherheitsvorteile
| Aspekt | Public | Private |
|---|---|---|
| Internet-Scanner | Auffindbar | Versteckt |
| Direkte Angriffe | Möglich | Blockiert |
| Control UI Zugriff | Browser | Proxy/VPN |
| Webhook-Zustellung | Direkt | Via Tunnel |
Hinweise
- Fly.io nutzt x86 Architektur (nicht ARM)
- Das Dockerfile ist mit beiden Architekturen kompatibel
- Für WhatsApp/Telegram Onboarding nutze
fly ssh console - Persistente Daten liegen auf dem Volume unter
/data - Signal benötigt Java + signal-cli; nutze ein Custom Image und halte den Speicher bei 2GB+.
Kosten
Mit der empfohlenen Config (shared-cpu-2x, 2GB RAM):
- ~10-15 $/Monat je nach Nutzung
- Free Tier beinhaltet ein gewisses Kontingent
Details siehe Fly.io Pricing.