n8n: czym jest i jak zainstalować go na VPS-ie z Docker Compose

9 min czytania
Tropic
n8n: czym jest i jak zainstalować go na VPS-ie z Docker Compose

Language: pl

n8n na VPS-ie: własna platforma automatyzacji bez ręcznej pracy

Do strony trafia zapytanie. n8n sprawdza dane, wyszukuje duplikaty, tworzy transakcję, przygotowuje odpowiedź roboczą z pomocą AI i powiadamia menedżera w Telegramie. Człowiek pojawia się tylko wtedy, gdy potrzebna jest decyzja — nie po to, aby przenosić dane między kartami przeglądarki.

Poniżej wyjaśniamy, jak działa n8n i jak zainstalować go na VPS-ie z Docker Compose, PostgreSQL, HTTPS oraz odizolowanym wykonywaniem kodu.

n8n w siedmiu krokach

Minimalny plan uruchomienia:

  1. Utwórz VPS-a i skieruj na niego subdomenę, na przykład n8n.example.com.
  2. Zainstaluj Docker i Docker Compose.
  3. Uruchom n8n z PostgreSQL, zewnętrznym task runnerem i Caddy.
  4. Otwórz interfejs przez HTTPS i utwórz konto właściciela.
  5. Podłącz Telegram, CRM, pocztę lub dowolne zewnętrzne API.
  6. Skonfiguruj obsługę błędów i czas przechowywania danych wykonań.
  7. Zautomatyzuj kopie zapasowe bazy danych, danych oraz klucza szyfrowania.

W przypadku małej instalacji produkcyjnej rozsądnie jest zacząć od 2 vCPU i 4 GB RAM-u. 2 GB często wystarczą do testów, ale PostgreSQL, Docker i równoległe procesy szybko zużywają pozostały zapas.

Czym jest n8n i jak działa

n8n to platforma do automatyzacji procesów. Workflow buduje się z węzłów: jeden rozpoczyna proces, kolejne pobierają i przekształcają dane, a ostatni wykonuje działanie.

Prosty workflow wygląda tak:

Webhook → data validation → CRM → Telegram → website response

Łańcuch może zostać uruchomiony przez webhook, harmonogram, wiadomość e-mail, wiadomość lub zdarzenie w zewnętrznej usłudze. Między węzłami dostępne są warunki, pętle, filtry, oczekiwanie i obsługa błędów.

Jedną z mocnych stron n8n jest to, że automatyzacja nie ogranicza się do gotowych integracji. Z dowolną usługą mającą API połączysz się przez HTTP Request, a własną logikę możesz napisać w węźle Code za pomocą JavaScriptu lub Pythona. Dzięki temu n8n znajduje się pomiędzy prostym kreatorem no-code a własnym kodem po stronie serwera.

Dlaczego to coś więcej niż przekazywanie danych

n8n przydaje się, gdy proces obejmuje kilka systemów i wymaga decyzji:

form → validation → duplicate search → AI assessment → manager approval → CRM

Człowieka można pozostawić tylko w punkcie kontrolnym. Na przykład AI przygotowuje odpowiedź, ale wiadomość trafia do klienta dopiero po zatwierdzeniu przez pracownika.

Typowe zastosowania:

  • sprzedaż i wsparcie: zbieranie zapytań, przydzielanie leadów i tworzenie transakcji;
  • treści i AI: tworzenie wersji roboczych, klasyfikowanie zapytań i publikowanie po akceptacji;
  • DevOps: powiadomienia o awariach, webhooki Git i kontrole API;
  • operacje wewnętrzne: synchronizacja arkuszy, poczty, kalendarzy i systemów firmowych.

Instalacja self-hosted daje kontrolę nad procesem i bazą danych, ale nie sprawia, że zewnętrzne usługi stają się lokalne. Dane wysłane do Telegrama, CRM-u lub chmurowego modelu AI opuszczają VPS.

n8n Cloud czy własny serwer

Parametrn8n Cloudn8n na VPS-ie
UruchomienieBez konfiguracji serweraWymaga domeny, Dockera i HTTPS
AktualizacjeObsługuje je n8nOdpowiada za nie właściciel
Baza danych i plikiW infrastrukturze usługiNa wybranym serwerze
SkalowanieZależnie od planu chmurowegoKonfigurowane niezależnie
OdpowiedzialnośćMniej administracjiKopie zapasowe, bezpieczeństwo i monitoring należą do właściciela
Najlepsze zastosowanieSzybki start bez DevOpsKontrola, dostosowanie i procesy działające stale

