AiAdvisors
Wszystkie przewodniki
//Przewodnik

Jak zabezpieczyć self-hosted n8n na Dockerze?

Self-hosted n8n trzyma klucze do wszystkich systemów, które automatyzuje, więc zabezpiecza się go jak serwer z hasłami firmy. Minimum to tylko porty 80 i 443 przez reverse proxy z HTTPS, konto właściciela z 2FA, klucz szyfrowania z kopią poza serwerem i uwierzytelnienie na każdym webhooku. Na poziomie maksymalnym edytor jest dostępny tylko przez VPN, a z internetu przychodzą wyłącznie uwierzytelnione webhooki przez bramkę z WAF.

Aktualizacja
22.10.2026
Publikacja
22.10.2026
12 min czytania
Autor
Romuald Członkowski

Który poziom zabezpieczeń wybrać?

Nie każda instancja potrzebuje VPN i bramki z WAF. Podział, którego używam przy wdrożeniach:

PoziomDla kogoCo obejmuje
Podstawowykażda instancja, także testowaporty 80 i 443, HTTPS, konto właściciela z 2FA, klucz szyfrowania z kopią, uwierzytelnione webhooki, aktualizacje i backup
Firmowyn8n z danymi klientów, fakturami, dostępem do CRMpodstawowy plus utwardzony serwer z fail2ban, wyłączone public API, ochrona SSRF, izolowany węzeł Code, regularny audyt
Maksymalnyn8n z dostępem do poczty, dysków i systemów wewnętrznych albo w dużej organizacjifirmowy plus edytor tylko przez VPN, bramka z WAF przed webhookami, allowlista ruchu wychodzącego, osobna instancja do integracji zewnętrznych

Kolejne sekcje idą od poziomu podstawowego do maksymalnego. Ustawienia, które pomijam na niższych poziomach, opisuję tam, gdzie zaczynają mieć sens.

Czy n8n jest bezpieczny i co w nim chronisz?

Ustawienia domyślne n8n są rozsądne. O bezpieczeństwie decyduje konfiguracja, bo n8n jest celem atrakcyjniejszym niż typowa aplikacja webowa. Atakujący, który przejmie instancję, dostaje:

  • Credentiale. Klucze API i tokeny OAuth do CRM, poczty, księgowości, bazy danych. Jedna instancja trzyma dostęp do wszystkiego, co automatyzuje.
  • Wykonanie kodu. Węzeł Code uruchamia JavaScript i Pythona na Twoim serwerze.
  • Dostęp do sieci wewnętrznej. Węzeł HTTP Request z serwera n8n sięga tam, gdzie z internetu się nie da: do bazy w tej samej sieci Dockera, do usług wewnętrznych, do adresów metadanych chmury.
  • Dane z historii wykonań. Każde wykonanie zapisuje dane wejściowe i wyjściowe, często z danymi osobowymi.

Do instancji prowadzą trzy drogi: edytor z API, webhooki i formularze oraz sam serwer. Checklista poniżej zamyka je po kolei.

Które porty wystawić do internetu?

Tylko 80 i 443, i tylko dla reverse proxy. Przy instalacji przez Docker Compose przed n8n stoi Caddy albo inny reverse proxy, który wystawia certyfikat HTTPS i przekazuje ruch do kontenera n8n w prywatnej sieci Dockera. Porty 5678 (n8n), 5432 (Postgres) i 6379 (Redis w queue mode) nie mają mapowania na hosta.

Uwaga na pułapkę: port opublikowany przez Dockera w sekcji ports omija reguły ufw, bo Docker dopisuje własne reguły iptables przed regułami ufw. Jeśli ktoś „na chwilę” doda 5678:5678, n8n jest dostępny z internetu bez HTTPS, nawet gdy ufw status pokazuje zamknięty port. Dlatego pilnuję dwóch warstw:

  1. W compose: mapowanie portów ma tylko reverse proxy.
  2. W firewallu dostawcy chmury (Hetzner Cloud Firewall, AWS Security Group, Azure NSG): przychodzące tylko 80, 443 i SSH. Ten firewall stoi przed serwerem, więc Docker go nie obejdzie.

