n8n - платформа для автоматизаций с визуальным редактором: из узлов собирают сценарии, которые получают данные из webhook-ов, расписаний и внешних сервисов и передают их дальше. Облачная версия удобна для старта, но объем выполнений и возможности зависят от тарифа сервиса. Установка на собственный VPS переносит эти границы на ваш сервер: вы сами решаете, сколько сценариев запускать, где хранятся данные и ключи.

Ниже разберем, как установить n8n на VPS через Docker Compose с базой PostgreSQL, как вывести сервис наружу по HTTPS через nginx и certbot, как делать резервные копии и обновлять установку.

Что понадобится для установки n8n

  • VPS с Linux, доступ по SSH и пользователь с правами sudo;
  • Docker и плагин Docker Compose, см. статью Docker на VPS;
  • домен, например n8n.example.com, с A-записью на IP сервера, см. статью Домен и DNS;
  • nginx и certbot для HTTPS, как описано в статье Сайт на VPS: nginx и SSL.

По ресурсам для комфортной работы подойдет тариф Start: 2 vCPU, 4 ГБ RAM и 35 ГБ диска. Сам n8n, PostgreSQL и несколько сценариев с обработкой данных на таком сервере работают спокойно. На тарифе с 1 ГБ памяти база и n8n начнут конкурировать за память, а сценарии с большими файлами могут падать.

Структура проекта

Создайте каталог проекта и два файла: docker-compose.yml с описанием сервисов и .env с секретами. Файл .env не должен попадать в git и в публичные каталоги.

mkdir -p ~/n8n && cd ~/n8n
nano docker-compose.yml
nano .env
chmod 600 .env

Файл docker-compose.yml с PostgreSQL

В конфигурации два сервиса: postgres хранит сценарии, учетные данные и историю выполнений, а n8n работает с ней через внутреннюю сеть Compose. Порт n8n привязан к localhost, поэтому снаружи сервис недоступен напрямую, а доступ дается только через nginx.

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

  n8n:
    image: n8nio/n8n:latest
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_PORT: 5432
      DB_POSTGRESDB_DATABASE: n8n
      DB_POSTGRESDB_USER: n8n
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_HOST: n8n.example.com
      N8N_PORT: 5678
      N8N_PROTOCOL: https
      WEBHOOK_URL: https://n8n.example.com/
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      GENERIC_TIMEZONE: Europe/Moscow
      TZ: Europe/Moscow
    ports:
      - "127.0.0.1:5678:5678"
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_pgdata:
  n8n_data:

Несколько важных переменных. N8N_HOST - только имя хоста без протокола. WEBHOOK_URL - публичный адрес, по которому внешние сервисы будут вызывать ваши webhook-и, он должен совпадать с доменом nginx. N8N_PROTOCOL должен быть https, если сервис работает за HTTPS-прокси. GENERIC_TIMEZONE влияет на расписания cron-узлов.

Тег latest удобен для первого запуска. Для рабочей установки лучше указать конкретную версию n8n, которую вы проверили, например n8nio/n8n:<версия>.

Файл .env с секретами

POSTGRES_PASSWORD=replace-with-long-random-password
N8N_ENCRYPTION_KEY=replace-with-long-random-string

Длинные случайные значения можно сгенерировать командой openssl rand -hex 32. Пароль базы и ключ шифрования должны быть разными.

Запуск контейнеров

cd ~/n8n
docker compose up -d
docker compose ps
docker compose logs -f n8n

Когда в логах появится сообщение о запуске редактора, сервис слушает порт 5678 на localhost. Пока nginx не настроен, открыть n8n из браузера нельзя, и это правильно.

Публикация через nginx с HTTPS

nginx принимает запросы на портах 80 и 443, получает сертификат через certbot и передает запросы в n8n. Редактору и части функций нужен WebSocket, поэтому заголовки Upgrade и Connection обязательны. Создайте конфигурацию сайта:

server {
    listen 80;
    server_name n8n.example.com;

    client_max_body_size 16m;

    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-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }
}
sudo nano /etc/nginx/sites-available/n8n
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d n8n.example.com