Community Edition można hostować bezpłatnie i używać do procesów prywatnych oraz wewnętrznych procesów biznesowych. n8n nie jest jednak rozpowszechniane na tradycyjnej licencji open source, lecz na licencji fair-code Sustainable Use License. Pozwala ona na użytek wewnętrzny i modyfikacje, ale nie umożliwia prostego wdrożenia n8n, dodania własnego logo i sprzedawania dostępu jako samodzielnego SaaS-u. W przypadku takiego produktu warunki licencji trzeba przeanalizować osobno.

Wymagania serwera n8n

Obciążenie zależy od ilości danych, równoległości i rodzaju operacji. Pliki, długie listy, węzły Code i workflowy AI wymagają więcej pamięci niż przekazywanie małych ładunków JSON między API.

ScenariuszKonfiguracja początkowa
Testy i prywatne workflowy tekstowe1 vCPU, 2 GB RAM, 20 GB NVMe
Mała instalacja produkcyjna2 vCPU, 4 GB RAM, 25–40 GB NVMe
Procesy równoległe, AI lub pliki4 vCPU, 8 GB RAM lub więcej
Wiele procesów workerów w trybie kolejkiDobierz do liczby wykonań

SQLite nadaje się do nauki i małej konfiguracji z pojedynczą instancją. PostgreSQL jest wygodniejszy w produkcji: kopie zapasowe są prostsze, a późniejsze przejście do trybu kolejki łatwiejsze.

Jak zainstalować n8n na VPS-ie

W przykładzie używamy Ubuntu 24.04, PostgreSQL, Caddy i zewnętrznego task runnera. Zastąp n8n.example.com oraz strefę czasową własnymi wartościami.

1. Skonfiguruj DNS i przygotuj serwer

Utwórz rekord DNS A wskazujący na adres IPv4 VPS-a, a następnie połącz się przez SSH:

ssh root@SERVER_IP
apt update && apt upgrade -y
apt install -y ca-certificates curl ufw openssl

Zainstaluj Docker Engine i wtyczkę Compose z oficjalnego repozytorium:

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

cat > /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

apt update
apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
docker compose version

Zezwól tylko na SSH, HTTP i HTTPS:

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Nie zamykaj bieżącej sesji SSH, dopóki nie potwierdzisz, że nowe połączenie działa.

2. Utwórz zmienne środowiskowe

Przygotuj katalog:

mkdir -p /opt/n8n
cd /opt/n8n

Utwórz plik .env. Poniższe polecenia od razu wygenerują osobne losowe sekrety dla PostgreSQL, szyfrowania n8n i task runnera:

cat > .env <<EOF
N8N_VERSION=stable
N8N_HOST=n8n.example.com
GENERIC_TIMEZONE=Europe/Berlin

POSTGRES_DB=n8n
POSTGRES_USER=n8n
POSTGRES_PASSWORD=$(openssl rand -hex 32)

N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
RUNNERS_AUTH_TOKEN=$(openssl rand -hex 32)
EOF

chmod 600 .env

Tag stable jest wygodny przy pierwszym uruchomieniu. Po sprawdzeniu instalacji lepiej przypiąć konkretną wersję n8n, aby kolejna aktualizacja obrazu nie nastąpiła niespodziewanie.

Nie możesz utracić N8N_ENCRYPTION_KEY. n8n używa tego klucza do szyfrowania zapisanych haseł, tokenów i innych danych uwierzytelniających. Jeśli odtworzysz samo PostgreSQL bez klucza, rekordy pozostaną w bazie, ale n8n nie będzie w stanie ich odczytać.

3. Utwórz plik Docker Compose

Utwórz compose.yaml:

services:
  postgres:
    image: postgres:18-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      PGDATA: /var/lib/postgresql/data
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
    restart: unless-stopped
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_PORT: "5432"
      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
      DB_POSTGRESDB_USER: ${POSTGRES_USER}
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}

      N8N_HOST: ${N8N_HOST}
      N8N_PORT: "5678"
      N8N_PROTOCOL: https
      N8N_EDITOR_BASE_URL: https://${N8N_HOST}
      N8N_WEBHOOK_URL: https://${N8N_HOST}/
      N8N_PROXY_HOPS: "1"
      GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
      TZ: ${GENERIC_TIMEZONE}

      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: "true"
      N8N_BLOCK_ENV_ACCESS_IN_NODE: "true"

      N8N_RUNNERS_MODE: external
      N8N_RUNNERS_AUTH_TOKEN: ${RUNNERS_AUTH_TOKEN}
      N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0

      EXECUTIONS_DATA_PRUNE: "true"
      EXECUTIONS_DATA_MAX_AGE: "168"
      EXECUTIONS_DATA_PRUNE_MAX_COUNT: "10000"
    volumes:
      - n8n_data:/home/node/.n8n
    expose:
      - "5678"
    depends_on:
      postgres:
        condition: service_healthy

  n8n-runner:
    image: n8nio/runners:${N8N_VERSION}
    restart: unless-stopped
    environment:
      N8N_RUNNERS_AUTH_TOKEN: ${RUNNERS_AUTH_TOKEN}
      N8N_RUNNERS_TASK_BROKER_URI: http://n8n:5679
    depends_on:
      - n8n

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    environment:
      N8N_HOST: ${N8N_HOST}
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - n8n