Reverse proxy dokłada nagłówki bezpieczeństwa: Strict-Transport-Security, X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN i Referrer-Policy.

Jak utwardzić serwer pod n8n?

Kontener n8n jest tak bezpieczny jak maszyna, na której stoi. Na każdym serwerze robię to samo:

  • SSH tylko kluczem. W /etc/ssh/sshd_config ustawiam PasswordAuthentication no i PermitRootLogin no, a administruję z osobnego konta z sudo.
  • fail2ban na SSH. Po kilku nieudanych próbach logowania adres IP dostaje blokadę na określony czas. Przy logowaniu kluczem atakujący i tak nie wejdzie, ale fail2ban ucina automatyczne skanowanie i szum w logach.
  • fail2ban na logach reverse proxy, opcjonalnie. Można blokować adresy, które seriami próbują logować się do edytora. Ruch do kontenerów przechodzi jednak przez łańcuch iptables Dockera, więc akcja fail2ban musi dopisywać reguły do łańcucha DOCKER-USER, a nie do domyślnego INPUT. Inaczej blokada niczego nie zablokuje. Na poziomie maksymalnym ten punkt odpada, bo edytora nie ma w internecie.
  • Automatyczne łatki systemu. Na Ubuntu i Debianie unattended-upgrades instaluje poprawki bezpieczeństwa pakietów. Obrazu n8n to nie dotyczy, ten aktualizuję osobno.
  • Ostrożnie z grupą docker. Kto jest w tej grupie, ten w praktyce ma uprawnienia roota, bo może uruchomić kontener z całym systemem plików hosta. Dodaję do niej tylko osoby, które administrują serwerem.
  • Nic poza n8n. Serwer z n8n nie hostuje przy okazji strony firmowej ani panelu do bazy. Każda dodatkowa usługa to dodatkowa droga do credentiali.

Co zrobić w pierwszych minutach po instalacji?

Założyć konto właściciela, zanim ktokolwiek inny pozna adres. Świeża instancja n8n pokazuje formularz konfiguracji właściciela i instancję przejmuje ten, kto wypełni go pierwszy. Nieskonfigurowany n8n wystawiony do internetu to wyścig, a boty śledzą nowo wystawione certyfikaty HTTPS, więc nowy adres nie pozostaje długo nieznany.

Zaraz potem:

  • 2FA dla właściciela i każdego użytkownika. W darmowej Community Edition każdy włącza je sam. Wymuszenie 2FA dla całej instancji wymaga płatnego planu.
  • SMTP. Bez skonfigurowanej poczty linki z zaproszeniami trzeba przekazywać ręcznie, a użytkownicy nie zresetują sami hasła.

Przy wdrożeniach automatycznych konto właściciela da się założyć zmiennymi środowiskowymi z hashem hasła (N8N_INSTANCE_OWNER_MANAGED_BY_ENV), wtedy wyścigu w ogóle nie ma.

Jak chronić klucz szyfrowania n8n?

N8N_ENCRYPTION_KEY szyfruje wszystkie credentiale zapisane w bazie. To najważniejszy sekret instancji i trzy zasady są tu bezwzględne:

  1. Ustaw go jawnie przed pierwszym startem. Jeśli go nie podasz, n8n wygeneruje losowy klucz i zapisze go w wolumenie z danymi. Podanie innego klucza później psuje odczyt wszystkich credentiali.
  2. Trzymaj kopię poza serwerem, w menedżerze haseł albo sejfie na sekrety. Kopia bazy bez pasującego klucza jest bezużyteczna.
  3. Nie zmieniaj go edycją pliku .env. To nie jest rotacja, tylko utrata wszystkich credentiali. n8n ma osobną, jednokierunkową procedurę rotacji kluczy, którą uruchamia się po pełnym backupie bazy.

Reszta sekretów podlega tym samym regułom higieny: każda instancja dostaje świeże hasła wygenerowane na serwerze (openssl rand -base64 32), sekrety są tylko w pliku .env z uprawnieniami 600, a .env nigdy nie trafia do repozytorium. Nie kopiuję klucza ani .env z jednej instancji klienta na drugą.

Które zmienne środowiskowe ustawić?

