Как установить n8n на VPS: домен, HTTPS, база и резервные копии
Чтобы установить n8n на VPS, достаточно подготовить Linux-сервер с Docker Compose, привязать домен, запустить n8n вместе с PostgreSQL и настроить обратный прокси Caddy для HTTPS. После первого запуска важно сохранить ключ шифрования, проверить внешние вебхуки и настроить резервные копии. Ниже — последовательность команд для новой установки, а затем проверка восстановления на отдельном сервере.
Опубликовано: · Обновлено:

Что понадобится до установки
n8n — платформа автоматизации, которая запускает сценарии по расписанию, по HTTP-запросам и по событиям других приложений. VPS (виртуальный частный сервер) позволяет держать её работающей постоянно. В примере используется Ubuntu 24.04 LTS, выделенный публичный IP-адрес, домен и доступ по SSH (Secure Shell — защищённое удалённое подключение). Для небольшого числа простых сценариев можно ориентироваться, например, на 2 виртуальных CPU, 4 ГБ оперативной памяти и 30 ГБ SSD. Это пример конфигурации, а не универсальный минимум: тяжёлые интеграции, одновременные запуски, обработка файлов и AI-узлы потребляют больше ресурсов.
Потребуются права администратора на VPS, возможность менять DNS-записи (Domain Name System — система доменных имён), установленный Docker Engine с Compose plugin и открытые входящие TCP-порты 80 и 443. Учтите расходы на VPS, домен, хранение резервных копий и, при необходимости, внешнюю базу или мониторинг. Цены зависят от провайдера, диска, трафика и региона. Для self-hosted n8n также нужно проверить условия лицензирования, если автоматизация предоставляется как услуга клиентам.
Выбираем схему размещения
В этой инструкции используются три контейнера: PostgreSQL хранит процессы, пользователей и учётные данные; n8n исполняет сценарии; Caddy принимает внешний трафик, получает сертификат TLS (Transport Layer Security) и передаёт запросы n8n. Порт 5678 остаётся внутри сети Docker. Для простой тестовой установки подходит встроенная SQLite, но для длительной эксплуатации, удобных дампов и роста нагрузки разумнее сразу выбрать PostgreSQL. Переход со SQLite на PostgreSQL позднее требует отдельной миграции данных.
Подготовка VPS, DNS и Docker
Подключитесь к Ubuntu по SSH под пользователем с sudo. Сначала установите обновления и вспомогательные пакеты:
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl opensslСоздайте у регистратора A-запись: имя n8n, значение — публичный IPv4 VPS. Во всех примерах n8n.example.com служит заглушкой и должен быть заменён реальным доменом. При использовании IPv6 настройте AAAA-запись только на адрес, по которому сервер действительно доступен. Проверьте разрешение имени:
getent ahostsv4 n8n.example.comРазрешите SSH до активации межсетевого экрана; для нестандартного SSH-порта замените профиль OpenSSH нужным правилом. У провайдера VPS могут действовать дополнительные сетевые правила.
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw statusЕсли Docker ещё не установлен, добавьте его официальный репозиторий для Ubuntu:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${UBUNTU_CODENAME:-$VERSION_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker compose versionДалее команды Docker показаны с sudo: членство в группе docker фактически предоставляет привилегированный доступ к серверу. Установка через системные пакеты другой ОС требует адаптации команд.
Создаём каталог и переменные окружения
Размещаем проект в /opt/n8n. Файл .env хранит пароль PostgreSQL и постоянный ключ, которым n8n шифрует сохранённые учётные данные. Утеря ключа может сделать восстановленные credentials нечитаемыми, даже если сама база уцелела.
sudo mkdir -p /opt/n8n
sudo chown "$USER":"$USER" /opt/n8n
cd /opt/n8n
umask 077
cat > .env <<'EOF'
N8N_DOMAIN=n8n.example.com
N8N_VERSION=REPLACE_WITH_VERIFIED_STABLE_TAG
POSTGRES_USER=n8n
POSTGRES_DB=n8n
POSTGRES_PASSWORD=REPLACE_WITH_LONG_RANDOM_PASSWORD
N8N_ENCRYPTION_KEY=REPLACE_WITH_LONG_RANDOM_KEY
GENERIC_TIMEZONE=UTC
EOF
chmod 600 .envВместо заглушек задайте два разных случайных секрета. Например, дважды выполните openssl rand -hex 32, скопировав каждый результат в соответствующее поле. Для N8N_VERSION укажите точный тег стабильного образа, выбранный после проверки актуального выпуска и изменений версии. Использование latest облегчает первый запуск, но делает последующие обновления менее предсказуемыми. Важна совместимость всей связки: при будущей модернизации отдельно проверяйте изменения n8n и мажорную версию PostgreSQL.
openssl rand -hex 32
openssl rand -hex 32Настраиваем Docker Compose и HTTPS
Создайте compose.yaml. Здесь PostgreSQL 18 использует PGDATA=/var/lib/postgresql/data, чтобы файлы базы попадали в подключённый том: это особенно важно из-за изменений расположения каталога данных в 18-й ветке. Если у вас уже существует база PostgreSQL другой основной версии, простой смены тега образа недостаточно — потребуется штатное обновление кластера.
services:
postgres:
image: postgres:18
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
PGDATA: /var/lib/postgresql/data
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
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_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: ${N8N_DOMAIN}
N8N_PROTOCOL: https
N8N_PORT: 5678
N8N_PROXY_HOPS: 1
WEBHOOK_URL: https://${N8N_DOMAIN}/
N8N_EDITOR_BASE_URL: https://${N8N_DOMAIN}/
GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
TZ: ${GENERIC_TIMEZONE}
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 336
volumes:
- n8ndata:/home/node/.n8n
caddy:
image: caddy:2
restart: unless-stopped
depends_on:
- n8n
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddydata:/data
- caddyconfig:/config
volumes:
pgdata:
n8ndata:
caddydata:
caddyconfig:Создайте Caddyfile. Имя домена пишется буквально: Caddyfile не подставляет переменную из .env автоматически.
n8n.example.com {
reverse_proxy n8n:5678
}Caddy получает и обновляет сертификат для публичного домена, когда DNS указывает на VPS и порты 80/443 доступны. Внешние посетители подключаются по HTTPS, а n8n и Caddy общаются по внутренней сети контейнеров. PostgreSQL не публикует порт 5432, и n8n не публикует 5678. При наличии другого reverse proxy на 80/443 эту схему нужно адаптировать: два сервиса не смогут одновременно занять одни и те же порты.
Запуск и первые проверки
Убедитесь, что заменили все заглушки и записали Caddyfile. Затем проверьте синтаксис Compose, загрузите образы и запустите стек:
cd /opt/n8n
sudo docker compose config --quiet
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
sudo docker compose logs --tail=80 n8n
sudo docker compose logs --tail=80 caddyОткройте https://n8n.example.com и создайте учётную запись владельца. Проверьте адресную строку и действительность сертификата. Отдельно выполните curl -I https://n8n.example.com — ответ не обязательно будет 200, но ошибки TLS или 502 укажут на проблемы. Если сертификат не выдан, проверьте DNS, доступность 80/443 и логи Caddy. Не размещайте .env в публичной директории и не коммитьте его в Git.
Проверяем вебхуки и запуск по расписанию
Webhook — HTTP-адрес, на который внешняя система отправляет событие. В редакторе n8n создайте workflow с узлом Webhook, выберите GET и путь вроде health-demo. Для тестового URL нажмите Listen for test event и откройте показанный адрес: тестовый endpoint обычно работает, пока редактор ожидает событие. Затем активируйте workflow и запросите Production URL — именно он нужен сервисам, которые будут отправлять события постоянно.
curl -i https://n8n.example.com/webhook/health-demoКонкретный код ответа зависит от настроек узла и наличия активного workflow. Важнее увидеть исполнение в интерфейсе n8n и отсутствие ошибки маршрутизации. Test URL и Production URL различаются, а до активации сценария production webhook может не работать. Значения WEBHOOK_URL и N8N_PROXY_HOPS помогают формировать правильные внешние адреса за обратным прокси. Для Telegram и других интеграций HTTPS зачастую обязателен, а некоторым сервисам требуется подтверждение webhook или определённый формат ответа.
Для проверки расписания создайте отдельный workflow с Schedule Trigger, установите короткий интервал и посмотрите историю запусков. Часовой пояс определяется настройками самого workflow и переменными окружения экземпляра. Важно, чтобы контейнеры не останавливались, а серверные часы синхронизировались.
Что и как резервировать
Для полного восстановления нужны согласованные данные PostgreSQL, том /home/node/.n8n, файл .env с исходным ключом шифрования и конфигурация Compose/Caddy. PostgreSQL содержит workflows и большую часть прикладных данных. В томе n8n могут находиться настройки и локальные файлы. Если бинарные вложения хранятся отдельно, например во внешнем объектном хранилище, включите его в план резервирования. Обычный экспорт workflows не заменяет резервную копию credentials, истории и ключа.
Создаём согласованную копию
Для небольшого проекта удобно выделить короткое окно обслуживания: остановить n8n, оставить PostgreSQL работающим, получить SQL-дамп, затем архивировать том данных и конфигурацию. Команды запускайте из /opt/n8n. В архив попадут секреты, поэтому храните его только в защищённом месте.
cd /opt/n8n
mkdir -p backups
chmod 700 backups
sudo docker compose stop n8n
set -a; . ./.env; set +a
sudo docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc > backups/n8n.dump
test -s backups/n8n.dump || { echo 'Empty backup'; exit 1; }
sudo docker run --rm -v n8n_n8ndata:/source:ro -v "$PWD/backups":/backup alpine tar -C /source -czf /backup/n8ndata.tar.gz .
tar -czf backups/config.tar.gz .env compose.yaml Caddyfile
sudo docker compose start n8n
sha256sum backups/* > backups/SHA256SUMSИмя Docker-тома по умолчанию складывается из имени проекта и имени тома; для каталога /opt/n8n это обычно n8n_n8ndata. Перед архивированием проверьте фактическое имя командой sudo docker volume ls. Если имя отличается, подставьте его в команду docker run. После успешной копии убедитесь, что n8n вновь запущен. SQL-дамп не включает внешнее файловое хранилище.
Перенесите архивы на другой сервер или в защищённое объектное хранилище, включите шифрование, ограничьте доступ и установите политику хранения. Локальная папка backups на том же VPS защищает лишь от некоторых ошибок, но не от утраты всего сервера. Автоматизируйте резервирование через системный таймер после проверки сценария и отдельно контролируйте успешное завершение, свободное место и срок последней копии.
Проверяем восстановление на отдельном VPS
Тестовое восстановление выполняйте на другом сервере и другом домене, например n8n-restore.example.com. Не подключайте тестовый экземпляр к рабочим webhook-провайдерам: восстановленные активные сценарии могут повторно отправлять сообщения и обрабатывать реальные данные. Для строгой изоляции сначала закройте внешние исходящие подключения тестового окружения, а затем разрешайте лишь необходимые для проверки.
Установите Docker и Compose на чистом VPS. Перенесите резервные архивы в /opt/n8n-restore, распакуйте конфигурацию, замените домен в .env и Caddyfile на тестовый, но сохраните прежний N8N_ENCRYPTION_KEY и пароль базы. Используйте ту же основную версию PostgreSQL и совместимый тег n8n, что и при создании копии. Для этого примера задайте явное имя Compose-проекта n8nrestore во всех командах.
cd /opt/n8n-restore
tar -xzf config.tar.gz
# Отредактируйте N8N_DOMAIN и Caddyfile для тестового домена
sudo docker compose -p n8nrestore up -d --wait postgres
set -a; . ./.env; set +a
sudo docker compose -p n8nrestore exec -T postgres pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists --no-owner --exit-on-error < n8n.dumpКоманда восстановления должна завершиться с кодом 0. При ошибке остановитесь и проверьте версии PostgreSQL, содержимое архива и доступ к базе; не запускайте приложение с частично восстановленными данными. Важно восстановить том n8n до запуска приложения:
sudo docker volume create n8nrestore_n8ndata
sudo docker run --rm -v n8nrestore_n8ndata:/target -v "$PWD":/backup:ro alpine sh -c 'cd /target && tar -xzf /backup/n8ndata.tar.gz'
sudo docker compose -p n8nrestore up -d
sudo docker compose -p n8nrestore psУбедитесь, что доступны сохранённые workflows, пользователи и credentials, а выбранная тестовая интеграция может расшифровать ранее сохранённый секрет. Не запускайте в тестовой среде реальные платёжные, почтовые или производственные сценарии. По окончании проверки отключите тестовый стек, зафиксируйте результат восстановления и уточните допустимое время простоя и потерю последних данных.
Обновление и обслуживание
Перед обновлением n8n прочитайте изменения целевого релиза и сделайте проверенный бэкап. Измените N8N_VERSION на конкретный совместимый тег, затем выполните:
cd /opt/n8n
sudo docker compose pull n8n
sudo docker compose up -d n8n
sudo docker compose logs --tail=100 n8nНе повышайте основную версию PostgreSQL простой заменой image: новая версия сервера может не открыть прежний каталог данных. Потребуется отдельная процедура pg_upgrade либо дамп и импорт. Контролируйте загрузку процессора, память, объём диска, рост базы, ошибки запусков и срок действия сертификата. Сохранение только контейнера без постоянных volumes приведёт к потере данных после пересоздания.
Когда потребуется другая архитектура
При высокой параллельности пригодятся queue mode, Redis, выделенные workers и отдельные task runners. В n8n 2.x выполнение кода и настройки task runners требуют особого внимания: перед переходом от простой установки к масштабированию проверяйте требования и параметры именно выбранного релиза. Для крупных файлов нужна отдельная стратегия binary data storage. Если инфраструктура уже использует Nginx или Traefik, отдельный Caddy необязателен. Возможен и управляемый n8n Cloud, если не хочется обслуживать VPS, но контроль среды и условия тарификации будут другими.