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
- Sklonuj repozytorium → dostosuj
fly.toml - Utwórz aplikację + wolumin → ustaw sekrety
- Wdróż za pomocą
fly deploy - 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żywaOPENCLAW_GATEWAY_TOKEN, alegateway.auth.passwordlub poprawnie skonfigurowane wdrożenietrusted-proxyinne 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:
- Tunel ngrok - Uruchom ngrok wewnątrz kontenera lub jako sidecar
- Tailscale Funnel - Udostępnij określone ścieżki przez Tailscale
- 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
- Skonfiguruj kanały wiadomości: Kanały
- Skonfiguruj Gateway: Konfiguracja Gateway
- Aktualizuj OpenClaw na bieżąco: Aktualizowanie