Część ustawień chroni przed błędami konfiguracji za reverse proxy, część wyłącza funkcje, których nie używasz. Mój zestaw startowy:

ZmiennaWartośćPo co
N8N_PROTOCOL, N8N_PROXY_HOPShttps, 1n8n wie, że stoi za proxy, i ufa nagłówkom X-Forwarded-*
N8N_SECURE_COOKIEtrueciasteczko sesji tylko przez HTTPS
N8N_WEBHOOK_URL, N8N_EDITOR_BASE_URLpubliczny adres HTTPSbez tego n8n podaje adresy webhooków i callbacków z localhost; od n8n 2.35 starsza nazwa WEBHOOK_URL jest przestarzała
N8N_DIAGNOSTICS_ENABLEDfalsewyłącza anonimową telemetrię
N8N_BLOCK_ENV_ACCESS_IN_NODEtruewęzły i wyrażenia nie czytają zmiennych środowiskowych kontenera, czyli Twoich sekretów
N8N_PUBLIC_API_DISABLEDtrue, jeśli nieużywanewyłącza publiczne REST API; zostaw włączone, jeśli łączysz n8n-mcp albo agentów AI
N8N_SSRF_PROTECTION_ENABLEDtrueblokuje węzłom HTTP dostęp do adresów prywatnych, pętli zwrotnej i metadanych chmury; potrzebne wyjątki dopisujesz do allowlisty
N8N_COMMUNITY_PACKAGES_ENABLEDfalse, jeśli nieużywanewęzły społeczności to cudzy kod z dostępem do Twoich credentiali
N8N_TEMPLATES_ENABLEDfalse na poziomie maksymalnymwyłącza szablony i związane z nimi połączenia do serwerów n8n
EXECUTIONS_DATA_PRUNE, EXECUTIONS_DATA_MAX_AGEtrue, np. 336 godzinhistoria wykonań z danymi osobowymi nie leży w bazie bez końca

Dwie pułapki:

  • NODES_EXCLUDE. Od n8n 2.0 węzeł Execute Command jest domyślnie zablokowany. Ustawienie NODES_EXCLUDE=[], które wygląda na „nic nie wykluczaj”, włącza go z powrotem. Jeśli chcesz zablokować więcej węzłów, wypisz je wszystkie w tablicy, łącznie z Execute Command.
  • /metrics. Po włączeniu N8N_METRICS=true n8n wystawia endpoint z metrykami bez uwierzytelnienia. Reverse proxy przekazuje wszystko, więc metryki stają się publiczne, dopóki nie zablokujesz tej ścieżki w proxy.

Jak zabezpieczyć węzeł Code?

Węzeł Code wykonuje kod w task runnerze. W domyślnym trybie wewnętrznym runner to proces potomny n8n z tymi samymi uprawnieniami, więc nie daje izolacji. Dokumentacja n8n rezerwuje ten tryb dla instancji bez wrażliwych danych.

Na poziomie firmowym przechodzę na tryb zewnętrzny: obok n8n działa osobny kontener n8nio/runners, w tej samej wersji co n8n. To też jedyny sposób, żeby węzły Code w Pythonie działały na standardowym obrazie.

Drugi element to allowlisty modułów. W Pythonie domyślnie nie przechodzi nawet import json, więc pojawia się pokusa, żeby wpisać *. Na instancji, na której workflowy edytuje więcej niż jedna osoba, nigdy tego nie robię, bo * obejmuje os, subprocess i socket, czyli pełny dostęp do systemu i sieci. Dopisuję konkretne moduły, których workflowy potrzebują.

Jak zabezpieczyć webhooki w n8n?

Każdy produkcyjny webhook wymaga uwierzytelnienia. Węzeł Webhook obsługuje Basic Auth, Header Auth i JWT. Dla integracji systemów najprostszy jest nagłówek z długim, losowym tokenem, zapisany jako credential, a nie wpisany na sztywno w węźle.

Druga warstwa to opcja IP(s) Allowlist w węźle Webhook. Żądanie spoza listy dostaje odpowiedź 403. Ma to sens, gdy nadawca publikuje swoje adresy IP. Za reverse proxy działa tylko przy poprawnym N8N_PROXY_HOPS, bo inaczej n8n widzi adres proxy zamiast adresu nadawcy.

