Deploiement Fly.io

Objectif : faire tourner la passerelle OpenClaw sur une machine Fly.io avec stockage persistant, HTTPS automatique et acces aux canaux Discord/messagerie.

Ce dont vous avez besoin

  • CLI flyctl installe
  • Compte Fly.io (le tier gratuit fonctionne)
  • Auth modele : cle API pour votre fournisseur de modele
  • Identifiants de canal : token de bot Discord, token Telegram, etc.

Chemin rapide pour debutants

  1. Cloner le depot → personnaliser fly.toml
  2. Creer l’app + le volume → definir les secrets
  3. Deployer avec fly deploy
  4. Se connecter en SSH pour creer la config ou utiliser l’interface de controle

1) Creer l’app Fly

# Cloner le depot
git clone https://github.com/openclaw/openclaw.git
cd openclaw

# Creer une nouvelle app Fly (choisissez votre propre nom)
fly apps create my-openclaw

# Creer un volume persistant (1 Go suffit generalement)
fly volumes create openclaw_data --size 1 --region iad

Astuce : Choisissez une region proche de vous. Options courantes : lhr (Londres), iad (Virginie), sjc (San Jose).

2) Configurer fly.toml

Editez fly.toml pour correspondre a votre nom d’app et vos besoins.

Note de securite : La configuration par defaut expose une URL publique. Pour un deploiement renforce sans IP publique, consultez Deploiement prive ou utilisez fly.private.toml.

app = "my-openclaw"  # Votre nom d'app
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"

Parametres cles :

ParametreRaison
--bind lanEcoute sur 0.0.0.0 pour que le proxy Fly puisse atteindre la passerelle
--allow-unconfiguredDemarre sans fichier de configuration (vous le creez apres)
internal_port = 3000Doit correspondre a --port 3000 (ou OPENCLAW_GATEWAY_PORT) pour les health checks Fly
memory = "2048mb"512 Mo est trop peu ; 2 Go recommandes
OPENCLAW_STATE_DIR = "/data"Persiste l’etat sur le volume

3) Definir les secrets

# Requis : Token de passerelle (pour la liaison non-loopback)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)

# Cles API du fournisseur de modeles
fly secrets set ANTHROPIC_API_KEY=sk-ant-...

# Optionnel : Autres fournisseurs
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...

# Tokens de canaux
fly secrets set DISCORD_BOT_TOKEN=MTQ...

Notes :

  • Les liaisons non-loopback (--bind lan) necessitent OPENCLAW_GATEWAY_TOKEN pour la securite.
  • Traitez ces tokens comme des mots de passe.
  • Preferez les variables d’environnement au fichier de configuration pour toutes les cles API et tokens. Cela garde les secrets hors de openclaw.json ou ils pourraient etre accidentellement exposes ou journalises.

4) Deployer

fly deploy

Le premier deploiement construit l’image Docker (~2-3 minutes). Les deploiements suivants sont plus rapides.

Apres le deploiement, verifiez :

fly status
fly logs

Vous devriez voir :

[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx

5) Creer le fichier de configuration

Connectez-vous en SSH a la machine pour creer une configuration propre :

fly ssh console

Creez le repertoire et le fichier de configuration :

mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-opus-4-6",
        "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

Remarque : Avec OPENCLAW_STATE_DIR=/data, le chemin de configuration est /data/openclaw.json.

Remarque : Le token Discord peut provenir de :

  • Variable d’environnement : DISCORD_BOT_TOKEN (recommande pour les secrets)
  • Fichier de configuration : channels.discord.token

Si vous utilisez la variable d’environnement, pas besoin d’ajouter le token dans la configuration. La passerelle lit DISCORD_BOT_TOKEN automatiquement.

Redemarrez pour appliquer :

exit
fly machine restart <machine-id>

6) Acceder a la passerelle

Interface de controle

Ouvrir dans le navigateur :

fly open

Ou visitez https://my-openclaw.fly.dev/

Collez votre token de passerelle (celui de OPENCLAW_GATEWAY_TOKEN) pour vous authentifier.

Logs

fly logs              # Logs en direct
fly logs --no-tail    # Logs recents

Console SSH

fly ssh console

Depannage

”App is not listening on expected address”

La passerelle ecoute sur 127.0.0.1 au lieu de 0.0.0.0.

Correction : Ajoutez --bind lan a votre commande de processus dans fly.toml.

Health checks en echec / connexion refusee

Fly ne peut pas atteindre la passerelle sur le port configure.

Correction : Assurez-vous que internal_port correspond au port de la passerelle (definissez --port 3000 ou OPENCLAW_GATEWAY_PORT=3000).

OOM / Problemes de memoire

Le conteneur redemarrage en boucle ou est tue. Signes : SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration, ou redemarrages silencieux.

Correction : Augmentez la memoire dans fly.toml :

[[vm]]
  memory = "2048mb"

Ou mettez a jour une machine existante :

fly machine update <machine-id> --vm-memory 2048 -y

Remarque : 512 Mo est trop peu. 1 Go peut fonctionner mais peut entrainer un OOM sous charge ou avec une journalisation verbeuse. 2 Go est recommande.

Problemes de verrou de la passerelle

La passerelle refuse de demarrer avec des erreurs “already running”.

Cela se produit quand le conteneur redemarrage mais que le fichier de verrou PID persiste sur le volume.

Correction : Supprimez le fichier de verrou :

fly ssh console --command "rm -f /data/gateway.*.lock"
fly machine restart <machine-id>

Le fichier de verrou est a /data/gateway.*.lock (pas dans un sous-repertoire).

Configuration non lue

