Установка n8n на свой сервер: пошагово (Docker, PostgreSQL, HTTPS)
Решение принято: n8n будет работать на вашем сервере, а не в облаке. Когда это выгодно и сколько экономит, разобрано в статье свой сервер n8n: когда self-hosted выгоднее облака. Здесь другой вопрос: как поставить n8n так, чтобы через полгода, после первого сбоя или обновления, не пришлось собирать всё заново.
Инструкция собрана по документации docs.n8n.io на 20 октября 2026 года. Стабильная версия по документации - 2.44.4, минорные версии выходят почти каждую неделю, поэтому номер версии сверьте перед установкой.
Короткий ответ: нужен Linux-сервер с Docker, поддомен и четыре контейнера: n8n, PostgreSQL, task runner и Caddy, который сам выпустит HTTPS-сертификат. Ключ шифрования, адрес вебхуков и часовой пояс задаются в файле .env. Обновление занимает три команды, бэкап состоит из дампа базы и копии ключа вне сервера. Установка под ключ относится к простым задачам: 7-15 тыс. ₽.
Что понадобится до начала
Документация n8n честно предупреждает: свой хостинг рассчитан на тех, кто умеет настраивать серверы, а ошибки стоят потери данных и простоев. Что должно быть под рукой:
| Что | Минимум | Комментарий |
|---|---|---|
| Сервер | Linux, 2 vCPU и 2 ГБ памяти | В гайде по Hetzner документация n8n называет тариф CPX11 с такими параметрами достаточным для большинства задач. Память важнее процессора. |
| Память под n8n Assistant | 4 ГБ и 2 vCPU | Нужно только для встроенного ИИ-помощника с песочницей для кода. |
| Docker | Docker Engine и Compose v2 | Хостинг без root-доступа не подойдёт. |
| Домен | Поддомен с A-записью на IP сервера | Без домена не будет нормального HTTPS и вебхуков. |
| Порты | 80 и 443 открыты, 5678 закрыт снаружи | Порт n8n наружу не публикуется. |
| Доступ | SSH по ключу, пользователь с sudo | Постоянно работать под root не стоит. |
Про деньги сразу: расходы на сервер и сервисы считаются отдельно от установки. VPS с 2 ГБ памяти у российских хостингов на октябрь 2026 года стоит примерно от 1 до 4 тыс. ₽ в месяц в зависимости от линейки тарифов, плюс домен. Сама n8n Community Edition бесплатна.
Шаг 1. Docker и файрвол
Docker Engine и плагин Compose ставятся по официальной инструкции docs.docker.com для вашего дистрибутива. После установки проверьте обе команды, как советует документация n8n:
docker --version
docker compose version
Дальше файрвол. На Ubuntu это ufw: сначала разрешаем SSH, чтобы не отрезать себе доступ, потом веб-порты.
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
Деталь, о которой часто забывают: порты, опубликованные Docker, обходят правила ufw. В документации Docker сказано прямо, что трафик к контейнеру перенаправляется раньше, чем до него доходят правила файрвола. Закрыть порт 5678 через ufw не получится, его нужно не публиковать наружу в самом compose-файле. Ниже так и сделано.
Шаг 2. Домен и DNS
Создайте у регистратора A-запись: имя n8n или другой поддомен, значение - IP сервера. Запускайте контейнеры, когда запись начнёт отвечать: Caddy выпускает сертификат, только если домен уже указывает на сервер, а порты 80 и 443 доступны снаружи.
Шаг 3. Файл .env: ключ шифрования, адрес и часовой пояс
Создайте папку проекта и сгенерируйте два секрета: ключ шифрования и токен для task runner.
mkdir ~/n8n && cd ~/n8n
openssl rand -hex 32
openssl rand -hex 32
Первую строку вставьте в N8N_ENCRYPTION_KEY, вторую в N8N_RUNNERS_AUTH_TOKEN. Файл .env в папке проекта:
# Адрес, по которому будет открываться n8n
N8N_DOMAIN=n8n.example.ru
# Версия n8n: актуальный stable смотрите в документации n8n
N8N_VERSION=2.44.4
# Часовой пояс для расписаний (Europe/Minsk, Asia/Almaty и т.д.)
GENERIC_TIMEZONE=Europe/Moscow
# Ключ шифрования учётных данных: сгенерировать один раз и сохранить вне сервера
N8N_ENCRYPTION_KEY=change-me-encryption-key
# Общий секрет n8n и контейнера task runner
N8N_RUNNERS_AUTH_TOKEN=change-me-runner-token
# PostgreSQL: администратор базы и отдельный пользователь для n8n
POSTGRES_USER=change-me-admin
POSTGRES_PASSWORD=change-me-admin-password
POSTGRES_DB=n8n
POSTGRES_NON_ROOT_USER=change-me-n8n-user
POSTGRES_NON_ROOT_PASSWORD=change-me-n8n-password
После сохранения выполните chmod 600 .env, чтобы файл читал только владелец. Что здесь главное:
- N8N_ENCRYPTION_KEY. Этим ключом n8n шифрует учётные данные перед записью в базу. Если ключ не задать, n8n сгенерирует его сам при первом запуске и сохранит в папке .n8n. Явный ключ в .env проще сохранить отдельно от сервера.
- Адрес вебхуков. За обратным прокси n8n не может сам собрать правильный адрес: он складывает его из протокола, хоста и порта, а снаружи n8n виден на порту 443, а не на 5678. Поэтому адрес задаётся явно переменной N8N_WEBHOOK_URL, в compose-файле ниже он собирается из N8N_DOMAIN.
- GENERIC_TIMEZONE. По умолчанию n8n живёт по времени America/New_York, и расписания сработают по Нью-Йорку. Для Москвы ставят Europe/Moscow, для Минска Europe/Minsk, для Алматы Asia/Almaty. Переменная TZ рядом задаёт системное время контейнера.
- N8N_VERSION. Одна переменная на два образа: n8n и task runner по требованию документации должны быть одной версии.
- Пароли PostgreSQL. Как в официальном примере withPostgres: администратор базы и отдельный пользователь для n8n.
Шаг 4. Docker Compose: n8n, PostgreSQL, task runner и Caddy
Без настроек базы n8n хранит всё в SQLite. Документация прямо пишет: для пробы этого хватит, а для рабочего экземпляра, где сценарии работают круглосуточно, нужен PostgreSQL. Поддерживаются версии 16, 17 и 18. Переносить данные из SQLite в PostgreSQL автоматически n8n не умеет, поэтому базу выбирают до того, как на сервер переедут процессы. PostgreSQL понадобится и позже, когда вырастет нагрузка: режим очереди с воркерами n8n на SQLite не рекомендует, как это устроено, показано в кейсе n8n под нагрузкой.
Скрипт init-data.sh создаёт отдельного пользователя базы для n8n. Он взят из официального примера, упрощены только отступы:
#!/bin/bash
set -e
if [ -n "${POSTGRES_NON_ROOT_USER:-}" ] && [ -n "${POSTGRES_NON_ROOT_PASSWORD:-}" ]; then
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<EOSQL
CREATE USER ${POSTGRES_NON_ROOT_USER} WITH PASSWORD '${POSTGRES_NON_ROOT_PASSWORD}';
GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO ${POSTGRES_NON_ROOT_USER};
GRANT CREATE ON SCHEMA public TO ${POSTGRES_NON_ROOT_USER};
EOSQL
else
echo "SETUP INFO: No Environment variables given!"
fi
Файл compose.yaml в той же папке:
services:
postgres:
image: postgres:18
restart: always
environment:
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
- POSTGRES_NON_ROOT_USER
- POSTGRES_NON_ROOT_PASSWORD
- PGDATA=/var/lib/postgresql/data
volumes:
- db_storage:/var/lib/postgresql/data
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 5s
timeout: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
restart: always
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
- N8N_HOST=${N8N_DOMAIN}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- N8N_WEBHOOK_URL=https://${N8N_DOMAIN}/
- N8N_PROXY_HOPS=1
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${GENERIC_TIMEZONE}
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_RUNNERS_MODE=external
- N8N_RUNNERS_AUTH_TOKEN=${N8N_RUNNERS_AUTH_TOKEN}
- N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
ports:
- "127.0.0.1:5678:5678"
volumes:
- n8n_storage:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
n8n-runner:
image: n8nio/runners:${N8N_VERSION}
restart: always
environment:
- N8N_RUNNERS_AUTH_TOKEN=${N8N_RUNNERS_AUTH_TOKEN}
- N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
depends_on:
- n8n
caddy:
image: caddy:2
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- n8n
volumes:
db_storage:
n8n_storage:
caddy_data:
caddy_config:
Что важно в этом файле:
- postgres:18 и PGDATA. В PostgreSQL 18 поменялось место хранения данных по умолчанию. Строка PGDATA держит базу в папке, которую видит том. Документация предупреждает: без неё PostgreSQL 18 пишет данные мимо тома, и база стартует пустой.
- Порт n8n только на 127.0.0.1. Снаружи к нему не подключиться, Caddy ходит к n8n по внутренней сети Docker. Локальный порт нужен, чтобы проверять n8n с самого сервера.
- Task runner во внешнем режиме. Task runners выполняют код из узла Code, в n8n 2.x они включены по умолчанию. Внутренний режим документация считает небезопасным для рабочих серверов: код из сценария может добраться до базы, ключа шифрования и учётных данных. Поэтому рядом работает отдельный контейнер n8nio/runners той же версии.
Шаг 5. HTTPS через Caddy
Документация n8n рекомендует ставить перед n8n обратный прокси: он принимает HTTPS и сам продлевает сертификаты. В официальных гайдах встречаются Traefik и Caddy, у Caddy конфигурация короче. Файл Caddyfile в папке проекта:
n8n.example.ru {
reverse_proxy n8n:5678 {
flush_interval -1
}
}
Этого достаточно. Caddy сам получает сертификат у Let's Encrypt или ZeroSSL, продлевает его и перенаправляет HTTP на HTTPS. Заголовки X-Forwarded-For, X-Forwarded-Proto и X-Forwarded-Host он проставляет по умолчанию, а n8n за прокси ждёт именно их вместе с N8N_PROXY_HOPS=1. Параметр flush_interval -1 взят из гайда n8n: он отключает буферизацию, и ответы уходят клиенту сразу.
Можно взять и nginx, но заголовки X-Forwarded-* и WebSocket придётся прописать руками: по умолчанию n8n шлёт обновления в редактор через WebSocket, а Caddy проксирует его без настроек.
Шаг 6. Запуск и первый вход
docker compose up -d
docker compose ps
docker compose logs -f n8n
У postgres должен появиться статус healthy, остальные контейнеры должны работать без перезапусков. Проверка с самого сервера:
curl -sf http://127.0.0.1:5678/healthz
Если команда отработала без ошибки, n8n запущен.
При первом входе по адресу с вашим доменом n8n попросит создать учётную запись владельца: почта, имя, пароль. Это главный администратор экземпляра. На том же шаге можно бесплатно зарегистрировать Community Edition по почте. Придёт ключ, который открывает папки для сценариев, отладку на данных прошлых запусков и пользовательские данные выполнений.
Последняя проверка касается вебхуков. Создайте сценарий с узлом Webhook и посмотрите адрес в его настройках. Должно быть https://n8n.example.ru/webhook/..., а не localhost:5678. Если видите localhost, n8n не получил N8N_WEBHOOK_URL. Старое имя WEBHOOK_URL с версии 2.35.0 считается устаревшим, но ещё принимается: n8n пишет предупреждение при запуске.
Обновление версии
Документация советует обновляться хотя бы раз в месяц, чтобы не перепрыгивать через много версий сразу, и брать стабильную версию, а не бету. Порядок такой:
- Прочитать release notes между вашей и новой версией.
- Сделать бэкап, как описано в следующем разделе.
- Поменять N8N_VERSION в .env.
- Выполнить три команды из документации.
docker compose pull
docker compose down
docker compose up -d
Команда down останавливает и удаляет контейнеры, но не тома с данными. Тома удаляет только флаг -v, о нём ниже.
Мажорную версию самого PostgreSQL, например с 16 на 18, сменой тега не обновить: контейнер остановится с ошибкой database files are incompatible with server. Данные целы, а переход делается через дамп и восстановление. Обновлять n8n и PostgreSQL в один заход мы не советуем.
Бэкапы: база, ключ и проверка восстановления
Полный бэкап n8n по документации состоит из двух частей: папки .n8n, где лежит файл config с ключом шифрования, и внешней базы, если это PostgreSQL. Учётные данные в базе зашифрованы, поэтому дамп без ключа вернёт сценарии, но не пароли и токены к вашим сервисам.
set -a && . ./.env && set +a
mkdir -p ~/n8n-backups
docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" | gzip > ~/n8n-backups/n8n-$(date +%F).sql.gz
Первая строка загружает переменные из .env в оболочку: Compose читает этот файл сам, а shell нет. Дамп ставят в cron раз в сутки и копируют за пределы сервера: бэкап на том же диске не спасёт, если пропадёт сам сервер.
Ключ шифрования храните отдельно, например копию .env в менеджере паролей. Дополнительно сценарии и учётные данные можно выгружать в JSON встроенной командой n8n:
docker compose exec -u node n8n n8n export:workflow --backup --output=/home/node/.n8n/backups/workflows/
docker compose exec -u node n8n n8n export:credentials --backup --output=/home/node/.n8n/backups/credentials/
Такая выгрузка удобна, чтобы перенести сценарии на другой экземпляр, но полного восстановления не заменяет. В неё не входят пользователи, история выполнений, переменные и настройки экземпляра, включая ключ шифрования. Папки для сценариев и учётных данных держите раздельными: по документации импорт учётных данных из папки, где лежат и сценарии, сейчас завершается ошибкой.
Главное предупреждение из официального примера: не запускайте docker compose down -v. Флаг -v удаляет тома, а вместе с томом n8n_storage пропадёт и файл с ключом. Базу вы восстановите из дампа, но сохранённые учётные данные станут нечитаемыми, если ключ не сохранён в другом месте.
Бэкап, который ни разу не восстанавливали, остаётся надеждой. Раз в квартал разверните дамп и ключ на тестовом сервере и проверьте, что сценарии открываются, а учётные данные расшифровываются. Как автоматизировать выгрузку и историю изменений сценариев, показывает кейс резервных копий n8n-сценариев, общие правила хранения ключей собраны в разборе безопасности автоматизации.
Типовые ошибки и как их узнать
| Симптом | Причина | Что сделать |
|---|---|---|
| В узле Webhook адрес с localhost:5678, внешние сервисы не достучались | Не задан N8N_WEBHOOK_URL (на старых версиях n8n переменная называлась WEBHOOK_URL) | Задать адрес с https и доменом, пересоздать контейнер командой docker compose up -d |
| На пробной установке вход по http://IP:5678 выдаёт ошибку про secure cookie | По умолчанию N8N_SECURE_COOKIE=true, cookie передаются только по HTTPS | Входить по домену через HTTPS, а не отключать защиту |
| Расписание срабатывает на несколько часов раньше или позже | Не задан GENERIC_TIMEZONE, действует America/New_York | Задать часовой пояс и перепроверить узлы Schedule |
| Сайт не открывается по HTTPS, сертификата нет | DNS ещё не указывает на сервер или закрыты порты 80 и 443 | Проверить A-запись и файрвол, посмотреть docker compose logs caddy |
| После переезда учётные данные не расшифровываются | На новом сервере другой ключ шифрования | Вернуть прежний N8N_ENCRYPTION_KEY или файл config в папку .n8n |
| После смены образа PostgreSQL база пустая или контейнер не стартует | Удалена строка PGDATA или мажорная версия обновлена сменой тега | Вернуть PGDATA и прежний тег, обновлять базу через дамп |
| Сценарий обрывается, в логах JavaScript heap out of memory | Узел обрабатывает слишком много данных за один проход | Обрабатывать данные пачками, например по 200 строк вместо 10 000, вынести тяжёлое в подпроцессы, при необходимости добавить памяти |
| Диск постепенно заполняется | История выполнений и бэкапы лежат на том же диске | По умолчанию n8n удаляет выполнения старше 336 часов (14 дней) и хранит не больше 10 000 записей. Проверить, не отключили ли очистку, и вынести бэкапы с сервера |
Позже всего замечают молча упавший контейнер, поэтому после установки стоит настроить внешнюю проверку доступности и уведомление в Telegram, как в кейсе контроля доступности сервера. Если n8n не отвечает, первым делом смотрят docker compose ps и логи упавшего контейнера.
Чек-лист перед переносом рабочих сценариев
- n8n открывается по https, а http перенаправляет на https.
- Порт 5678 снаружи недоступен.
- В узле Webhook адрес с вашим доменом.
- Расписание срабатывает по местному времени.
- Ключ шифрования и копия .env хранятся вне сервера.
- Дамп базы делается по расписанию и хотя бы раз восстановлен на тестовой машине.
- Номер версии зафиксирован, и назначен человек, который раз в месяц обновляет n8n.
- Настроено уведомление о недоступности.
Не хотите ставить сами: поставим под ключ
Всё описанное выше по нашей шкале относится к простым задачам: 7-15 тыс. ₽, срок от 3 дней. В работу входят сервер, Docker Compose с PostgreSQL, HTTPS, переменные окружения, бэкапы по расписанию, проверка вебхуков и короткая инструкция по эксплуатации. Расходы на сервер и сервисы оплачиваются отдельно: VPS и домен. Если нужны регулярные обновления, разбор ошибок и доработки сценариев, поддержка стоит 4-15 тыс. ₽ в месяц.
Что именно входит в работу, описано на странице услуги n8n на вашем сервере, пример результата есть в кейсе установки n8n на сервер.
Итог
Рабочая установка n8n - это четыре контейнера: n8n, PostgreSQL, task runner и Caddy. Порт n8n закрыт снаружи, адрес вебхуков и часовой пояс заданы явно, ключ шифрования хранится отдельно, дамп базы делается каждый день и проверен восстановлением. Тогда обновление занимает три команды раз в месяц, а потеря сервера не означает потерю автоматизаций.
Частые вопросы
Можно ли оставить SQLite и не ставить PostgreSQL?
Для пробы можно: без настроек базы n8n сам создаёт SQLite в папке .n8n. Для рабочего экземпляра, где сценарии работают круглосуточно, документация n8n рекомендует PostgreSQL. Учтите, что данные из SQLite в PostgreSQL автоматически не переносятся: новая база стартует пустой. Поэтому базу выбирают до того, как на сервер переедут рабочие процессы, а не после.
Что будет, если потерять ключ шифрования n8n?
Сценарии восстановятся из дампа базы, а учётные данные к вашим сервисам нет: n8n хранит их в базе в зашифрованном виде, и без того же ключа из файла config или переменной N8N_ENCRYPTION_KEY расшифровать их нельзя. Придётся заново вводить все пароли, токены и подключения. Поэтому ключ хранят отдельно от сервера, например копию .env в менеджере паролей.
Как часто обновлять n8n и не сломает ли обновление сценарии?
Минорные версии n8n выходят почти каждую неделю, а документация советует обновляться хотя бы раз в месяц: так не придётся перепрыгивать через много версий сразу. Перед обновлением читают release notes на предмет несовместимых изменений и делают бэкап. Для рабочих серверов берут стабильную версию, а не бету, и фиксируют её номер в .env, чтобы обновление происходило только по вашей команде.
Не готовы обсуждать проект? Оцените выгоду сами: калькулятор ROI автоматизации - 1 минута, без контактов. Или заберите чек-лист «Что автоматизировать первым».