Najważniejszy fakt w tej sekcji: n8n nie ma ustawienia, które wymusza uwierzytelnienie na wszystkich webhookach. Każdy użytkownik z uprawnieniami do edycji może zbudować publiczny webhook bez zabezpieczeń. Na poziomie podstawowym i firmowym ratuje to audyt: polecenie n8n audit (albo narzędzie audytu w n8n-mcp) wskazuje niezabezpieczone webhooki. Uruchamiam go regularnie, a na instancjach firmowych według harmonogramu, z alertem do osoby odpowiedzialnej. Na poziomie maksymalnym wymuszenie robi bramka przed n8n, opisuję ją niżej.

Tę samą zasadę stosuję do formularzy: formularz wewnętrzny dostaje Basic Auth w węźle Form Trigger.

Jak aktualizować n8n i robić kopie zapasowe?

Aktualizacje. Wersję obrazu przypinam w .env zamiast używać latest, żeby aktualizacja była decyzją, a nie skutkiem ubocznym innej zmiany. Dokumentacja n8n zaleca aktualizację co najmniej raz w miesiącu. Przed każdą czytam listę zmian, a krytyczne poprawki bezpieczeństwa instaluję szybciej.

Backup przed aktualizacją, nie po. n8n przy starcie automatycznie uruchamia migracje bazy i działają one tylko w jedną stronę. Po aktualizacji powrót do poprzedniej wersji wymaga więc starego obrazu i kopii bazy sprzed aktualizacji.

Co jest w kopii. Dwie rzeczy, które mają sens tylko razem: klucz szyfrowania i dane (wolumen z SQLite albo pg_dump bazy Postgres). Kopie lądują poza serwerem, a odtworzenie testuję przynajmniej raz, na czystej maszynie.

Jak zabezpieczyć n8n na poziomie maksymalnym?

Ten wariant projektuję dla instancji, które mają być dostępne z internetu dla webhooków i asystentów AI, a jednocześnie pracują w dużej organizacji albo blisko wrażliwych danych. Opieram go na architekturze, którą niedawno projektowałem dla jednego z klientów.

Dwie instancje zamiast jednej

Instancja z dostępem do poczty, dysków firmowych i systemów wewnętrznych nie jest wystawiona do internetu w ogóle. Integracje zewnętrzne (platformy reklamowe, CRM w chmurze, strony www) obsługuje druga, osobna instancja, która nie ma żadnej drogi do tamtych danych: nie przechowuje credentiali do Microsoft 365 ani Google Workspace i nie ma połączenia sieciowego z zasobami wewnętrznymi.

Po co komplikować? Bo wtedy w najgorszym scenariuszu wyciekają dane, które firma i tak trzyma u zewnętrznych dostawców, a nie skrzynki zarządu. Przy jednej instancji każda luka w webhooku jest luką w dostępie do wszystkiego.

Edytor tylko przez VPN

Edytor, API i webhooki testowe są dostępne wyłącznie z sieci firmowej albo przez VPN (WireGuard, Tailscale, firmowy VPN), z logowaniem SSO, jeśli licencja na to pozwala. Alternatywą jest model zero-trust, na przykład Cloudflare Access, w którym dostęp dostaje zalogowana osoba, a nie każdy w sieci. SSH też działa tylko przez VPN, a port 22 jest zamknięty dla internetu w firewallu chmury.

Rzeczy, które łatwo przy tym odciąć przez przypadek:

  • Callbacki OAuth. Otwiera je przeglądarka osoby, która podłącza credential, więc przez VPN działają.
  • n8n-mcp i agenci AI potrzebują publicznego API (/api/v1/). Muszą działać w sieci VPN albo przechodzić przez Cloudflare Access tokenem serwisowym. Agent poza VPN dostanie odmowę połączenia, która wygląda dokładnie jak zły adres instancji.

