Hosting

Fly.io

Cel: OpenClaw Gateway działający na maszynie Fly.io z trwałą pamięcią masową, automatycznym HTTPS i dostępem do Discorda/kanału.

Czego potrzebujesz

  • Zainstalowany flyctl CLI
  • Konto Fly.io (wystarczy plan darmowy)
  • Uwierzytelnianie modelu: klucz API dla wybranego dostawcy modelu
  • Dane uwierzytelniające kanału: token bota Discord, token Telegram itd.

Szybka ścieżka dla początkujących

  1. Sklonuj repozytorium → dostosuj fly.toml
  2. Utwórz aplikację + wolumin → ustaw sekrety
  3. Wdróż za pomocą fly deploy
  4. Połącz się przez SSH, aby utworzyć konfigurację, albo użyj Control UI
  • Create the Fly app

    # Clone the repo
    git clone https://github.com/openclaw/openclaw.git
    cd 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 iad
    

    Wskazówka: Wybierz region blisko siebie. Typowe opcje: lhr (Londyn), iad (Wirginia), sjc (San Jose).

  • Configure fly.toml

    Edytuj fly.toml, aby pasował do nazwy aplikacji i wymagań.

    Uwaga dotycząca bezpieczeństwa: Domyślna konfiguracja udostępnia publiczny URL. Aby wdrożyć utwardzoną konfigurację bez publicznego IP, zobacz Wdrożenie prywatne albo użyj deploy/fly.private.toml.

    app = "my-openclaw"  # Your 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"
    

    Kluczowe ustawienia:

    Ustawienie Dlaczego
    --bind lan Wiąże z 0.0.0.0, aby proxy Fly mogło dotrzeć do Gateway
    --allow-unconfigured Uruchamia bez pliku konfiguracji (utworzysz go później)
    internal_port = 3000 Musi pasować do --port 3000 (albo OPENCLAW_GATEWAY_PORT) dla kontroli stanu Fly
    memory = "2048mb" 512 MB to za mało; zalecane są 2 GB
    OPENCLAW_STATE_DIR = "/data" Utrwala stan na woluminie
  • Set secrets

    # Required: Gateway token (for 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: Other providers
    fly secrets set OPENAI_API_KEY=sk-...
    fly secrets set GOOGLE_API_KEY=...
    
    # Channel tokens
    fly secrets set DISCORD_BOT_TOKEN=MTQ...
    

    Uwagi:

    • Powiązania inne niż loopback (--bind lan) wymagają prawidłowej ścieżki uwierzytelniania Gateway. Ten przykład Fly.io używa OPENCLAW_GATEWAY_TOKEN, ale gateway.auth.password lub poprawnie skonfigurowane wdrożenie trusted-proxy inne niż loopback również spełnia to wymaganie.
    • Traktuj te tokeny jak hasła.
    • Preferuj zmienne środowiskowe zamiast pliku konfiguracyjnego dla wszystkich kluczy API i tokenów. Dzięki temu sekrety nie trafiają do openclaw.json, gdzie mogłyby zostać przypadkowo ujawnione lub zapisane w logach.
  • Deploy

    fly deploy
    

    Pierwsze wdrożenie buduje obraz Dockera (~2-3 minuty). Kolejne wdrożenia są szybsze.

    Po wdrożeniu sprawdź:

    fly status
    fly logs
    

    Powinno być widoczne:

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

    Połącz się z maszyną przez SSH, aby utworzyć właściwą konfigurację:

    fly ssh console
    

    Utwórz katalog i plik konfiguracji:

    mkdir -p /data
    cat > /data/openclaw.json << 'EOF'
    {
      "agents": {
        "defaults": {
          "model": {
            "primary": "anthropic/claude-opus-4-6",
            "fallbacks": ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4"]
          },
          "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",
        "controlUi": {
          "allowedOrigins": [
            "https://my-openclaw.fly.dev",
            "http://localhost:3000",
            "http://127.0.0.1:3000"
          ]
        }
      },
      "meta": {}
    }
    EOF
    

    Uwaga: Przy OPENCLAW_STATE_DIR=/data ścieżka konfiguracji to /data/openclaw.json.

    Uwaga: Zastąp https://my-openclaw.fly.dev rzeczywistym origin aplikacji Fly. Uruchamianie Gateway inicjuje lokalne originy Control UI na podstawie wartości środowiskowych --bind i --port, więc pierwszy rozruch może przebiec przed istnieniem konfiguracji, ale dostęp przez przeglądarkę za pośrednictwem Fly nadal wymaga dokładnego origin HTTPS wpisanego w gateway.controlUi.allowedOrigins.

    Uwaga: Token Discord może pochodzić z jednego z dwóch miejsc:

    • Zmienna środowiskowa: DISCORD_BOT_TOKEN (zalecane dla sekretów)
    • Plik konfiguracji: channels.discord.token

    Jeśli używasz zmiennej środowiskowej, nie trzeba dodawać tokenu do konfiguracji. Gateway automatycznie odczytuje DISCORD_BOT_TOKEN.

    Uruchom ponownie, aby zastosować:

    exit
    fly machine restart <machine-id>
    
  • Access the Gateway

    Control UI

    Otwórz w przeglądarce:

    fly open
    

    Albo odwiedź https://my-openclaw.fly.dev/

    Uwierzytelnij się skonfigurowanym współdzielonym sekretem. Ten przewodnik używa tokenu Gateway z OPENCLAW_GATEWAY_TOKEN; jeśli przełączono się na uwierzytelnianie hasłem, użyj zamiast tego tego hasła.

    Logi

    fly logs              # Live logs
    fly logs --no-tail    # Recent logs
    

    Konsola SSH

    fly ssh console
    
  • Rozwiązywanie problemów

    „App is not listening on expected address”

    Gateway wiąże się z 127.0.0.1 zamiast 0.0.0.0.

    Poprawka: Dodaj --bind lan do polecenia procesu w fly.toml.

    Kontrole stanu kończą się niepowodzeniem / odmowa połączenia

    Fly nie może dotrzeć do Gateway na skonfigurowanym porcie.

    Poprawka: Upewnij się, że internal_port pasuje do portu Gateway (ustaw --port 3000 albo OPENCLAW_GATEWAY_PORT=3000).

    OOM / problemy z pamięcią

    Kontener ciągle się restartuje albo jest zabijany. Oznaki: SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration albo ciche restarty.

    Poprawka: Zwiększ pamięć w fly.toml:

    [[vm]]
      memory = "2048mb"
    

    Albo zaktualizuj istniejącą maszynę:

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

    Uwaga: 512 MB to za mało. 1 GB może działać, ale może prowadzić do OOM pod obciążeniem albo przy szczegółowym logowaniu. Zalecane są 2 GB.

    Problemy z blokadą Gateway

    Gateway odmawia uruchomienia z błędami „already running”.

    Dzieje się tak, gdy kontener uruchamia się ponownie, ale plik blokady PID pozostaje na woluminie.

    Poprawka: Usuń plik blokady:

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

    Plik blokady znajduje się w /data/gateway.*.lock (nie w podkatalogu).

    Konfiguracja nie jest odczytywana

    --allow-unconfigured tylko pomija strażnika uruchamiania. Nie tworzy ani nie naprawia /data/openclaw.json, więc upewnij się, że rzeczywista konfiguracja istnieje i zawiera gateway.mode="local", gdy chcesz normalnie uruchomić lokalny Gateway.

    Sprawdź, czy konfiguracja istnieje:

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

    Zapisywanie konfiguracji przez SSH

    Polecenie fly ssh console -C nie obsługuje przekierowania powłoki. Aby zapisać plik konfiguracji:

    # Use echo + tee (pipe from local to remote)
    echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"
    
    # Or use sftp
    fly sftp shell
    > put /local/path/config.json /data/openclaw.json
    

    Uwaga: fly sftp może się nie powieść, jeśli plik już istnieje. Najpierw go usuń:

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

    Stan nie jest utrwalany

    Jeśli po restarcie tracisz profile uwierzytelniania, stan kanału/dostawcy albo sesje, katalog stanu zapisuje dane w systemie plików kontenera.

    Poprawka: Upewnij się, że OPENCLAW_STATE_DIR=/data jest ustawione w fly.toml, i wdróż ponownie.

    Aktualizacje

    # Pull latest changes
    git pull
    
    # Redeploy
    fly deploy
    
    # Check health
    fly status
    fly logs
    

    Aktualizowanie polecenia maszyny

    Jeśli musisz zmienić polecenie startowe bez pełnego ponownego wdrożenia:

    # Get machine ID
    fly machines list
    
    # Update command
    fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y
    
    # Or with memory increase
    fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y
    

    Uwaga: Po fly deploy polecenie maszyny może zostać zresetowane do tego, co jest w fly.toml. Jeśli wprowadzono ręczne zmiany, zastosuj je ponownie po wdrożeniu.

    Wdrożenie prywatne (utwardzone)

    Domyślnie Fly przydziela publiczne adresy IP, dzięki czemu Gateway jest dostępny pod https://your-app.fly.dev. Jest to wygodne, ale oznacza, że wdrożenie może zostać wykryte przez skanery internetowe (Shodan, Censys itd.).

    Aby wdrożyć utwardzoną konfigurację bez publicznej ekspozycji, użyj szablonu prywatnego.

    Kiedy używać wdrożenia prywatnego

    • Wykonujesz tylko wychodzące wywołania/wiadomości (bez przychodzących Webhooków)
    • Używasz tuneli ngrok lub Tailscale dla dowolnych wywołań zwrotnych Webhook
    • Uzyskujesz dostęp do Gateway przez SSH, proxy lub WireGuard zamiast przez przeglądarkę
    • Chcesz, aby wdrożenie było ukryte przed skanerami internetowymi

    Konfiguracja

    Użyj deploy/fly.private.toml zamiast standardowej konfiguracji:

    # Deploy with private config
    fly deploy -c deploy/fly.private.toml
    

    Albo przekształć istniejące wdrożenie:

    # List current IPs
    fly ips list -a my-openclaw
    
    # Release public IPs
    fly ips release <public-ipv4> -a my-openclaw
    fly 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 deploy/fly.private.toml
    
    # Allocate private-only IPv6
    fly ips allocate-v6 --private -a my-openclaw
    

    Po tym fly ips list powinno pokazywać tylko adres IP typu private:

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

    Dostęp do wdrożenia prywatnego

    Ponieważ nie ma publicznego URL, użyj jednej z tych metod:

    Opcja 1: Lokalne proxy (najprostsze)

    # Forward local port 3000 to the app
    fly proxy 3000:3000 -a my-openclaw
    
    # Then open http://localhost:3000 in browser
    

    Opcja 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]:3000
    

    Opcja 3: Tylko SSH

    fly ssh console -a my-openclaw
    

    Webhooki z wdrożeniem prywatnym

    Jeśli potrzebujesz wywołań zwrotnych webhook (Twilio, Telnyx itd.) bez publicznej ekspozycji:

    1. Tunel ngrok - Uruchom ngrok wewnątrz kontenera lub jako sidecar
    2. Tailscale Funnel - Udostępnij określone ścieżki przez Tailscale
    3. Tylko ruch wychodzący - Niektórzy dostawcy (Twilio) działają poprawnie dla połączeń wychodzących bez webhooków

    Przykładowa konfiguracja połączeń głosowych z ngrok:

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

    Tunel ngrok działa wewnątrz kontenera i udostępnia publiczny URL webhook bez wystawiania samej aplikacji Fly. Ustaw webhookSecurity.allowedHosts na publiczną nazwę hosta tunelu, aby przekazywane nagłówki hosta były akceptowane.

    Korzyści bezpieczeństwa

    Aspekt Publiczne Prywatne
    Skanery internetowe Wykrywalne Ukryte
    Bezpośrednie ataki Możliwe Zablokowane
    Dostęp do Control UI Przeglądarka Proxy/VPN
    Dostarczanie webhooków Bezpośrednio Przez tunel

    Uwagi

    • Fly.io używa architektury x86 (nie ARM)
    • Dockerfile jest zgodny z obiema architekturami
    • Do wdrażania WhatsApp/Telegram użyj fly ssh console
    • Dane trwałe znajdują się na woluminie w /data
    • Signal wymaga Java + signal-cli; użyj niestandardowego obrazu i utrzymuj pamięć na poziomie 2 GB+.

    Koszt

    Przy zalecanej konfiguracji (shared-cpu-2x, 2 GB RAM):

    • ~10-15 USD/miesiąc w zależności od użycia
    • Darmowy plan obejmuje pewien limit

    Szczegóły znajdziesz w cenniku Fly.io.

    Następne kroki

    Powiązane