Si vous utilisez --allow-unconfigured, la passerelle cree une configuration minimale. Votre configuration personnalisee a /data/openclaw.json devrait etre lue au redemarrage.

Verifiez que la configuration existe :

fly ssh console --command "cat /data/openclaw.json"

Ecrire la configuration via SSH

La commande fly ssh console -C ne supporte pas la redirection shell. Pour ecrire un fichier de configuration :

# Utiliser echo + tee (pipe du local vers le distant)
echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"

# Ou utiliser sftp
fly sftp shell
> put /local/path/config.json /data/openclaw.json

Remarque : fly sftp peut echouer si le fichier existe deja. Supprimez d’abord :

fly ssh console --command "rm /data/openclaw.json"

L’etat ne persiste pas

Si vous perdez les identifiants ou sessions apres un redemarrage, le repertoire d’etat ecrit sur le systeme de fichiers du conteneur.

Correction : Assurez-vous que OPENCLAW_STATE_DIR=/data est defini dans fly.toml et redeployez.

Mises a jour

# Tirer les derniers changements
git pull

# Redeployer
fly deploy

# Verifier la sante
fly status
fly logs

Mettre a jour la commande de la machine

Si vous devez changer la commande de demarrage sans un redploiement complet :

# Obtenir l'ID de la machine
fly machines list

# Mettre a jour la commande
fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y

# Ou avec augmentation de memoire
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y

Remarque : Apres fly deploy, la commande de la machine peut etre reinitialise a ce qui est dans fly.toml. Si vous avez fait des changements manuels, reappliquez-les apres le deploiement.

Deploiement prive (renforce)

Par defaut, Fly alloue des IP publiques, rendant votre passerelle accessible a https://your-app.fly.dev. C’est pratique mais signifie que votre deploiement est decouvrable par les scanners Internet (Shodan, Censys, etc.).

Pour un deploiement renforce sans exposition publique, utilisez le modele prive.

Quand utiliser le deploiement prive

  • Vous ne faites que des appels/messages sortants (pas de webhooks entrants)
  • Vous utilisez des tunnels ngrok ou Tailscale pour les callbacks webhook
  • Vous accedez a la passerelle via SSH, proxy ou WireGuard au lieu du navigateur
  • Vous voulez que le deploiement soit invisible aux scanners Internet

Configuration

Utilisez fly.private.toml au lieu de la configuration standard :

# Deployer avec la configuration privee
fly deploy -c fly.private.toml

Ou convertissez un deploiement existant :

# Lister les IP actuelles
fly ips list -a my-openclaw

# Liberer les IP publiques
fly ips release <public-ipv4> -a my-openclaw
fly ips release <public-ipv6> -a my-openclaw

# Passer a la configuration privee pour que les futurs deploiements ne reallouent pas d'IP publiques
# (supprimer [http_service] ou deployer avec le modele prive)
fly deploy -c fly.private.toml

# Allouer une IPv6 privee uniquement
fly ips allocate-v6 --private -a my-openclaw

Apres cela, fly ips list ne devrait montrer qu’une IP de type private :

VERSION  IP                   TYPE             REGION
v6       fdaa:x:x:x:x::x      private          global

Acceder a un deploiement prive

Comme il n’y a pas d’URL publique, utilisez l’une de ces methodes :

Option 1 : Proxy local (le plus simple)

# Rediriger le port local 3000 vers l'app
fly proxy 3000:3000 -a my-openclaw

# Puis ouvrir http://localhost:3000 dans le navigateur

Option 2 : VPN WireGuard

# Creer la configuration WireGuard (une seule fois)
fly wireguard create

# Importer dans le client WireGuard, puis acceder via IPv6 interne
# Exemple : http://[fdaa:x:x:x:x::x]:3000

Option 3 : SSH uniquement

fly ssh console -a my-openclaw

Webhooks avec deploiement prive

Si vous avez besoin de callbacks webhook (Twilio, Telnyx, etc.) sans exposition publique :

  1. Tunnel ngrok - Executer ngrok dans le conteneur ou en sidecar
  2. Tailscale Funnel - Exposer des chemins specifiques via Tailscale
  3. Sortant uniquement - Certains fournisseurs (Twilio) fonctionnent tres bien pour les appels sortants sans webhooks

Exemple de configuration d’appel vocal avec ngrok :

{
  "plugins": {
    "entries": {
      "voice-call": {
        "enabled": true,
        "config": {
          "provider": "twilio",
          "tunnel": { "provider": "ngrok" },
          "webhookSecurity": {
            "allowedHosts": ["example.ngrok.app"]
          }
        }
      }
    }
  }
}

Le tunnel ngrok s’execute dans le conteneur et fournit une URL webhook publique sans exposer l’app Fly elle-meme. Definissez webhookSecurity.allowedHosts sur le nom d’hote public du tunnel pour que les en-tetes host rediriges soient acceptes.

Avantages en termes de securite

AspectPublicPrive
Scanners InternetDecouvrableCache
Attaques directesPossibleBloque
Acces interfaceNavigateurProxy/VPN
WebhooksDirectVia tunnel

Notes

  • Fly.io utilise une architecture x86 (pas ARM)
  • Le Dockerfile est compatible avec les deux architectures
  • Pour l’accueil WhatsApp/Telegram, utilisez fly ssh console
  • Les donnees persistantes sont sur le volume a /data
  • Signal necessite Java + signal-cli ; utilisez une image personnalisee et gardez la memoire a 2 Go+.

Cout

Avec la configuration recommandee (shared-cpu-2x, 2 Go RAM) :

  • ~10-15 $/mois selon l’utilisation
  • Le tier gratuit inclut une certaine allocation

Consultez la tarification Fly.io pour les details.