Bezpieczeństwo instancji OpenClaw: bind, auth, sekrety i kopie
Umowy, RODO i papiery to lekcja siódma i szesnasta. Ta jest o portach, tokenach i uprawnieniach plików. Żadna z tych rzeczy nie zajmuje więcej niż kwadrans, a pominięcie jednej potrafi wystawić Twoje dane na otwarty port.
Zanim otworzysz port: pięć trybów gateway.bind
Gateway multipleksuje WebSocket i HTTP na jednym porcie, domyślnie 18789, a o tym, kto może się do niego dobić, decyduje gateway.bind. Tryby to loopback (domyślny, tylko połączenia lokalne), lan, tailnet, auto i custom. Loopback jest opisany jako zalecany punkt startu dla instalacji typu osobisty asystent i naprawdę nie ma powodu, żeby ruszać go pierwszego dnia.
Dokumentacja formułuje warunek bardzo bezpośrednio: szersza ekspozycja wymaga uwierzytelniania gatewaya — współdzielonego tokenu, hasła albo poprawnie skonfigurowanego zaufanego proxy — oraz prawdziwej zapory. Wystawianie gatewaya na 0.0.0.0 bez auth jest odradzane wprost, bez żadnych zastrzeżeń typu „chyba że w sieci wewnętrznej”.
Zamiast otwierać LAN, dokumentacja poleca Tailscale Serve i tryb tailnet. Wtedy dostęp opiera się na tożsamości urządzenia w sieci prywatnej, a nie na tym, że ktoś zna adres IP i port. Audyt bezpieczeństwa ma zresztą osobny check gateway.tailscale_funnel, bo Funnel wystawia usługę do publicznego internetu i to jest już całkiem inna decyzja niż Serve.
Osobna warstwa to Control UI. gateway.controlUi.enabled jest domyślnie włączone, basePath domyślnie prowadzi do /openclaw, a gateway.controlUi.allowedOrigins staje się obowiązkowa przy dostępie spoza pętli zwrotnej. Istnieje też zmienna OPENCLAW_ALLOW_INSECURE_PRIVATE_WS, która zdejmuje wymóg szyfrowania na prywatnych nazwach DNS. Ustawiasz ją tylko w środowisku procesu i tylko na czas jednej awarii — nie w configu i nie na stałe.
Nazwa trybu auto sugeruje, że coś się samo domyśli. Nie domyśli się, że siedzisz w kontenerze, i to akurat mocno myli ludzi. Sprawdź to, zanim spędzisz wieczór na szukaniu, czemu przeglądarka nie widzi dashboardu.
openclaw config get gateway.bind
openclaw config get gateway.port
openclaw gateway status --deep --jsonDlaczego -p 18789:18789 nie wystarcza w Dockerze
W kontenerze domyślny loopback oznacza 127.0.0.1 wewnątrz kontenera, a nie na Twoim hoście. Przy zwykłym mapowaniu -p 18789:18789 ruch przychodzi na interfejs kontenera, gateway nasłuchuje wyłącznie na pętli zwrotnej i połączenie nie dochodzi. Nie ma trybu, który włączy się sam po wykryciu kontenera — gateway.bind trzeba zmienić świadomie i od razu dołożyć uwierzytelnianie.
Dlatego oficjalny skrypt ./scripts/docker/setup.sh ustawia bind na lan i przy okazji generuje token podczas onboardingu. Konsekwencja jest prosta: skoro proces musi nasłuchiwać poza pętlą, auth przestaje być opcjonalne. Dashboard otwierasz potem pod http://127.0.0.1:18789/ z wygenerowanym tokenem. Obrazy oficjalne to ghcr.io/openclaw/openclaw:latest jako główne źródło i openclaw/openclaw:latest jako lustro na Docker Hubie.
Druga część pułapki jest sieciowa i kosztuje więcej. Publikowanie portów przez -p przepuszcza ruch przez łańcuchy forwardowania Dockera, a nie tylko przez INPUT hosta. Twoje reguły UFW mogą wyglądać na szczelne i nie łapać niczego, bo decyzja zapada w łańcuchu DOCKER-USER. Dokumentacja pokazuje przykładowy zestaw reguł dla tego łańcucha — przepuszczone 80, 443 i SSH plus połączenia established, reszta odrzucona — oraz osobne reguły IPv6 w /etc/ufw/after6.rules.
Przy pisaniu tych reguł nie zaszywaj nazw interfejsów w rodzaju eth0. Różnią się między obrazami VPS-ów, a reguła, która nie pasuje do niczego, po cichu nie blokuje niczego. To jest ten rodzaj błędu, którego nie widać w żadnym logu, dopóki ktoś nie zeskanuje Ci portu.
Trwałość stanu zapewniają trzy podpięte katalogi: /home/node/.openclaw na config, /home/node/.config/openclaw na profile uwierzytelniania i /home/node/.openclaw/workspace na przestrzeń roboczą. Znany objaw rozjechanego właścicielstwa to komunikat „blocked plugin candidate: suspicious ownership (uid=1000, expected uid=0 or root)”. Naprawa jest krótka: sudo chown -R 1000:1000 na katalog konfiguracji i workspace, potem openclaw doctor --fix.
docker pull ghcr.io/openclaw/openclaw:latest
# gdy plugin nie chce się załadować w kontenerze:
sudo chown -R 1000:1000 <config> <workspace>
openclaw doctor --fixUwierzytelnianie Gatewaya jest fail-closed — ustaw je świadomie
Uwierzytelnianie jest wymagane domyślnie i działa fail-closed: bez poprawnie skonfigurowanej ścieżki auth gateway odmawia połączeń WebSocket. Gateway odmawia bindowania bez skonfigurowanego auth, a w logu zostawia wtedy „refusing to bind gateway without auth”. Tryb ustawia gateway.auth.mode i przyjmuje wartości none, token, password oraz trusted-proxy.
Zalecany jest tryb token, czyli współdzielony bearer token w gateway.auth.token. Nie wymyślaj go sam — openclaw doctor --generate-gateway-token zrobi to za Ciebie. Odpowiedniki środowiskowe to OPENCLAW_GATEWAY_TOKEN i OPENCLAW_GATEWAY_PASSWORD, przy czym hasło lepiej trzymać właśnie w zmiennej niż w pliku konfiguracyjnym.
Tryb trusted-proxy ma dwie pułapki, na które dokumentacja zwraca uwagę osobno. Pierwsza: Twoje proxy musi nadpisywać nagłówek X-Forwarded-For, a nie dopisywać do niego kolejne wartości, inaczej klient sam podstawi sobie tożsamość. Druga: reverse proxy stojące na pętli zwrotnej musi mieć jawnie ustawione gateway.auth.trustedProxy.allowLoopback na true — bez tego i tak wymagany jest token albo hasło. Tożsamość przychodzi nagłówkiem wskazanym w userHeader.
Webhooki i hooki uwierzytelniają się nagłówkiem Authorization: Bearer albo x-openclaw-token. Audyt ma na to osobny check hooks.token_reuse_gateway_token, bo używanie tego samego sekretu do gatewaya i do hooków oznacza, że rotacja jednego wymusza rotację drugiego, a zwykle zapomina się o tym drugim. Drugi check z tej rodziny, hooks.allowed_agent_ids_unrestricted, wyłapuje hooki, które mogą trafić do dowolnego agenta.
Jedna rzecz proceduralna, o którą wszyscy się potykają: zmiana portu i zmiana ustawień uwierzytelniania to zmiany infrastrukturalne. Hot reload ich nie podniesie. Po edycji trzeba zrestartować gateway, inaczej będziesz debugować konfigurację, która jeszcze nie działa.
openclaw doctor --generate-gateway-token
openclaw config set gateway.auth.mode token
openclaw gateway restartSekrety mają leżeć na hoście gatewaya, nie w workspace
Zasada, którą dokumentacja formułuje najkrócej: zakładaj, że cokolwiek leży pod ~/.openclaw, może zawierać sekrety albo dane prywatne. Stąd konkretne uprawnienia. 600 na ~/.openclaw/openclaw.json, 700 na sam katalog ~/.openclaw, 600 na wszystko w ~/.openclaw/credentials oraz 600 na ~/.openclaw/state/openclaw.sqlite, gdzie siedzą tokeny MCP i stan runtime.
Poświadczenia dostawców modeli nie mają prawa leżeć w pliku .env wewnątrz workspace agenta. Ich miejsce to środowisko procesu gatewaya, globalny dotenv albo config. Powód jest prozaiczny: workspace projekt zaleca trzymać w prywatnym repozytorium git, a narzędzia agenta czytają go swobodnie. Klucz w tym katalogu to klucz w historii commitów.
Sekrety wczytywane są z trzech źródeł w ustalonej kolejności: zmienne procesu rodzica, plik .env z bieżącego katalogu roboczego, na końcu globalny ~/.openclaw/.env jako fallback. W samym configu działają podstawienia ${NAZWA_ZMIENNEJ} wewnątrz stringów, ale tylko dla nazw pisanych wielkimi literami. Gdy gateway chodzi jako usługa systemowa i nie widzi zmiennych użytkownika, ratuje OPENCLAW_LOAD_SHELL_ENV=1.
Katalogu ~/.openclaw nie wrzucaj do repozytorium nigdy. Są tam poświadczenia kanałów, tokeny OAuth, transkrypty sesji i zaszyfrowane payloady sekretów. Workspace i katalog stanu to dwie osobne lokalizacje, obie wymagają kopii, ale tylko jedna nadaje się do gita.
Przy zgłoszeniach do wsparcia i przy migracji przydaje się nawyk sprawdzania obecności tokenu bez wypisywania jego wartości. Do samego zgłoszenia lepiej nadaje się openclaw status --all — to diagnoza tylko do odczytu z ogonem logów i zredagowanymi tokenami.
chmod 700 ~/.openclaw
chmod 600 ~/.openclaw/openclaw.json
chmod -R 600 ~/.openclaw/credentials
openclaw status --allSandbox ogranicza zasięg błędu, ale nie zastępuje polityki narzędzi
Sandbox oddziela wykonywanie narzędzi od procesu gatewaya i domyślnie jest wyłączony. Włączasz go w agents.defaults.sandbox globalnie albo w agents.entries.*.sandbox dla pojedynczego agenta. Trzy ustawienia sterują całością: sandbox.mode przyjmuje off, non-main i all (domyślnie off), sandbox.scope przyjmuje agent, session i shared (domyślnie agent), a sandbox.backend to docker, ssh albo openshell (domyślnie docker). Wariantu shared lepiej unikać.
Dostęp sandboxa do workspace ustawia workspaceAccess. Wartość none jest domyślna i daje narzędziom tylko workspace sandboxa, ro montuje workspace agenta do odczytu pod /agent, a rw daje zapis pod /workspace. Backend dockerowy startuje z restrykcyjnymi wartościami: network ustawiony na none, czyli brak ruchu wychodzącego, readOnlyRoot włączone i zrzucone capability. Obraz sandboxa budujesz skryptem scripts/sandbox-setup.sh, a w instalacji dockerowej włącza go OPENCLAW_SANDBOX=1 przed uruchomieniem setup.sh.
Dokumentacja nie udaje, że sandbox jest granicą bezpieczeństwa. Ogranicza dostęp do plików i procesów, gdy model zrobi coś głupiego, i na tym kończy się jego rola — sam gateway zostaje poza nim. Osobne wyjście awaryjne stanowi tools.elevated — uruchamia exec poza sandboxem i obchodzi całą tę warstwę. Trzymaj tools.elevated.enabled na false, a jeśli musisz go włączyć, tools.elevated.allowFrom ma być wąskie.
Twarda podstawa na start wygląda tak: gateway.mode local, gateway.bind loopback, gateway.auth.mode token, session.dmScope ustawione na per-channel-peer, tools.profile na messaging, tools.fs.workspaceOnly na true, tools.exec.security na deny i tools.exec.ask na always, tools.elevated.enabled na false. Do tego dmPolicy pairing na kanałach i requireMention w grupach.
Po stronie kanałów są dwa szczegóły, które lubią zaskakiwać. Tryb dmPolicy „open” wymaga jawnego wpisu „*” na allowliście kanału — bez niego wiadomości nadal będą blokowane. A w grupach działa groupAllowFrom; allowFrom pełni tam tylko rolę fallbacku. Ustawienie samego allowFrom i zdziwienie, że nic nie przechodzi, to klasyk.
{
agents: {
defaults: {
sandbox: { mode: "all", scope: "agent", backend: "docker", workspaceAccess: "none" }
}
},
tools: {
profile: "messaging",
fs: { workspaceOnly: true },
exec: { security: "deny", ask: "always" },
elevated: { enabled: false }
}
}openclaw security audit robi to, czego nie chce Ci się sprawdzać ręcznie
Zamiast przechodzić powyższą listę z pamięci, odpal openclaw security audit. Komenda wykonuje ponad 80 sprawdzeń, każde z własnym identyfikatorem checkId i przypisaną wagą: critical, warn albo info. Przy każdym znalezisku widać też, czy istnieje automatyczna naprawa.
Zakres pokrywa dokładnie te miejsca, w których ludzie się mylą. Uprawnienia plików łapią fs.state_dir.perms_world_writable i fs.config.perms_writable. Ekspozycję sieciową i brak auth — gateway.bind_no_auth, gateway.http.no_auth oraz gateway.tailscale_funnel. Control UI — gateway.control_ui.allowed_origins_required i gateway.control_ui.device_auth_disabled. Sandbox — sandbox.dangerous_bind_mount i sandbox.dangerous_network_mode. Politykę wykonywania poleceń — tools.exec.security_full_configured. A dostępność narzędzi z otwartych kanałów — security.exposure.open_channels_with_exec.
Flaga --deep dokłada żywe sondowanie gatewaya i kolektory bezpieczeństwa pluginów, w tym checki plugins.code_safety i skills.code_safety szukające podejrzanych wzorców w kodzie. Do sondowania trzeba podać poświadczenia: --deep --token <token> albo --deep --password <hasło>. Wyjście maszynowe daje --json.
Flaga --fix jest celowo wąska i to jej zaleta. Stosuje naprawy deterministyczne: zaciska uprawnienia do 600 na plikach i 700 na katalogach oraz przestawia otwarte polityki grupowe na allowlisty. Nie rotuje poświadczeń i nie wyłącza narzędzi — takie decyzje zostają po Twojej stronie. Jeśli świadomie akceptujesz jakieś ryzyko, zapisz to w security.audit.suppressions, zamiast uczyć się ignorować czerwony wynik.
Praktyczny moment na uruchomienie audytu jest jeden: przed każdą zmianą ekspozycji sieciowej albo polityki dostępu. Nie po. Różnica polega na tym, że przed zmianą naprawiasz konfigurację, a po zmianie już tylko odtwarzasz, co się wydarzyło.
openclaw security audit
openclaw security audit --deep --token <token>
openclaw security audit --fix
openclaw security audit --jsonKopia zapasowa i plan na noc, w której coś wycieknie
Kopię robisz komendą openclaw backup create z flagą --verify, która waliduje archiwum od razu po utworzeniu. Obejmuje katalog stanu, aktywny plik konfiguracyjny, katalog credentials, katalogi workspace, profile uwierzytelniania, stan sesji i bazy SQLite. Bazy zrzucane są przez online backup API SQLite i kompaktowane przez VACUUM, więc gatewaya nie trzeba zatrzymywać.
Przydatne flagi: --dry-run do podglądu, --json do wyjścia maszynowego, --no-include-workspace, gdy workspace i tak żyje w gicie, oraz --only-config, gdy chcesz zapisać sam plik konfiguracyjny. Flaga --agent <id> nie należy do backup create — używa się jej przy openclaw backup sqlite create. Podkomendy create, list, verify i restore wskazują repozytorium snapshotów flagą --repository <katalog> i to ona jest tam obowiązkowa.
Plan na incydent ma trzy fazy i dobrze mieć go zapisany, zanim będzie potrzebny. Powstrzymanie: zatrzymujesz gateway, ustawiasz gateway.bind na loopback, wyłączasz ryzykowne polityki DM i grup. Rotacja: zmieniasz gateway.auth.token, gateway.remote.token oraz poświadczenia dostawców. Przegląd: czytasz openclaw logs, transkrypty sesji z ~/.openclaw/agents/<agentId>/sessions/ oraz ostatnie zmiany w konfiguracji.
Odrzucone konfiguracje zostają obok pliku jako openclaw.json.rejected.<timestamp>, a nadpisane jako *.clobbered.*. Gateway przyjmuje wyłącznie pliki w pełni zgodne ze schematem, więc literówka nie nadpisze działającej wersji. Do przywrócenia ostatniej znanej dobrej kopii służy openclaw doctor --fix.
Jeśli utrzymywanie tej warstwy samodzielnie nie jest pracą, którą chcesz wykonywać, istnieje wariant chmurowy — ClawLabs uruchamia instancję OpenClaw w chmurze EU (Hetzner), z własnymi kluczami API w modelu BYOK i DPA na żądanie, plany od 399 zł miesięcznie. Sam OpenClaw jest darmowy i otwarty, więc wybór sprowadza się do tego, kto ma pilnować portów, tokenów i kopii.
mkdir -p ~/Backups/openclaw
openclaw backup create --output ~/Backups/openclaw --verify
openclaw backup sqlite list --repository ~/Backups/openclaw-sqlite
openclaw doctor --fixCo warto zapamiętać
- Domyślny gateway.bind to loopback, a w kontenerze oznacza to 127.0.0.1 wewnątrz kontenera — przy zwykłym -p 18789:18789 gateway pozostaje nieosiągalny, dopóki nie zmienisz bindu i nie dołożysz uwierzytelniania.
- Publikowanie portu przez -p omija reguły INPUT hosta: decyzje zapadają w łańcuchu DOCKER-USER, a reguły IPv6 trzeba dopisać osobno w /etc/ufw/after6.rules.
- gateway.auth.mode przyjmuje none, token, password i trusted-proxy; token generuje openclaw doctor --generate-gateway-token, a proxy musi nadpisywać X-Forwarded-For, nie dopisywać do niego.
- Uprawnienia z dokumentacji: 700 na ~/.openclaw, 600 na openclaw.json, 600 na ~/.openclaw/credentials/** i 600 na ~/.openclaw/state/openclaw.sqlite, gdzie leżą tokeny MCP.
- Sandbox jest domyślnie wyłączony; sandbox.mode ma wartości off, non-main i all, scope domyślnie agent, backend domyślnie docker, workspaceAccess domyślnie none. tools.elevated omija sandbox całkowicie.
- openclaw security audit wykonuje ponad 80 sprawdzeń z identyfikatorami takimi jak gateway.bind_no_auth czy sandbox.dangerous_network_mode; --fix zaciska uprawnienia do 600/700 i zamienia otwarte polityki grup na allowlisty, ale nie rotuje poświadczeń.
Częste pytania
Uruchomiłem OpenClaw w Dockerze z -p 18789:18789 i nie mogę wejść na dashboard. Co jest nie tak?+
Prawie na pewno bind. Domyślny loopback oznacza 127.0.0.1 wewnątrz kontenera, a ruch z mapowania portu przychodzi na interfejs kontenera, więc nikt go nie odbiera. Trzeba świadomie zmienić gateway.bind i od razu włączyć uwierzytelnianie, bo bez auth gateway odmówi bindowania poza pętlą. Oficjalny skrypt ./scripts/docker/setup.sh robi obie rzeczy naraz: ustawia bind na lan i generuje token podczas onboardingu.
Mam UFW i przepuszczone tylko 22, 80 i 443. Czy port 18789 z kontenera jest zablokowany?+
Niekoniecznie. Publikowanie portów przez -p przepuszcza ruch przez łańcuchy forwardowania Dockera, a nie tylko przez INPUT hosta, więc reguły UFW mogą go w ogóle nie dotykać. Reguły trzeba dopisać w łańcuchu DOCKER-USER, a dla IPv6 osobno w /etc/ufw/after6.rules. Przy pisaniu nie zaszywaj nazw interfejsów w rodzaju eth0 — różnią się między obrazami VPS-ów, a reguła, która nie pasuje, po cichu niczego nie blokuje.
Czy sandbox wystarczy, żeby agent nie zrobił szkód na serwerze?+
Nie wystarczy sam z siebie. Dokumentacja opisuje sandbox jako mechanizm, który realnie ogranicza dostęp do plików i procesów, ale nie jest doskonałą granicą bezpieczeństwa. Sam gateway działa poza sandboxem, a tools.elevated uruchamia exec z jego pominięciem. Sandbox trzeba więc łączyć z polityką narzędzi: tools.profile, tools.fs.workspaceOnly, tools.exec.security oraz tools.elevated.enabled ustawione na false.
Co zrobić najpierw, gdy podejrzewam, że ktoś dostał się do instancji?+
Trzy fazy w tej kolejności. Powstrzymanie: zatrzymaj gateway, ustaw gateway.bind na loopback, wyłącz ryzykowne polityki DM i grup. Rotacja: zmień gateway.auth.token, gateway.remote.token oraz poświadczenia dostawców modeli i kanałów. Przegląd: przejrzyj openclaw logs, transkrypty sesji w ~/.openclaw/agents/<agentId>/sessions/ i ostatnie zmiany konfiguracji. Dopiero potem wracaj do normalnej ekspozycji.
Źródła danych z tej lekcji
- OpenClaw Docs — Gateway Security (bind, auth, sekrety, incydenty)
- OpenClaw Docs — Security audit checks
- OpenClaw Docs — CLI: security
- OpenClaw Docs — Sandboxing
- OpenClaw Docs — Docker install
- OpenClaw Docs — Configuration reference
- OpenClaw Docs — CLI: backup
- ClawLabs — konfiguracja OpenClaw po polsku
- ClawLabs — bezpieczeństwo i dane
Chcesz to przećwiczyć na żywo?
Uruchom własnego agenta i wypróbuj to, o czym przed chwilą przeczytałeś. Pierwsza subskrypcja pakietu Premium ma 5 dni za darmo, a kurs czytasz dalej niezależnie od tego.
Zobacz plany