Najczystszy układ to dwie subdomeny: jedna publiczna tylko dla webhooków i formularzy, druga dla edytora, widoczna wyłącznie z VPN. Jeśli musi zostać jedna domena, reverse proxy przepuszcza z internetu tylko ścieżki produkcyjne. Domyślnie są to /webhook/, /webhook-waiting/, /form/ i /form-waiting/, a resztę, łącznie z /webhook-test/, /form-test/, /rest/ i /api/v1/, kieruje tylko do ruchu z VPN. Ścieżki można zmienić zmiennymi N8N_ENDPOINT_*, więc listę sprawdzam w konfiguracji konkretnej instancji, a układ testuję przed wdrożeniem.

Bramka z WAF przed webhookami

Ponieważ n8n sam nie wymusza uwierzytelnienia webhooków, robi to bramka przed nim: Azure Application Gateway, AWS WAF, Cloudflare albo inny reverse proxy z regułami. Bramka publikuje tylko ścieżkę produkcyjnych webhooków i odrzuca każde żądanie bez wymaganego nagłówka albo tokenu. Webhook bez zabezpieczeń jest wtedy nieosiągalny z internetu, nawet jeśli ktoś go zbuduje.

Za bramką zostają dwie warstwy z poziomu firmowego: uwierzytelnienie w każdym węźle Webhook, allowlista IP tam, gdzie nadawca publikuje adresy, i audyt n8n audit uruchamiany według harmonogramu, z alertem do IT.

Formularze

Formularz n8n otwiera przeglądarka człowieka, a ta nie wyśle tajnego nagłówka. Reguła bramki „bez tokenu nie wpuszczam” zablokuje więc każdy publiczny formularz. Formularze dostają osobne reguły:

  • Formularz wewnętrzny zostaje za VPN, z Basic Auth w Form Trigger.
  • Formularz publiczny przechodzi przez bramkę bez wymogu tokenu, ale z limitem liczby żądań z jednego adresu i regułami WAF przeciw botom.

Strony formularzy i hostowanego czatu ładują też pliki statyczne n8n. Przy ostrym filtrowaniu ścieżek formularz potrafi się nie wyrenderować, dlatego ten element testuję w przeglądarce spoza VPN, zanim zamknę resztę.

Endpoint MCP dla Claude i ChatGPT

Jeśli zespół buduje albo uruchamia workflowy z firmowych kont Claude lub ChatGPT, te usługi łączą się z serwerem MCP z chmury dostawcy, a nie z komputera pracownika. Endpoint MCP instancji (/mcp-server/http) idzie wtedy przez tę samą bramkę, z trzema ograniczeniami:

  • przyjmuje tylko użytkowników zalogowanych przez OAuth,
  • opcjonalnie tylko z zakresów IP publikowanych przez dostawcę AI,
  • pokazuje wyłącznie workflowy jawnie włączone do MCP.

Wariant bez publicznego MCP: pracownicy używają lokalnych konektorów w Claude Desktop albo Codex na swoich komputerach, przez VPN. Wtedy żadna chmura dostawcy AI nie łączy się z instancją.

Ruch wychodzący

Reverse proxy widzi tylko ruch przychodzący. Połączenia, które n8n wykonuje do API, wychodzą z kontenera bezpośrednio, więc ich ograniczenie ustawia się w firewallu chmury albo przez proxy wyjściowe, a nie w Caddy czy Nginx.

Allowlista ruchu wychodzącego (tylko domeny używanych platform, np. Google, Meta, CRM) ogranicza szkody po przejęciu instancji, bo dane nie mają dokąd wyjść. Ma sens na instancji, która rozmawia z kilkoma znanymi usługami. Przy instancji ogólnego przeznaczenia, z dziesiątkami integracji, lista staje się nie do utrzymania. Wtedy wystarcza ochrona SSRF i wyłączenie zbędnych połączeń zgodnie z poradnikiem n8n o izolacji instancji.

Pozostałe ustawienia poziomu maksymalnego

  • Krytyczne poprawki bezpieczeństwa n8n w ciągu 72 godzin od wydania.
  • Wyłączone węzły społeczności, szablony i telemetria.
  • Neutralna domena, która nie zdradza, czyja to instancja.

