Як встановити n8n на VPS через Docker
Покрокова інструкція встановлення n8n з Docker Compose та Postgres. Як уникнути помилок з WEBHOOK_URL та налаштувати HTTPS через reverse proxy.
Що ви створюєте
n8n — це інструмент для автоматизації робочих процесів. Це візуальний редактор, де тригер (webhook, розклад або відправка форми) запускає ланцюжок вузлів (nodes). Ці вузли викликають API, змінюють структуру даних та записують їх в інші системи. n8n став стандартом для робочих процесів з AI-агентами, оскільки він підтримує всіх постачальників моделей та баз даних без необхідності писати власний сервіс. Один docker run отримує готовий редактор за дві хвилини. Цей посібник присвячений іншим дев'яноста відсотках: забезпеченню стабільності за допомогою Postgres замість стандартного файлу SQLite, налаштуванню доступу через HTTPS та — найпоширенішій помилці — налаштуванню webhook так, щоб вони надавали URL-адресу, доступну ззовні.
Готовий стек складається з двох контейнерів в одній мережі Docker: самого n8n та бази даних Postgres, де зберігаються робочі процеси та облікові дані. Reverse proxy на хост-машині завершує TLS-з'єднання та перенаправляє запити на n8n на localhost. Таким чином, ніщо не доступне через інтернет напряму, окрім цього проксі. Цей стек входить до списку 2026 self-hosting shortlist.
Попередні вимоги та реальні обмеження
Вам потрібен VPS із мінімум 1 GB RAM. Плануйте 2 GB для виконання складних робочих процесів, оскільки виконання сценаріїв та середовище Node.js споживають багато пам'яті. Якщо OOM killer завершить роботу контейнера під час виконання, це ускладнить навчання. Для початку достатньо одного vCPU.
Вам потрібен домен або піддомен — наприклад, n8n.example.com — з A-записом, що вказує на публічну IP-адресу VPS. Домен має розв'язуватися до запиту сертифіката. Порти 80 та 443 мають бути відкриті для проксі; порт n8n 5678 не повинен бути доступний з інтернету. Вам потрібні Docker Engine та плагін Compose; якщо docker compose version видає помилку docker: 'compose' is not a docker command, ви використовуєте старий окремий бінарний файл, а плагін — це sudo apt install docker-compose-plugin.
SQLite підходить для тестування, Postgres — для критично важливих завдань
Базова база даних n8n — це файл SQLite за шляхом /home/node/.n8n/database.sqlite. Для первинного тестування цього достатньо. Якщо не підмонтувати volume, дані будуть втрачені після першого перестворення container. Перехід на Postgres потрібен не через швидкість. SQLite використовує блокування для одного запису. Це призводить до помилки SQLITE_BUSY: database is locked, якщо запущено кілька workflow одночасно або використовується queue mode. Postgres не має таких обмежень, підтримує коректне резервне копіювання через pg_dump і є рекомендованим рішенням згідно з документацією n8n для стабільної роботи. Зміна бази у майбутньому потребуватиме ручної міграції даних. Якщо сервер важливий, використовуйте Postgres відразу.
DNS та firewall
Спочатку налаштуйте запис та відкрийте порти. Це потрібно, щоб етап отримання сертифіката не завершився помилкою через неможливість розпізнати ім'я.
dig +short n8n.example.com
curl -s ifconfig.me
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow OpenSSH
sudo ufw enableНе відкривайте порт 5678. Файл compose прив'язує n8n до 127.0.0.1:5678, тому доступ до нього має мати лише reverse proxy хоста. Відкриття порту через ufw allow 5678 порушить цю ізоляцію.
Файл Compose
Створіть робочу директорію та docker-compose.yml. Це весь стек — два сервіси, одна приватна мережа та два іменовані volume.
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- n8n_net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
interval: 10s
timeout: 5s
retries: 5
n8n:
image: docker.n8n.io/n8nio/n8n:2.29.10
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
- N8N_HOST=n8n.example.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_PROXY_HOPS=1
- GENERIC_TIMEZONE=Europe/London
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- n8n_data:/home/node/.n8n
networks:
- n8n_net
depends_on:
postgres:
condition: service_healthy
volumes:
postgres_data:
n8n_data:
networks:
n8n_net:Важливі технічні примітки. DB_POSTGRESDB_HOST=postgres — це назва сервісу, яку Docker визначає у спільній мережі, а не localhost, що всередині контейнера n8n означає сам n8n. Використання depends_on з condition: service_healthy запобігає спробам n8n підключитися до Postgres під час завантаження; без цього n8n не знайде базу даних і завершить роботу. Іменований volume n8n_data за шляхом /home/node/.n8n зберігає ключ шифрування та, у випадку SQLite, саму базу даних — це єдиний каталог, який не можна втрачати. Використовуйте конкретну версію образу, не використовуйте latest; причини наведено в розділі про оновлення нижче.
Файл secrets
Ніколи не зберігайте паролі у compose file. Зберігайте їх у файлі .env поруч із ним, який Compose зчитує автоматично. Генеруйте паролі так, щоб вони були дійсно випадковими.
printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)" > .env
printf 'N8N_ENCRYPTION_KEY=%s\n' "$(openssl rand -hex 32)" >> .env
chmod 600 .envN8N_ENCRYPTION_KEY — це найважливіший рядок у цьому файлі. Це ключ, за допомогою якого шифруються всі збережені облікові дані. Встановіть його явно, а не дозволяйте n8n генерувати його самостійно. Значення, яке ви згенеруєте самі, можна записати та відновити. Після того як n8n зашифрує свої перші облікові дані за допомогою цього ключа, його зміна зробить всі облікові дані неможливими для розшифрування — тому встановіть його один раз зараз і більше не змінюйте цей рядок.
Змінні оточення, що визначають роботу webhooks
Чотири змінні керують тим, як n8n представляє себе зовнішньому світу. Неправильне налаштування цих змінних є найпоширенішою проблемою у зверненнях до служби підтримки n8n.
N8N_HOST— це публічний hostname,n8n.example.com. Якщо залишити значення за замовчуваннямlocalhostпри використанні проксі, редактор намагатиметься завантажити власний API зlocalhostу вашому браузері, що призведе до помилки.N8N_PROTOCOL=httpsвказує n8n, що сервіс працює через TLS, тому n8n маркує сесійний cookieSecureта формуєhttps://URL.N8N_PORT=5678— це порт, який n8n використовує для прослуховування всередині контейнера. Це не публічний порт; порт 443 належить проксі.WEBHOOK_URL=https://n8n.example.com/— найбільш критична змінна. n8n формує адреси webhook, які ви вставляєте у Stripe, GitHub або будь-який інший зовнішній сервіс, на основі цих значень. Якщо змінна не встановлена або має неправильне значення, n8n використовуєN8N_HOST:N8N_PORTі видає вамhttps://n8n.example.com:5678/webhook/...або, що гірше,http://localhost:5678/webhook/.... Ці адреси виглядають правдоподібно і не викликають помилок при відображенні, але вони недоступні з інтернету, тому запити від зовнішніх сервісів просто не доходять. Встановіть її як точний публічний base URL із завершальним слешем, а потім переконайтеся, що вузол webhook відображає URL без порту.
N8N_PROXY_HOPS=1 дозволяє Express-серверу n8n довіряти одному проксі-серверу. Це необхідно, щоб обмеження частоти запитів (rate-limiting) та функції визначення IP-адреси клієнта бачили реальну адресу, а не адресу проксі. Одна змінна, яку ми навмисно не встановлюємо, — це N8N_RUNNERS_ENABLED. Task runners (виконавці завдань) — процес, у якому n8n запускає логіку Code-node в окремому ізольованому середовищі — є стандартними з версії 1.69 і є обов'язковими у версіях 2.x, на які посилається цей посібник, тому старий метод активації застарів. Якщо ви встановите її зараз, n8n лише виведе повідомлення про те, що її слід видалити.
Перший запуск
docker compose up -d
docker compose ps
docker compose logs -f n8nУспішне перше завантаження завершується рядком Editor is now accessible via:, перед яким має бути рядок n8n ready on ..., port 5678. docker compose ps має відображати обидва контейнери Up, де postgres позначено як (healthy). Якщо n8n потрапляє у Restarting цикл, перевірте логи — зазвичай це пов'язано з підключенням до бази даних або правами доступу до volume, описаними нижче.
TLS з реверс-проксі
n8n використовує HTTP на порту 5678; HTTPS має термінувати сторонній сервіс. Є два основні варіанти.
Якщо ви вже використовуєте кілька контейнерів, розмістіть n8n за реверс-проксі Traefik з автоматичним випуском TLS-сертифікатів за допомогою кількох labels — Traefik сам запитує та оновлює сертифікат.
Якщо це єдиний додаток на сервері, простіше налаштувати nginx virtual host із сертифікатом Let's Encrypt. Використовуйте налаштування Certbot та nginx TLS для Ubuntu 24.04, щоб отримати сертифікат, а потім додайте цей server block:
server {
listen 443 ssl;
server_name n8n.example.com;
ssl_certificate /etc/letsencrypt/live/n8n.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600;
client_max_body_size 16m;
}
}Заголовки Upgrade та Connection "upgrade" є обов'язковими. n8n передає оновлення виконання в редактор через WebSocket; без цих двох рядків сторінка входу завантажиться, а потім зависне з банером "lost-connection". proxy_read_timeout 3600 запобігає перериванню тривалих процесів через стандартний ліміт nginx у 60 секунд. Заголовок X-Forwarded-Proto $scheme працює разом із N8N_PROXY_HOPS=1: він повідомляє n8n, що оригінальний запит був через HTTPS, хоча проксі звертається до нього через HTTP. Це потрібно, щоб n8n не вважав з'єднання незахищеним і не відхиляв власні cookie.
Ваш перший робочий процес для перевірки
Відкрийте https://n8n.example.com/, створіть обліковий запис власника (наступний розділ) та побудуйте найпростіший робочий процес для перевірки шляху передачі даних: вхідний webhook, HTTP-запит та відповідь.
- Додайте вузол Webhook. Встановіть метод на
POSTта шлях, наприкладhello. Система відобразить два URL-адреси: Test URL та Production URL. Це причина половини звернень щодо непрацюючих webhook. Test URL відповідає лише на один виклик і тільки поки натиснуто Listen for test event; після цього термін дії закінчується. Production URL відповідає щоразу, коли робочий процес має статус Active. - Додайте після нього вузол HTTP Request, спрямований на будь-який публічний JSON API. GET-запит до
https://api.github.com/zenповерне рядок з одного рядка, цього достатньо. - Додайте вузол Respond to Webhook. У налаштуваннях вузла Webhook змініть параметр Respond на "Using Respond to Webhook node", щоб викликаюча сторона отримала вихідні дані від HTTP-вузла.
- Увімкніть статус Active для робочого процесу (у верхньому правому куті) та зробіть виклик:
curl -X POST https://n8n.example.com/webhook/hello. Ви маєте отримати ту саму строку — POST-запит, виклик API та відповідь. Це типова структура більшості реальних автоматизацій.
Варіант за розкладом замінює вузол Webhook на Schedule Trigger і викликає endpoint моделі. Використання Ollama running on the same VPS — зручний спосіб створити систему щонічногочного резюмування.
Управління користувачами, а не basic auth
У старих посібниках n8n рекомендують встановлювати N8N_BASIC_AUTH_ACTIVE=true. Ці змінні були видалені в n8n 1.0 і зараз не виконують жодних функцій. Сучасна автентифікація базується на обліковому записі власника (owner account): під час першого завантаження редактора n8n вимагає створити власника з email та паролем. Цей етап є обов'язковим — анонімний режим відсутній. Створюйте обліковий запис одразу після першого запуску, перш ніж надавати URL іншим користувачам: у проміжку між docker compose up та відправкою першої форми інстанс може бути захоплений будь-ким, хто першим отримає до нього доступ. Додатковий рівень basic-auth через reverse-proxy є доцільним, але це лише другий фактор, а не основна автентифікація.
Backups: спочатку ключ шифрування, потім база даних
Необхідно зробити резервну копію двох об'єктів, які мають різний рівень важливості.
N8N_ENCRYPTION_KEY. Усі облікові дані, які ви зберігаєте в n8n — API tokens, паролі до баз даних, OAuth secrets — шифруються у стані спокою за допомогою цього ключа. Робочі процеси (workflows) у Postgres стануть непридатними без цього ключа: якщо відновити базу даних на новому сервері з іншим ключем, n8n не зможе розшифрувати жодні облікові дані. Відновлення або скидання у такому разі неможливі. Файл .env містить цей ключ; скопіюйте його на інший носій — ідеально підійде запис у password-manager — одразу після створення. Це найважливіша резервна копія.
База даних Postgres, яка містить workflows, історію виконання та самі зашифровані облікові дані:
docker compose exec -T postgres pg_dump -U n8n -d n8n \
| gzip > n8n-db-$(date +%F).sql.gzНалаштуйте виконання цієї команди за розкладом і копіюйте дамп за межі сервера. Для відновлення на новому VPS: запустіть стек один раз, щоб база даних була створена, зупиніть n8n, завантажте дамп за допомогою psql, додайте той самий N8N_ENCRYPTION_KEY у .env і запустіть n8n. Поєднання того самого ключа та дампу дасть робочий екземпляр; новий ключ призведе до втрати доступу до всіх облікових даних у workflows.
Upgrades: pin the tag
Файл compose навмисно використовує n8nio/n8n:2.29.10 замість latest. n8n випускає нові minor-версії майже щотижня. Між релізами іноді змінюється схема бази даних або поведінка нод. Через це latest означає, що автоматичне завантаження образу може призвести до міграції бази даних одразу після запуску. Зафіксуйте версію, прочитайте release notes перед оновленням — n8n вказує там про breaking changes — і виконуйте оновлення свідомо:
docker compose exec -T postgres pg_dump -U n8n -d n8n | gzip > pre-upgrade.sql.gz
# edit the image tag in docker-compose.yml, then:
docker compose pull n8n
docker compose up -d n8n
docker compose logs -f n8nПерехід на нові major-версії є найбільш критичним. Наприклад, у версії 2.0 параметр N8N_BLOCK_ENV_ACCESS_IN_NODE було змінено на true за замовчуванням. Будь-яка Code node, яка читала process.env, втратить доступ, доки ви не повернете значення на false. У цьому ж релізі було впроваджено суворі дозволи для файлу налаштувань. Прочитайте сторінку 2.0 breaking-changes перед переходом на нову major-версію. n8n автоматично запускає всі необхідні міграції бази даних під час старту. Саме тому виконання pg_dump перед оновленням є обов'язковим. Оскільки облікові дані зберігаються в зашифрованому вигляді з ключем у .env, а дані знаходяться в Postgres, контейнери є тимчасовими: оновлення виконується шляхом їх заміни, а відкат — шляхом фіксації попереднього тегу та відновлення дампу.
Режими відмови та рядки, які ви побачите
The requested webhook "POST hello" is not registered. Помилка 404 при виклику webhook, чий workflow не є Active, або при виклику тестового шляху, коли ніхто не очікує на подію. Тестові шляхи (/webhook-test/...) відповідають лише тоді, коли натиснуто "Listen for test event"; робочі шляхи (/webhook/...) відповідають лише тоді, коли перемикач workflow увімкнено. Суміжний This webhook is not registered for GET requests. Did you mean to make a POST request? означає неправильний метод — вузол очікує POST, а ви надіслали GET.
URL-адреса webhook показує :5678 або localhost. Вузол відображає https://n8n.example.com:5678/webhook/... або http://localhost:5678/.... WEBHOOK_URL не встановлено або вказано невірно, тому n8n створив адресу на основі N8N_HOST:N8N_PORT замість вашої публічної базової адреси. Встановіть WEBHOOK_URL=https://n8n.example.com/, перестворіть контейнер за допомогою docker compose up -d, і порт зникне.
There was a problem loading init data у браузері. Редактор завантажився, але не може зв'язатися з власним backend API. При використанні проксі це майже завжди помилка N8N_HOST або WEBHOOK_URL, відсутність заголовків WebSocket Upgrade у проксі, або невідповідність N8N_PROTOCOL параметрам підключення. Перевірте чотири публічні змінні та переконайтеся, що проксі перенаправляє Upgrade та Connection.
password authentication failed for user "n8n" у логах, контейнер перезапускається. Пароль, який надсилає n8n, не збігається з паролем, використаним при ініціалізації бази даних. Проблема в тому, що Postgres зчитує POSTGRES_PASSWORD лише під час ініціалізації порожньої директорії даних. Запустіть стек один раз, потім змініть POSTGRES_PASSWORD у .env, і існуючий том postgres_data все ще міститиме старий пароль. Поверніть оригінальний пароль або, якщо вам не потрібно зберігати дані, видаліть docker compose down та docker volume rm том postgres, а потім запустіть його заново.
EACCES: permission denied, open '/home/node/.n8n/config' під час запуску. n8n працює від імені користувача node (UID 1000) і не може записати дані в директорію конфігурації. Це трапляється, коли використовується bind-mount папки хоста (./n8n_data:/home/node/.n8n), яка належить root. Використовуйте іменований том, вказаний вище, або, якщо ви використовуєте bind mount, спочатку виконайте sudo chown -R 1000:1000 ./n8n_data.
Permissions 0644 for n8n settings file /home/node/.n8n/config are too wide. Changing permissions to 0600.. Починаючи з версії 2.x, n8n за замовчуванням застосовує 0600 до цього файлу налаштувань і виправляє його самостійно під час завантаження — цей рядок у логах означає, що режим уже виправлено, зазвичай після bind mount або після віднов better з файлу з вільними правами доступу. Жодних дій не потрібно; встановлюйте N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false лише якщо ваша файлова система дійсно не підтримує права доступу.
Mismatching encryption keys — повний рядок вказує, що ключ шифрування у файлі налаштувань /home/node/.n8n/config не збігається з N8N_ENCRYPTION_KEY у вашому оточенні. Ключ у вашому оточенні відрізняється від того, який n8n записав у свій том даних під час попереднього запуску — найчастіше через те, що n8n згенерував випадковий ключ під час раннього запуску, коли змінна не була встановлена, а потім ви встановили інший ключ. Поверніть оригінальний ключ у .env або, якщо у вас немає збережених облікових даних, які варто зберігати, видаліть файл config всередині тому n8n_data і дозвольте n8n перегенерувати його — врахуйте, що існуючі облікові дані стануть нечитабельними.
Баннер входу про безпечні cookies: Your n8n server is configured to use a secure cookie, however you are either visiting this via an insecure URL, or using Safari. Ви встановили N8N_PROTOCOL=https, але звернулися до n8n через звичайний HTTP — зазвичай шляхом прямого звернення до IP та порту замість HTTPS проксі. Звертайтеся через https://n8n.example.com/. Встановлюйте N8N_SECURE_COOKIE=false лише у випадку, якщо ви дійсно не можете використовувати HTTPS, і ніколи не робіть цього на пристроях, доступних з інтернету.
Щоб додати мовну модель у ці workflow, див. building AI workflows with Claude and n8n.
FAQ
Чи варто використовувати SQLite або Postgres для n8n?
SQLite (за замовчуванням) підходить для ознайомлення з n8n або для персонального використання, коли виконується лише один workflow одночасно. Переходьте на Postgres для будь-яких критично важливих завдань: блокування одного запису у SQLite викликає database is locked при паралельних запитах, а Postgres забезпечує коректне резервне копіювання за допомогою pg_dump. Міграція пізніше виконується вручну, тому якщо стабільність сервера важлива, одразу використовуйте Postgres.
Чому мої n8n webhooks не спрацьовують?
Майже завжди це WEBHOOK_URL. Якщо параметр не встановлено або він вказаний невірно, n8n створює адреси webhook на основі N8N_HOST:N8N_PORT — часто з :5678 або localhost — які виглядають коректно, але недоступні з інтернету, тому запити не доходять. Встановіть WEBHOOK_URL=https://n8n.example.com/ і переконайтеся, що вузол відображає URL без порту. Друга причина — виклик webhook, для якого workflow не переведено в режим Active, що повертає The requested webhook ... is not registered..
Що саме потрібно резервувати в n8n?
Дві речі. N8N_ENCRYPTION_KEY з вашого файлу .env, оскільки всі збережені облікові дані зашифровані за допомогою нього; втрата цього файлу зробить їх неможливими для розшифрування — скопіюйте його з сервера одразу після створення. Також зробіть pg_dump бази даних Postgres, де зберігаються workflow, історія та облікові дані. Для відновлення потрібні обидва компоненти: той самий ключ та дамп.
Як налаштувати n8n через HTTPS?
n8n працює через HTTP на порту 5678; зворотний проксі (reverse proxy) перед ним завершує TLS-з'єднання. Прив'яжіть n8n до 127.0.0.1:5678, щоб доступ мав лише проксі, а потім використовуйте Traefik з автоматичними сертифікатами або nginx з сертифікатом Let's Encrypt. Встановіть N8N_PROTOCOL=https та WEBHOOK_URL=https://your-host/ і переконайтеся, що проксі передає заголовки WebSocket Upgrade, інакше редактор зависне.
Як безпечно оновити n8n?
Замість latest використовуйте конкретний тег образу, спочатку зробіть pg_dump, оскільки n8n автоматично запускає міграції під час старту, прочитайте примітки до релізу на предмет несумісних змін, потім змініть тег і запустіть docker compose pull n8n && docker compose up -d n8n. Контейнер є тимчасовим, тому для відкату використовуйте попередній тег і відновіть дамп, зроблений перед оновленням.