volumes:
  postgres_data:
    name: n8n_postgres_data
  n8n_data:
    name: n8n_data
  caddy_data:
    name: n8n_caddy_data
  caddy_config:
    name: n8n_caddy_config

Zewnętrzny task runner wykonuje kod oddzielnie od głównego procesu n8n. Jest to bezpieczniejsze niż tryb wewnętrzny i zmniejsza ryzyko, że błąd w węźle Code wpłynie na edytor oraz obsługę webhooków.

4. Włącz HTTPS

Utwórz Caddyfile:

{$N8N_HOST} {
    reverse_proxy n8n:5678
}

Caddy automatycznie pobierze certyfikat TLS, jeśli DNS już wskazuje na VPS-a, a porty 80 i 443 są dostępne. Wewnętrzny port 5678 nie jest wystawiony do internetu: z zewnątrz dostępne są tylko porty 80 i 443, a Caddy łączy się z n8n przez sieć Dockera.

Zmienne N8N_WEBHOOK_URL i N8N_PROXY_HOPS są potrzebne, aby edytor generował prawidłowe publiczne adresy webhooków i ufał nagłówkom od jednego reverse proxy.

5. Uruchom n8n

Sprawdź końcową konfigurację i uruchom kontenery:

docker compose config
docker compose up -d
docker compose ps
docker compose logs --tail=100 n8n caddy

Otwórz:

https://n8n.example.com

Utwórz konto właściciela. Nie udostępniaj jego hasła współpracownikom: w pracy zespołowej używaj osobnych kont i przyznawaj każdej osobie tylko potrzebne uprawnienia.

Pierwszy użyteczny workflow

Dobrym testem jest obsługa zapytania ze strony internetowej:

  1. Dodaj węzeł Webhook z metodą POST.
  2. Użyj Edit Fields, aby pozostawić tylko nazwę, adres e-mail i źródło.
  3. Za pomocą węzła If odrzuć zapytanie bez wymaganych danych.
  4. Utwórz transakcję w CRM-ie lub wyślij żądanie przez HTTP Request.
  5. Dodaj powiadomienie Telegram.
  6. Zakończ łańcuch węzłem Respond to Webhook.
  7. Po testach aktywuj workflow i zastąp testowy webhook adresem produkcyjnym.

Ten przykład od razu sprawdza domenę, HTTPS, przychodzące żądania, dane uwierzytelniające i zewnętrzną integrację. Następnie dodaj osobny Error Workflow, który powiadomi Cię o awarii głównego łańcucha.

Zabezpieczenie n8n po instalacji

Zainstalowana instancja n8n nie jest automatycznie niezawodna. Po uruchomieniu upewnij się, że:

  • edytor jest dostępny wyłącznie przez HTTPS;
  • plik .env ma uprawnienia 600 i nie jest dodany do Gita;
  • zewnętrzne klucze API mają minimalny wymagany zakres uprawnień;
  • każdy webhook sprawdza podpis lub sekret źródła;
  • historia wykonań jest automatycznie usuwana;
  • błędy w krytycznych workflowach trafiają do administratora.

Węzły społecznościowe są instalowane jako pakiety i mogą uzyskać dostęp do danych workflowów oraz serwera. Nie dodawaj nieznanych węzłów bez ich sprawdzenia. Jeśli ich nie potrzebujesz, wyłącz je za pomocą N8N_COMMUNITY_PACKAGES_ENABLED=false.

Uruchom wbudowany audyt:

docker compose exec n8n n8n audit

Pomoże on znaleźć niezabezpieczone webhooki, ryzykowne węzły i problemy z danymi uwierzytelniającymi, ale nie zastępuje ręcznego przeglądu.

Historia wykonań i dane osobowe

n8n przechowuje dane wejściowe i wyjściowe na potrzeby debugowania. Razem z nimi w bazie mogą pozostać wiadomości e-mail, numery telefonów, dokumenty i odpowiedzi API.

W powyższej konfiguracji wykonania są usuwane po siedmiu dniach, a ich liczba jest ograniczona do 10 000. W przypadku wrażliwych procesów wybierz okres przechowywania zgodnie z polityką retencji danych i usuń niepotrzebne pola przed zakończeniem workflowu.

Kopie zapasowe i aktualizacje

