Fly.io
Despliegue en Fly.io
Sección titulada «Despliegue en Fly.io»Objetivo: OpenClaw Gateway ejecutándose en una máquina Fly.io con almacenamiento persistente, HTTPS automático y acceso a Discord/canales.
Lo que necesitas
Sección titulada «Lo que necesitas»- CLI flyctl instalada
- Cuenta de Fly.io (la capa gratuita funciona)
- Autenticación del modelo: clave de API de Anthropic (u otras claves de proveedores)
- Credenciales del canal: token del bot de Discord, token de Telegram, etc.
Ruta rápida para principiantes
Sección titulada «Ruta rápida para principiantes»- Clonar repositorio → personalizar
fly.toml - Crear app + volumen → establecer secretos
- Desplegar con
fly deploy - Entrar por SSH para crear la configuración o usar la Interfaz de Control
1) Crear la app de Fly
Sección titulada «1) Crear la app de Fly»# Clone the repogit clone https://github.com/openclaw/openclaw.gitcd openclaw
# Create a new Fly app (pick your own name)fly apps create my-openclaw
# Create a persistent volume (1GB is usually enough)fly volumes create openclaw_data --size 1 --region iadConsejo: Elige una región cercana a ti. Opciones comunes: lhr (Londres), iad (Virginia), sjc (San José).
2) Configurar fly.toml
Sección titulada «2) Configurar fly.toml»Edita fly.toml para que coincida con el nombre de tu app y los requisitos.
Nota de seguridad: La configuración predeterminada expone una URL pública. Para un despliegue reforzado sin IP pública, consulta Despliegue Privado o usa fly.private.toml.
app = "my-openclaw" # Your app nameprimary_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"Configuraciones clave:
| Configuración | Por qué |
|---|---|
--bind lan | Se enlaza a 0.0.0.0 para que el proxy de Fly pueda alcanzar el gateway |
--allow-unconfigured | Se inicia sin un archivo de configuración (crearás uno después) |
internal_port = 3000 | Debe coincidir con --port 3000 (o OPENCLAW_GATEWAY_PORT) para los controles de salud de Fly |
memory = "2048mb" | 512MB es muy poco; se recomiendan 2GB |
OPENCLAW_STATE_DIR = "/data" | Persiste el estado en el volumen |
3) Establecer secretos
Sección titulada «3) Establecer secretos»# Required: Gateway token (for non-loopback binding)fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)
# Model provider API keysfly secrets set ANTHROPIC_API_KEY=sk-ant-...
# Optional: Other providersfly secrets set OPENAI_API_KEY=sk-...fly secrets set GOOGLE_API_KEY=...
# Channel tokensfly secrets set DISCORD_BOT_TOKEN=MTQ...Notas:
- Los enlaces no locales (
--bind lan) requierenOPENCLAW_GATEWAY_TOKENpor seguridad. - Trata estos tokens como contraseñas.
- Prefiere variables de entorno al archivo de configuración para todas las claves de API y tokens. Esto mantiene los secretos fuera de
openclaw.jsondonde podrían exponerse o registrarse accidentalmente.
4) Desplegar
Sección titulada «4) Desplegar»fly deployEl primer despliegue construye la imagen de Docker (~2-3 minutos). Los despliegues posteriores son más rápidos.
Después del despliegue, verifica:
fly statusfly logsDeberías ver:
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)[discord] logged in to discord as xxx5) Crear archivo de configuración
Sección titulada «5) Crear archivo de configuración»Entra por SSH a la máquina para crear una configuración adecuada:
fly ssh consoleCrea el directorio y el archivo de configuración:
mkdir -p /datacat > /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" }}EOFNota: Con OPENCLAW_STATE_DIR=/data, la ruta de configuración es /data/openclaw.json.
Nota: El token de Discord puede provenir de:
- Variable de entorno:
DISCORD_BOT_TOKEN(recomendado para secretos) - Archivo de configuración:
channels.discord.token
Si usa una variable de entorno, no es necesario agregar el token a la configuración. El gateway lee DISCORD_BOT_TOKEN automáticamente.
Reinicie para aplicar:
exitfly machine restart <machine-id>6) Acceder al Gateway
Sección titulada «6) Acceder al Gateway»Interfaz de control
Sección titulada «Interfaz de control»Abrir en el navegador:
fly openO visite https://my-openclaw.fly.dev/
Pegue su token del gateway (el de OPENCLAW_GATEWAY_TOKEN) para autenticarse.
Registros
Sección titulada «Registros»fly logs # Live logsfly logs --no-tail # Recent logsConsola SSH
Sección titulada «Consola SSH»fly ssh consoleSolución de problemas
Sección titulada «Solución de problemas»”La aplicación no está escuchando en la dirección esperada”
Sección titulada «”La aplicación no está escuchando en la dirección esperada”»El gateway se está vinculando a 127.0.0.1 en lugar de 0.0.0.0.
Solución: Agregue --bind lan a su comando de proceso en fly.toml.
Fallo en las comprobaciones de salud / conexión rechazada
Sección titulada «Fallo en las comprobaciones de salud / conexión rechazada»Fly no puede alcanzar el gateway en el puerto configurado.
Solución: Asegúrese de que internal_port coincida con el puerto del gateway (configure --port 3000 o OPENCLAW_GATEWAY_PORT=3000).
Problemas de memoria OOM
Sección titulada «Problemas de memoria OOM»El contenedor se reinicia o se elimina repetidamente. Signos: SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration o reinicios silenciosos.
Solución: Aumente la memoria en fly.toml:
[[vm]] memory = "2048mb"O actualice una máquina existente:
fly machine update <machine-id> --vm-memory 2048 -yNota: 512MB es muy poco. 1GB puede funcionar pero puede dar errores OOM bajo carga o con registro detallado. Se recomiendan 2GB.
Problemas de bloqueo del Gateway
Sección titulada «Problemas de bloqueo del Gateway»El Gateway se niega a iniciarse con errores de “ya está en ejecución”.
Esto sucede cuando el contenedor se reinicia pero el archivo de bloqueo PID persiste en el volumen.
Solución: Elimine el archivo de bloqueo:
fly ssh console --command "rm -f /data/gateway.*.lock"fly machine restart <machine-id>El archivo de bloqueo está en /data/gateway.*.lock (no en un subdirectorio).
Configuración no leída
Sección titulada «Configuración no leída»Si usa --allow-unconfigured, el gateway crea una configuración mínima. Su configuración personalizada en /data/openclaw.json debería leerse al reiniciar.
Verifique que la configuración exista:
fly ssh console --command "cat /data/openclaw.json"Escribir configuración a través de SSH
Sección titulada «Escribir configuración a través de SSH»El comando fly ssh console -C no admite el redireccionamiento de shell. Para escribir un archivo de configuración:
# Use echo + tee (pipe from local to remote)echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"
# Or use sftpfly sftp shell> put /local/path/config.json /data/openclaw.jsonNota: fly sftp puede fallar si el archivo ya existe. Elimínelo primero:
fly ssh console --command "rm /data/openclaw.json"Estado que no persiste
Sección titulada «Estado que no persiste»Si pierde las credenciales o las sesiones después de un reinicio, el directorio de estado se está escribiendo en el sistema de archivos del contenedor.
Solución: Asegúrese de que OPENCLAW_STATE_DIR=/data esté configurado en fly.toml y vuelva a implementar.
Actualizaciones
Sección titulada «Actualizaciones»# Pull latest changesgit pull
# Redeployfly deploy
# Check healthfly statusfly logsActualizar el comando de máquina
Sección titulada «Actualizar el comando de máquina»Si necesita cambiar el comando de inicio sin una reimplementación completa:
# Get machine IDfly machines list
# Update commandfly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y
# Or with memory increasefly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -yNota: Después de fly deploy, el comando de máquina puede restablecerse a lo que está en fly.toml. Si realizó cambios manuales, aplíquelos nuevamente después de la implementación.
Implementación privada (Refuerzo de seguridad)
Sección titulada «Implementación privada (Refuerzo de seguridad)»De forma predeterminada, Fly asigna direcciones IP públicas, lo que hace que su puerta de enlace sea accesible en https://your-app.fly.dev. Esto es conveniente, pero significa que su implementación es discoverable por escáneres de Internet (Shodan, Censys, etc.).
Para una implementación reforzada con sin exposición pública, utilice la plantilla privada.
Cuándo usar la implementación privada
Sección titulada «Cuándo usar la implementación privada»- Solo realiza llamadas/mensajes salientes (sin webhooks entrantes)
- Utiliza túneles ngrok o Tailscale para cualquier devolución de llamada de webhook
- Accede a la puerta de enlace a través de SSH, proxy o WireGuard en lugar del navegador
- Desea que la implementación esté oculta para los escáneres de Internet
Configuración
Sección titulada «Configuración»Use fly.private.toml en lugar de la configuración estándar:
# Deploy with private configfly deploy -c fly.private.tomlO convierta una implementación existente:
# List current IPsfly ips list -a my-openclaw
# Release public IPsfly ips release <public-ipv4> -a my-openclawfly ips release <public-ipv6> -a my-openclaw
# Switch to private config so future deploys don't re-allocate public IPs# (remove [http_service] or deploy with the private template)fly deploy -c fly.private.toml
# Allocate private-only IPv6fly ips allocate-v6 --private -a my-openclawDespués de esto, fly ips list debería mostrar solo una IP de tipo private:
VERSION IP TYPE REGIONv6 fdaa:x:x:x:x::x private globalAcceder a una implementación privada
Sección titulada «Acceder a una implementación privada»Dado que no hay una URL pública, use uno de estos métodos:
Opción 1: Proxy local (el más simple)
# Forward local port 3000 to the appfly proxy 3000:3000 -a my-openclaw
# Then open http://localhost:3000 in browserOpción 2: VPN WireGuard
# Create WireGuard config (one-time)fly wireguard create
# Import to WireGuard client, then access via internal IPv6# Example: http://[fdaa:x:x:x:x::x]:3000Opción 3: Solo SSH
fly ssh console -a my-openclawWebhooks con implementación privada
Sección titulada «Webhooks con implementación privada»Si necesita devoluciones de llamada de webhook (Twilio, Telnyx, etc.) sin exposición pública:
- Túnel ngrok - Ejecute ngrok dentro del contenedor o como sidecar
- Tailscale Funnel - Exponer rutas específicas a través de Tailscale
- Solo saliente - Algunos proveedores (Twilio) funcionan bien para llamadas salientes sin webhooks
Ejemplo de configuración de llamada de voz con ngrok:
{ "plugins": { "entries": { "voice-call": { "enabled": true, "config": { "provider": "twilio", "tunnel": { "provider": "ngrok" }, "webhookSecurity": { "allowedHosts": ["example.ngrok.app"] } } } } }}El túnel ngrok se ejecuta dentro del contenedor y proporciona una URL de webhook pública sin exponer la aplicación Fly en sí. Establezca webhookSecurity.allowedHosts en el nombre de host del túnel público para que se acepten los encabezados de host reenviados.
Beneficios de seguridad
Sección titulada «Beneficios de seguridad»| Aspecto | Público | Privado |
|---|---|---|
| Escáneres de Internet | Detectable | Oculto |
| Ataques directos | Posible | Bloqueado |
| Acceso a la interfaz de control | Navegador | Proxy/VPN |
| Entrega de webhooks | Directa | Vía túnel |
- Fly.io utiliza arquitectura x86 (no ARM)
- El Dockerfile es compatible con ambas arquitecturas
- Para el incorporado de WhatsApp/Telegram, use
fly ssh console - Los datos persistentes residen en el volumen en
/data - Signal requiere Java + signal-cli; use una imagen personalizada y mantenga la memoria en 2GB o más.
Con la configuración recomendada (shared-cpu-2x, 2GB RAM):
- ~$10-15/mes dependiendo del uso
- El nivel gratuito incluye alguna asignación
Consulte Fly.io pricing para obtener detalles.