Blog

n8n self-hosted na Docker Compose: instalacja krok po kroku

Kategoria:

Własną instancję n8n utrzymuję od ponad roku i pracuje na niej dziś ponad 20 przepływów, od porannych raportów po publikację treści na kilku stronach. Sama instalacja zajmuje około godziny. Więcej uwagi wymagają rzeczy, o których łatwo zapomnieć przy pierwszym uruchomieniu: klucz szyfrowania, kopie zapasowe i historia wykonań, która rośnie z każdym przebiegiem. Opisuję całość w kolejności, w jakiej ją konfiguruję.

Czy n8n self-hosted jest darmowy?

Tak. Wersja Community do samodzielnego hostowania nie ma opłat licencyjnych ani limitu wykonań; płacisz za serwer. Licencja fair-code ogranicza głównie odsprzedawanie n8n jako usługi, a część funkcji dla większych firm, takich jak logowanie SSO czy osobne środowiska, wymaga płatnej licencji Enterprise. Różnice między własną instalacją a n8n Cloud opisałem w przewodniku n8n: co to jest i jak działa.

Czego potrzebujesz do instalacji?

  • serwera VPS z Linuksem; na start wystarczą 2 vCPU i 4 GB RAM, więcej pamięci potrzebują przepływy, które przetwarzają duże pliki albo setki elementów naraz,
  • Dockera z wtyczką Compose,
  • domeny albo subdomeny, na przykład n8n.twojafirma.pl, skierowanej na adres serwera.

Plik docker-compose.yml dla n8n z PostgreSQL

Domyślnie n8n zapisuje dane w SQLite. Do instalacji firmowej wybieram PostgreSQL: lepiej znosi równoległe wykonania i łatwiej go kopiować.

services:
  postgres:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: n8n
    volumes:
      - db_data:/var/lib/postgresql/data

  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_DATABASE: n8n
      DB_POSTGRESDB_USER: n8n
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_HOST: n8n.twojafirma.pl
      N8N_PROTOCOL: https
      WEBHOOK_URL: https://n8n.twojafirma.pl/
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      GENERIC_TIMEZONE: Europe/Warsaw
      TZ: Europe/Warsaw
      EXECUTIONS_DATA_PRUNE: "true"
      EXECUTIONS_DATA_MAX_AGE: "336"
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres

volumes:
  db_data:
  n8n_data:

Port 5678 wystawiam tylko na 127.0.0.1, więc z internetu n8n jest dostępny wyłącznie przez serwer pośredniczący z HTTPS. W środowisku produkcyjnym podaję też konkretną wersję obrazu zamiast domyślnej najnowszej, żeby termin aktualizacji wybierać samemu.

Hasło bazy i klucz szyfrowania trzymam w pliku .env obok, poza repozytorium:

POSTGRES_PASSWORD=dlugie-losowe-haslo
N8N_ENCRYPTION_KEY=wynik-polecenia-openssl-rand-hex-32

Klucz generuję poleceniem openssl rand -hex 32, a całość uruchamiam przez docker compose up -d.

Co się stanie, gdy zgubisz klucz szyfrowania?

n8n szyfruje tym kluczem zapisane dane dostępowe: hasła, tokeny API i klucze do usług. Bez zmiennej N8N_ENCRYPTION_KEY n8n generuje własny klucz i zapisuje go w wolumenie n8n_data. Przy przenosinach na nowy serwer albo po utracie wolumenu baza z przepływami wstaje, ale zapisanych poświadczeń nie da się odszyfrować i trzeba je wpisać od nowa, jedno po drugim. Klucz przechowuję w menedżerze haseł, osobno od kopii bazy.

Jak wystawić n8n przez HTTPS?

Webhooki i logowanie wymagają HTTPS, więc przed n8n stawiam serwer pośredniczący (reverse proxy). Caddy pobiera certyfikat Let’s Encrypt samodzielnie, a konfiguracja mieści się w trzech liniach:

n8n.twojafirma.pl {
    reverse_proxy 127.0.0.1:5678
}

Nginx albo Traefik zadziałają tak samo, jeśli przekazują połączenia WebSocket, z których korzysta edytor n8n. Zmienna WEBHOOK_URL musi wskazywać adres publiczny. Bez niej węzły webhook pokazują adres z localhost, pod który zewnętrzna usługa niczego nie wyśle.

Kopie zapasowe i aktualizacje

Kopia składa się z dwóch elementów: zrzutu bazy PostgreSQL i klucza szyfrowania. Zrzut bazy uruchamiaj z crona raz na dobę:

docker compose exec -T postgres pg_dump -U n8n n8n > n8n-$(date +%F).sql

Kopię wysyłam poza serwer, bo kopia na tym samym dysku przepada razem z nim. Dodatkowo eksport przepływów do plików (n8n export:workflow --all --output=... uruchomione w kontenerze) daje wersjonowaną historię zmian w repozytorium Git.

Aktualizacja to docker compose pull, a potem docker compose up -d. Przed większą wersją czytam informacje o zmianach, bo nowe wersje n8n potrafią zmienić zachowanie węzłów, a przepływy produkcyjne sprawdzam zaraz po aktualizacji.

Czego pilnuję po instalacji?

  • Historia wykonań. n8n zapisuje wejście i wyjście każdego węzła. W historii jednego z moich przepływów znalazłem token dostępu zwrócony przez API dostawcy danych. Przy przepływach, które dotykają danych dostępowych albo osobowych, wyłączam w ustawieniach przepływu zapisywanie udanych wykonań, a zmienną EXECUTIONS_DATA_MAX_AGE ograniczam, jak długo n8n przechowuje resztę (wartość 336 to 14 dni).
  • Alerty o błędach. Przepływ, który pada po cichu, wygląda z zewnątrz tak samo jak przepływ, który nie ma nic do zrobienia. Mój radar pozycji w Google przez tydzień kończył się błędem, bo dostawca danych przeniósł swoje API pod nowy adres, a wyszło to dopiero przy przeglądzie stanu stron. Na takie sytuacje n8n ma przepływ błędów: węzeł Error Trigger w osobnym przepływie, wskazanym w ustawieniach przepływów produkcyjnych, który przy każdej porażce wysyła alert na komunikator.
  • Dostęp do panelu. Silne hasła, uwierzytelnianie dwuskładnikowe dla kont i baza danych niewystawiona do internetu.

Kiedy lepiej wybrać n8n Cloud?

Gdy w firmie brakuje osoby, która raz w miesiącu zaktualizuje kontener i sprawdzi, czy kopie się wykonują. Chmura zdejmuje z Ciebie administrację w zamian za abonament z limitem wykonań. Przy kilku lekkich przepływach to rozsądny start, a przeniesienie się później na własny serwer oznacza eksport przepływów i ponowne wpisanie poświadczeń.

Jeśli wolisz, żeby instalację i opiekę wziął ktoś inny, wdrażam n8n w firmach razem z konfiguracją serwera, kopiami i monitoringiem. Przykłady przepływów, które pracują u mnie na takiej instalacji, zebrałem w tekście n8n: przykłady użycia.