certbot добавит блок для порта 443 и при необходимости перенаправление с HTTP на HTTPS. Подробности про выпуск сертификата и автообновление описаны в статье Сайт на VPS: nginx и SSL. Порт 5678 наружу открывать не нужно: в фаерволе оставьте только 22, 80 и 443.

Первый вход и учетная запись владельца

Откройте https://n8n.example.com. При первом входе n8n предложит создать учетную запись владельца: укажите email и длинный уникальный пароль. Эта учетная запись получает полный доступ к экземпляру, поэтому делиться ею нельзя. Если версия n8n поддерживает двухфакторную аутентификацию, включите ее в настройках профиля.

Старые версии n8n защищались базовой авторизацией через переменные N8N_BASIC_AUTH_*. В актуальных версиях вход защищает учетная запись владельца. Проверьте документацию для вашей версии, прежде чем полагаться на конкретный механизм. Главное правило одно: редактор не должен быть открыт без входа, поэтому создайте владельца сразу после запуска.

Резервные копии базы и данных

Для n8n важны две части. Первая - база PostgreSQL: сценарии, учетные данные в зашифрованном виде и история выполнений. Вторая - каталог /home/node/.n8n в томе n8n_data, где лежат служебные файлы n8n. Ключ шифрования хранится отдельно, и без него база не даст восстановить сохраненные учетные данные.

cd ~/n8n
mkdir -p backups
docker compose exec -T postgres pg_dump -U n8n -d n8n | gzip > backups/n8n-db-$(date +%F).sql.gz
docker run --rm -v n8n_n8n_data:/data:ro -v "$(pwd)/backups":/backup alpine tar czf /backup/n8n-data-$(date +%F).tar.gz -C /data .

Имя тома зависит от имени каталога проекта: в примере каталог называется n8n, поэтому том получает имя n8n_n8n_data. Точное имя проверьте командой docker volume ls.

Копии храните вне сервера: в S3-совместимом хранилище, на другом VPS или у себя локально. Бэкап на том же диске не спасет, если сломается сам сервер. Раз в месяц проверяйте восстановление на тестовом стенде: копия, которую никогда не разворачивали, остается предположением.

Восстановление базы выполняется обратной командой: поднимите PostgreSQL из compose, затем передайте дамп через gunzip -c backups/n8n-db-ДАТА.sql.gz и docker compose exec -T postgres psql -U n8n -d n8n. Перед восстановлением остановите n8n командой docker compose stop n8n.

Обновление n8n

Перед обновлением сделайте свежий бэкап. Затем загрузите новый образ и пересоздайте контейнеры:

cd ~/n8n
docker compose pull
docker compose up -d
docker compose logs --tail=50 n8n

Крупные версии могут менять поведение отдельных узлов и миграции базы. Читайте релиз-ноты перед обновлением, после запуска проверяйте ключевые сценарии и только потом считайте обновление успешным. Если что-то пошло не так, вернитесь на предыдущий тег в docker-compose.yml и восстановите базу из бэкапа, если миграция уже прошла.

Безопасность self-hosted n8n

  • Не публикуйте порты 5678 и 5432 наружу. В описанной конфигурации PostgreSQL вообще не имеет секции ports.
  • Храните .env с правами 600 и не коммитьте его в git.
  • Давайте API-ключам, подключенным в n8n, только те права, которые нужны сценарию.
  • Не храните в сценариях пароли открытым текстом: используйте credentials n8n.
  • Обновляйте систему и Docker, а базовые меры защиты сервера описаны в статье Безопасность Linux-сервера.

Частые проблемы при установке

  • Webhook-и показывают http вместо https: проверьте WEBHOOK_URL и N8N_PROTOCOL, затем пересоздайте контейнер командой docker compose up -d.
  • Редактор открывается, но не обновляется: чаще всего в nginx не хватает заголовков Upgrade и Connection.
  • n8n не стартует и пишет ошибку подключения к базе: проверьте пароль в .env и статус контейнера postgres.
  • certbot не выпускает сертификат: домен должен указывать на IP сервера, а порты 80 и 443 быть доступны снаружи.

Если сценарий работает в редакторе, но не срабатывает по webhook-у, первым делом проверьте публичный адрес в WEBHOOK_URL и доступность домена извне.