Odtworzenie wymaga zrzutu PostgreSQL, wolumenu n8n_data, plików konfiguracyjnych oraz pliku .env zawierającego N8N_ENCRYPTION_KEY. Przed kopiowaniem zatrzymaj procesory, pozostawiając PostgreSQL uruchomione. Spowoduje to krótką przerwę w wykonywaniu workflowów:

cd /opt/n8n
mkdir -p backup
docker compose stop n8n n8n-runner

docker compose exec -T postgres sh -c \
  'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' \
  | gzip > "backup/n8n-db-$(date +%F).sql.gz"

docker run --rm \
  -v n8n_data:/source:ro \
  -v "$PWD/backup":/backup \
  alpine sh -c \
  'tar -czf /backup/n8n-data-$(date +%F).tar.gz -C /source .'

tar -czf "backup/n8n-config-$(date +%F).tar.gz" \
  .env compose.yaml Caddyfile

docker compose start n8n n8n-runner

Archiwum zawierające .env ma sekrety: zaszyfruj je i przechowuj poza VPS-em. Co jakiś czas sprawdzaj kopię, wykonując testowe odtworzenie.

Przed aktualizacją wykonaj kopię zapasową i przeczytaj informacje o wydaniu:

cd /opt/n8n
docker compose pull
docker compose up -d
docker compose ps

Task runner i główny kontener muszą używać tego samego tagu wersji.

Kiedy potrzebne jest skalowanie

Nie zaczynaj od Redis i kilku workerów, zanim nie pojawi się rzeczywiste obciążenie. Pojedyncza instancja z PostgreSQL jest łatwiejsza w utrzymaniu i zwykle wystarcza do małych procesów wewnętrznych.

Tryb kolejki staje się potrzebny, gdy długie zadania opóźniają webhooki, wiele workflowów uruchamia się jednocześnie albo przetwarzanie plików regularnie zużywa całą dostępną pamięć. W takiej konfiguracji główna instancja odbiera zdarzenia, Redis rozdziela zadania, a workery wykonują je równolegle. Wszystkie komponenty muszą łączyć się z tą samą bazą PostgreSQL i używać tego samego N8N_ENCRYPTION_KEY.

Jaki VPS wybrać dla n8n

Dla n8n, PostgreSQL, Caddy i task runnera razem rozsądnie jest zacząć od 2 vCPU, 4 GB RAM-u i dysku NVMe. W tropic.host plan Light odpowiada tej konfiguracji: 2 vCPU, 4 GB RAM-u i 25 GB NVMe. Wystarczy to do pierwszych produkcyjnych workflowów bez intensywnego przetwarzania plików.

W przypadku dokumentów, dużych zbiorów danych i wielu równoległych workflowów AI lepszym wyborem będzie 8 GB RAM-u. Ważna jest również stabilna sieć: webhooki, wywołania zwrotne OAuth i zadania harmonogramu muszą być stale dostępne.

Podsumowanie

n8n zamienia powtarzalne operacje w przejrzyste wizualne przepływy: gotowe węzły przyspieszają start, HTTP Request łączy niemal każde API, a węzeł Code pozwala dodać własną logikę.

Wersja self-hosted daje kontrolę nad serwerem i bazą danych, ale wymaga HTTPS, ograniczonych kluczy, czyszczenia historii i sprawdzonych kopii zapasowych. Przechowuj N8N_ENCRYPTION_KEY razem z PostgreSQL: bez niego odtworzone dane uwierzytelniające nie mogą zostać odszyfrowane.

FAQ

Czy z n8n można korzystać bezpłatnie?

Tak. Community Edition można bezpłatnie hostować na własnym serwerze do procesów prywatnych i wewnętrznych. Odsprzedaż hostowanego n8n jako samodzielnego SaaS-u jest ograniczona przez licencję fair-code.

Czy n8n można zainstalować bez domeny?

Do lokalnych testów — tak. W przypadku publicznych webhooków i OAuth lepiej użyć domeny oraz HTTPS.

Ile RAM-u potrzebuje n8n?

Proste prywatne workflowy często działają przy 2 GB RAM-u. Dla n8n z PostgreSQL, Caddy i task runnerem rozsądniejsze będzie 4 GB; pliki i równoległe wykonania mogą wymagać 8 GB lub więcej.

Czy wszystkie dane pozostają na VPS-ie?

Tylko te dane, których workflow nie wysyła dalej. Baza danych i historia wykonań są przechowywane na VPS-ie, ale węzły Telegrama, CRM-u lub zewnętrznego modelu AI wysyłają wybrane dane do odpowiedniej usługi.

Co powinno znaleźć się w kopii zapasowej n8n?

Zrzut PostgreSQL, wolumen n8n_data, compose.yaml, Caddyfile i plik .env zawierający N8N_ENCRYPTION_KEY. Kopię przechowuj poza VPS-em w zaszyfrowanej postaci i sprawdź ją przez odtworzenie.