Najczęstsze błędy

  • Port 5678 opublikowany „na chwilę”. Docker omija ufw, więc n8n jest dostępny bez HTTPS, choć firewall wygląda na zamknięty.
  • Brak firewalla u dostawcy chmury. Jedyna warstwa, której Docker nie obejdzie.
  • Instancja bez właściciela wystawiona do internetu. Przejmuje ją ten, kto pierwszy otworzy adres.
  • Klucz szyfrowania tylko na serwerze. Awaria dysku oznacza wtedy utratę wszystkich credentiali, nawet przy aktualnym backupie bazy.
  • latest w obrazie. Każde docker compose pull, na przykład w skrypcie, który miał tylko zmienić ustawienie, aktualizuje wtedy n8n i uruchamia migrację bazy, której nikt nie planował.
  • Publiczne webhooki bez uwierzytelnienia i tokeny wpisane na sztywno w węzłach. n8n audit znajduje je w kilka sekund.
  • NODES_EXCLUDE=[], które po cichu włącza Execute Command.
  • N8N_METRICS=true bez blokady w proxy, czyli publiczne metryki instancji.

Częste pytania

Czy n8n jest bezpieczny?
Sam n8n ma rozsądne ustawienia domyślne: szyfruje zapisane credentiale, od wersji 2.0 blokuje węzeł Execute Command i uruchamia kod w osobnym procesie. O bezpieczeństwie self-hosted instancji decyduje jednak konfiguracja: które porty są otwarte, czy edytor jest publiczny, czy webhooki wymagają uwierzytelnienia i czy klucz szyfrowania ma kopię. n8n nie wymusza uwierzytelnienia webhooków, to trzeba zrobić samemu.
Co się stanie, gdy zgubię klucz szyfrowania n8n?
Wszystkie zapisane credentiale staną się nie do odczytania i trzeba je wprowadzić od nowa. Kopia bazy danych bez pasującego klucza nie pomoże. Dlatego N8N_ENCRYPTION_KEY ustawia się jawnie przed pierwszym startem i przechowuje poza serwerem, na przykład w menedżerze haseł.
Czy n8n za VPN może przyjmować webhooki?
Tak. Za VPN chowa się edytor i API, a ścieżki produkcyjnych webhooków i formularzy publikuje się osobno, najlepiej na oddzielnej subdomenie albo przez bramkę z WAF, która przepuszcza tylko żądania z poprawnym tokenem. Callbacki OAuth otwiera przeglądarka użytkownika, więc przez VPN działają normalnie.
Czy Cloudflare Access wystarczy zamiast VPN?
Do ochrony edytora tak, to model zero-trust: dostęp dostaje zalogowana osoba, a nie każdy z dostępem do sieci. Ścieżki webhooków trzeba wtedy wyłączyć spod Access, bo zewnętrzne systemy nie przejdą logowania, i chronić je uwierzytelnieniem w węźle Webhook. Agenci AI i n8n-mcp przechodzą przez Access tokenem serwisowym.
Czy darmowa wersja n8n ma 2FA?
Tak, każdy użytkownik Community Edition może włączyć sobie uwierzytelnianie dwuskładnikowe. Płatne jest dopiero wymuszenie 2FA dla wszystkich użytkowników instancji.
Jak często aktualizować self-hosted n8n?
Dokumentacja n8n zaleca co najmniej raz w miesiącu, żeby nie przeskakiwać wielu wersji naraz. Przed każdą aktualizacją czytam listę zmian i robię kopię bazy, bo migracje bazy działają tylko w jedną stronę. Krytyczne poprawki bezpieczeństwa instaluję szybciej, w ciągu kilku dni.

Dane, na których opiera się ten przewodnik

Liczby z n8n AI Automation Index odświeżane co tydzień.

Chcesz, żeby ktoś zabezpieczył Twoje n8n?

Stawiam self-hosted n8n z zabezpieczeniami z tej checklisty i przeglądam instancje, które już działają. Pierwszy etap wdrożenia kosztuje od 1 000 do 2 000 euro i kończy się instancją z kopiami zapasowymi i jedną integracją w produkcji.

Automatyzacja procesów w n8n
//Kontakt

Porozmawiajmy o AI w Twoim biznesie

Opowiedz Alicji, co zajmuje czas w Twojej firmie. Umówi Cię na bezpłatną konsultację strategiczną ze mną.

Wolisz kalendarz? Wybierz termin

albo napisz: romuald@aiadvisors.pl · +48 695 263 884