DevOps и Контейнеризация 12 мин чтения 2026-09-01

Как поднять все сайты и контейнеры на одном VDS: пошаговый гайд по Nginx Proxy Manager и Docker Compose с авто-SSL в 2026 году

Полный практический гайд по развертыванию Nginx Proxy Manager в связке с Docker Compose на VDS. Как за 15 минут запустить обратный прокси-сервер с удобным веб-интерфейсом, настроить единую изолированную сеть для контейнеров, выпускать и автоматически продлевать бесплатные SSL-сертификаты Let's Encrypt в 1 клик, защитить панель управления и гибко маршрутизировать веб-трафик.

Инженерная редакция SysKit Проверено инженерами SysKit.ru

Когда разработчик или вебмастер арендует чистый виртуальный сервер (VDS), перед ним почти сразу встает задача размещения нескольких независимых проектов: корпоративного сайта на WordPress, интернет-магазина, Telegram-бота на Node.js или Python, панели аналитики, Swagger-документации или личного пет-проекта. Классический путь системного администрирования предполагает установку «голого» Nginx прямо в операционную систему, ручное написание конфигурационных файлов /etc/nginx/sites-available/*, генерацию SSL через консольный Certbot и регулярную ручную правку директив proxy_pass.

Однако по мере роста количества сервисов такой подход превращается в кошмар сопровождения: опечатка в одном конфиге роняет весь веб-сервер при выполнении nginx -s reload, таймеры Certbot дают сбои, а порты 3000, 8000, 8080 хаотично открываются наружу, создавая критические уязвимости в сетевом периметре.

Современный стандарт решения этой задачи — связка Docker Compose и Nginx Proxy Manager (NPM). В этом подробном инженерном руководстве мы с нуля настроим отказоустойчивый обратный прокси-сервер с визуальным интерфейсом, создадим изолированную Docker-сеть, выпустим бесплатные SSL-сертификаты Let's Encrypt за пару кликов и научимся безопасно проксировать трафик к любым контейнерам.

💡
Совет инженера: Nginx Proxy Manager — это не урезанный суррогат Nginx, а полноценный промышленный Nginx OpenResty в Docker-обертке с удобным веб-дашбордом и встроенным движком Certbot. Под капотом он генерирует идеально выверенные конфигурации Nginx, поддерживает HTTP/2, HSTS, WebSockets, кастомные директивы вставки кода (Custom Nginx Configuration) и проброс «сырых» TCP/UDP сокетов.

1. Почему ручной Nginx уходит в прошлое: преимущества Nginx Proxy Manager

Сравним классическое ручное администрирование Nginx на хосте и управление трафиком через Nginx Proxy Manager в Docker:

Критерий Классический Nginx на хосте Nginx Proxy Manager в Docker
Добавление сайта / домена Ручное создание файлов в sites-available, симлинки, тесты nginx -t 3 клика в веб-интерфейсе за 15 секунд
Выпуск и продление SSL Команды certbot, ручная привязка webroot, cron-задачи продления Автоматический выпуск Let's Encrypt и автопродление в фоновом режиме
Поддержка Wildcard SSL (*.domain.ru) Сложные bash-хуки для взаимодействия с DNS API регистратора Встроенная поддержка DNS-01 Challenge для 30+ DNS-провайдеров (Cloudflare, Reg.ru и др.)
Ограничение доступа (Access Lists) Ручная генерация htpasswd и написание правил allow / deny в конфиге Создание списков пользователей и белых IP прямо в UI с назначением на любой хост
Цена человеческой ошибки Синтаксическая ошибка в одном файле может заблокировать перезапуск всех сайтов Каждый хост изолирован, валидация происходит перед применением конфигурации

2. Сетевая архитектура Docker: почему нельзя открывать порты контейнеров наружу

Типичная ошибка начинающих разработчиков при использовании Docker — публикация внутренних портов сервисов на внешний интерфейс хоста с помощью директивы ports: ["3000:3000", "8080:8080", "5432:5432"]. При такой схеме база данных, Node.js-бэкенд или Redis становятся открыты для всего интернета, минуя даже правила системного брандмауэра UFW (так как Docker по умолчанию напрямую модифицирует цепочки iptables).

Правильная архитектура безопасного обратного прокси:

  1. Единая входная точка (Ingress Gateway): Только контейнер Nginx Proxy Manager публикует во внешний мир порты 80 (HTTP) и 443 (HTTPS), а также защищенный административный порт 81 (Web UI).
  2. Общая изолированная сеть-мост (Docker Bridge Network): Создается отдельная виртуальная сеть (например, web_gateway). К ней подключаются NPM и все контейнеры, которые должны отвечать на внешние веб-запросы.
  3. Отсутствие публичных портов у приложений: В файлах docker-compose.yml ваших клиентских сайтов и сервисов секция ports полностью удаляется. Контейнеры слушают трафик только внутри локальной сети web_gateway.
  4. Маршрутизация по именам сервисов: Nginx Proxy Manager обращается к вашим сайтам не по IP-адресу, а по внутреннему DNS-имени контейнера в Docker-сети (например: http://my-blog:80 или http://api-backend:3000).

3. Шаг 1: Подготовка VDS (Ubuntu 24.04 LTS) и установка Docker Engine

Для стабильной работы Docker и Nginx Proxy Manager рекомендуется виртуальный KVM-сервер с операционной системой Ubuntu 24.04 LTS или Debian 12 и объемом оперативной памяти от 1–2 ГБ RAM.

1. Проверка занятости портов 80 и 443:
Перед установкой убедитесь, что на сервере не запущены сторонние веб-серверы (системный Apache или Nginx), которые будут конфликтовать за сетевые сокеты:

# Проверяем, какие процессы слушают 80 и 443 порты
sudo ss -tulpn | grep -E ':(80|443)\s'

# Если порты заняты системным apache2 или nginx, отключите их:
sudo systemctl stop apache2 nginx 2>/dev/null || true
sudo systemctl disable apache2 nginx 2>/dev/null || true

Для детальной диагностики открытых портов извне вы можете использовать онлайн-инструмент Сканер открытых портов SysKit.

2. Установка официального Docker Engine и Docker Compose:
Установим свежий релиз Docker из официального репозитория Docker Inc.:

# 1. Обновляем индекс пакетов и устанавливаем вспомогательные утилиты
sudo apt update && sudo apt install -y ca-certificates curl gnupg lsb-release

# 2. Добавляем официальный GPG-ключ Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 3. Подключаем официальный APT-репозиторий
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 4. Устанавливаем Docker Engine, CLI и Docker Compose v2
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 5. Проверяем корректность установки
docker --version && docker compose version

3. Создание общей внешней сети для проксирования:

# Создаем Docker-сеть типа bridge
sudo docker network create web_gateway

4. Шаг 2: Эталонный production docker-compose.yml для Nginx Proxy Manager

Создадим выделенную системную директорию для хранения конфигурационных файлов и персистентных данных Nginx Proxy Manager:

# Создаем структуру каталогов
sudo mkdir -p /opt/npm
cd /opt/npm

Создадим файл /opt/npm/docker-compose.yml со следующей конфигурацией:

services:
  npm:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      # Публичные порты для веб-трафика
      - '80:80'
      - '443:443'
      # Порт административной панели управления
      - '81:81'
    environment:
      # Отключаем анонимную телеметрию
      DISABLE_IPV6: 'true'
    volumes:
      # Данные базы SQLite, конфигурации хостов и сертификаты
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    networks:
      - web_gateway
    logging:
      driver: 'json-file'
      options:
        max-size: '10m'
        max-file: '3'

networks:
  web_gateway:
    external: true
💡
SQLite vs MariaDB: Для 95% серверов и нагрузок до 100+ сайтов встроенная база SQLite (используемая по умолчанию при монтировании каталога ./data) работает молниеносно, не расходует дополнительную оперативную память (экономит ~250 МБ RAM) и предельно просто бэкапится простым копированием папки. Отдельный контейнер MySQL/MariaDB нужен только в распределенных кластерах высокой доступности.

Запустим контейнер Nginx Proxy Manager в фоновом режиме:

# Запуск стека
sudo docker compose up -d

# Проверка статуса контейнера
sudo docker compose ps

Если в графе STATUS отображается Up (healthy) или Up, обратный прокси-сервер успешно инициализировался и готов принимать входящие соединения.

5. Шаг 3: Первый вход в дашборд и харденинг безопасности админки

Откройте веб-браузер и перейдите по адресу: http://IP_ВАШЕГО_СЕРВЕРА:81.

Стандартные учетные данные по умолчанию:

  • Email: admin@example.com
  • Password: changeme

Сразу после первого успешного входа система в обязательном порядке потребует указать ваше реальное имя администратора, актуальный адрес электронной почты и задать новый сложный криптостойкий пароль (рекомендуем сгенерировать его через наш Генератор надежных паролей).

⚠️
Критическая уязвимость порта 81: Административная панель на порту 81 по умолчанию работает по незашифрованному протоколу HTTP и доступна всему миру. Злоумышленники и сканирующие боты круглосуточно брутфорсят порт 81. Оставлять его открытым в публичный интернет категорически запрещено!

Как надежно защитить порт 81 панели управления:

Способ 1: Ограничение доступа через системный UFW Firewall (Рекомендуется):
Разрешите доступ к порту 81 только с вашего статического IP-адреса или подключайтесь к нему через защищенный SSH-туннель:

# Закрываем порт 81 для всех, открываем только для вашего домашнего/офисного IP:
sudo ufw allow from ВАШ_СТАТИЧЕСКИЙ_IP to any port 81 proto tcp

# Либо открываем защищенный SSH-туннель с вашего локального ПК:
# ssh -L 8181:127.0.0.1:81 root@IP_СЕРВЕРА
# После этого панель будет доступна в браузере по адресу: http://localhost:8181

Способ 2: Проксирование админки через сам NPM с HTTPS и Access List:
Вы можете привязать к панели субдомен (например, npm.yourdomain.ru), выпустить на него SSL-сертификат и повесить двухфакторную HTTP Basic аутентификацию (Access List), после чего закрыть порт 81 в UFW навсегда. Готовые правила фаервола смотрите в нашем шаблоне Настройка фаервола UFW для веб-сервера.

6. Рекомендуемые VDS-провайдеры для работы с Docker и контейнерами

Для стабильной работы Docker-контейнеров, быстрой сборки образов и мгновенной обработки SSL-рукопожатий необходим надежный KVM-сервер с производительными процессорами и быстрыми накопителями NVMe. Ниже представлены проверенные облачные хостинги с идеальной совместимостью с Docker:

Рекомендуемые VDS-провайдеры

Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с

Высокая производительность NVMe
🔷

Selectel Cloud VPS

Быстрое развертывание Ubuntu 24.04 с предустановленным Docker в 1 клик. Полноценная KVM-виртуализация, выделенные IPv4-адреса, надежный SLA 99.98% и дата-центры уровня Tier III.

Конфигурация
от 1 vCPU / 1 GB RAM / 15 GB NVMe
Идеально под Docker и микросервисы

Timeweb Cloud VDS

Современные процессоры AMD EPYC с частотой до 5.0 GHz, почасовая оплата, удобная панель управления сервером, моментальное создание снапшотов перед масштабными обновлениями.

Конфигурация
от 1 vCPU / 2 GB RAM / 30 GB NVMe
Простота и стабильность
🟠

Beget VPS

Мгновенный старт сервера, скоростная дисковая подсистема NVMe, автоматические ежедневные бэкапы всей виртуальной машины и круглосуточная отзывчивая служба технической поддержки.

Конфигурация
от 1 vCPU / 2 GB RAM / 35 GB NVMe

7. Шаг 4: Добавление первого сайта и выпуск SSL-сертификата в 1 клик

Рассмотрим пошаговый процесс публикации сайта на домене (например, app.example.com) с автоматическим выпуском и привязкой бесплатного SSL-сертификата Let's Encrypt.

1. Настройка DNS-записей домена:
В панели управления вашей DNS-зоной (у регистратора или в Cloudflare) создайте A-запись, указывающую на публичный IP-адрес вашего VDS сервера:

Тип записи Имя хоста (Host) Значение (Value / IP) TTL
A app (или @ для корня) 185.xxx.xxx.xxx (IP вашего VDS) 300 сек (Auto)

Перед продолжением убедитесь, что DNS-запись разошлась по мировым резолверам с помощью утилиты DNS Lookup и Резолвер SysKit.

2. Создание Proxy Host в интерфейсе NPM:

  1. В дашборде перейдите в раздел Hosts → Proxy Hosts и нажмите кнопку «Add Proxy Host».
  2. Вкладка «Details» (Основные параметры):
    • Domain Names: введите ваш домен app.example.com и нажмите Enter.
    • Scheme: выберите http (или https, если контейнер сам принимает TLS).
    • Forward Hostname / IP: укажите имя вашего сервиса в Docker-сети (например: my-web-app) или локальный IP хоста 172.17.0.1 / host.docker.internal.
    • Forward Port: внутренний порт приложения (например, 3000, 80 или 8080).
    • Опции оптимизации:
      • Cache Assets — включает кэширование статических файлов в Nginx (CSS, JS, картинки).
      • Block Common Exploits — блокирует распространенные веб-эксплойты, SQL-инъекции и спам-ботов.
      • Websockets Support — обязательно включите, если ваше приложение использует сокеты (Socket.io, чаты, live-уведомления).
  3. Вкладка «SSL» (Бесплатный сертификат):
    • В выпадающем списке SSL Certificate выберите пункт «Request a new SSL Certificate».
    • ✅ Включите тумблер Force SSL (автоматический 301-редирект с HTTP на защищенный HTTPS).
    • ✅ Включите HTTP/2 Support (ускоряет загрузку сайта благодаря мультиплексированию запросов).
    • ✅ Включите HSTS Enabled (запрещает браузерам открывать сайт по незащищенному протоколу).
    • Укажите ваш контактный Email для регистрации в Let's Encrypt и согласитесь с условиями (I Agree to the Let's Encrypt Terms of Service).
  4. Нажмите «Save».

Через 5–10 секунд Nginx Proxy Manager свяжется с серверами Let's Encrypt, пройдет процедуру валидации HTTP-01 Challenge, получит сертификат, пропишет его в конфигурацию Nginx и перезапустит воркеры. Сайт мгновенно станет доступен по безопасному протоколу https://app.example.com с валидным зеленым замком!

Работоспособность и цепочку доверия сертификата можно моментально протестировать через наш инструмент Проверка SSL / TLS сертификата онлайн.

8. Шаг 5: Практический пример — деплой веб-приложения за Nginx Proxy Manager

Посмотрим, как на практике выглядит подключение любого контейнеризированного приложения к Nginx Proxy Manager. Развернем, к примеру, быстрое приложение на Node.js или контейнер с Whoami/Nginx.

Создадим директорию проекта /opt/apps/my-web-app и файл docker-compose.yml:

services:
  my-app:
    image: 'traefik/whoami:latest'
    container_name: my-web-app
    restart: unless-stopped
    # Обратите внимание: секция ports ОТСУТСТВУЕТ!
    # Порт 80 не светится в интернет, а доступен только внутри Docker-сети
    environment:
      - WHOAMI_NAME=SysKit-Production-Node
    networks:
      - web_gateway

networks:
  web_gateway:
    external: true

Запустим приложение:

cd /opt/apps/my-web-app
sudo docker compose up -d

Теперь в Nginx Proxy Manager при создании Proxy Host в поле Forward Hostname достаточно написать имя контейнера: my-web-app, а в поле Forward Port80. NPM самостоятельно найдет контейнер по имени через встроенный в Docker DNS-резолвер 127.0.0.11!

Аналогично подключаются популярные стеки: WordPress, Bitrix, Laravel, FastAPI или Ghost. Готовые production-рецепты Compose смотрите в нашем каталоге Docker Compose LEMP + Redis + Nginx и Docker Compose Portainer + Nginx Proxy Manager.

9. Шаг 6: Продвинутые возможности: Access Lists, редиректы и TCP Streams

Nginx Proxy Manager предоставляет мощный инструментарий для решения нестандартных задач инфраструктуры:

1. Списки контроля доступа (Access Lists):
Если у вас есть закрытый административный контур (например, админка Swagger, pgAdmin, phpMyAdmin или тестовый Stage-сервер), вы можете защитить его в пару кликов:

  • Перейдите в Access Lists → Add Access List.
  • Во вкладке Authorization добавьте логины и пароли для HTTP Basic Auth.
  • Во вкладке Access добавьте белый список доверенных IP-адресов (например, ваш домашний IP или корпоративный VPN). Для всех остальных пользователей вход будет заблокирован ошибкой 403 Forbidden.
  • Привяжите созданный Access List к нужному Proxy Host в выпадающем списке.

2. Редиректы с одного домена на другой (Redirection Hosts):
Вам не нужно писать сложные конструкции с rewrite или return 301. В разделе Redirection Hosts можно настроить моментальное перенаправление трафика (например, с oldsite.ru на newsite.ru или с http://domain.ru на https://domain.ru) с сохранением query-параметров и путей (Forward HTTP Scheme & Path).

3. Проброс и балансировка TCP/UDP потоков (Streams):
Если вам необходимо проксировать не HTTP/HTTPS веб-трафик, а «сырые» сетевые порты (например, подключение к СУБД PostgreSQL на порту 5432, брокеру сообщений RabbitMQ на 5672 или игровому серверу), используйте раздел Streams. NPM перенаправит трафик на уровне 4-го уровня модели OSI (Layer 4 TCP/UDP Proxy).

10. Типичные проблемы и фатальные ошибки начинающих (Траблшутинг)

⚠️ Распространенные ошибки при настройке:

  • Ошибка 502 Bad Gateway: Контейнер с сайтом не подключен к сети web_gateway, либо внутри контейнера процесс слушает 127.0.0.1 (локальный loopback контейнера) вместо 0.0.0.0.
  • Let's Encrypt: Internal Error при выпуске: Домен еще не делегирован на IP сервера, либо 80 порт заблокирован интернет-провайдером / внешним фаерволом. Для Let's Encrypt порт 80 обязан быть доступен извне!
  • Host is unreachable по имени контейнера: Контейнер был перезапущен с другим именем, или в compose-файле не объявлена сеть networks: [web_gateway].
  • Исчерпание дискового пространства логами: Без ограничения logging: max-size: 10m логи Nginx в Docker-контейнере со временем могут занять десятки гигабайт.

✅ Инженерные правила решения сбоев:

  • Проверка логов NPM в реальном времени: используйте команду sudo docker logs -f nginx-proxy-manager.
  • Проверка доступности контейнера из NPM: зайдите внутрь контейнера прокси командой docker exec -it nginx-proxy-manager ping my-web-app.
  • Проверка правильности HTTP-заголовков: валидируйте заголовки X-Forwarded-For и HSTS через Инспектор HTTP заголовков SysKit.
  • Бэкап данных в 1 команду: регулярно сохраняйте директории /opt/npm/data и /opt/npm/letsencrypt по нашему гайду Автоматический бэкап VDS в S3 хранилище.

11. Резюме и чек-лист сисадмина

Внедрение Nginx Proxy Manager в связке с Docker Compose кардинально упрощает серверную архитектуру: вы получаете централизованную точку входа, автоматический менеджмент SSL-сертификатов, полную изоляцию бэкенд-сервисов от публичной сети и возможность разворачивать новые сайты и пет-проекты за считанные секунды прямо из удобного веб-интерфейса.

Для мониторинга доступности ваших сайтов после развертывания настройте алерты по нашему руководству Мониторинг сайтов и SSL в Telegram с помощью Uptime Kuma, а проверку сетевой задержки выполните с помощью утилиты Пинг и время ответа TTFB.

Готовы развернуть стек Nginx Proxy Manager на надежном VDS?

Закажите высокоскоростной сервер на Timeweb Cloud с быстрыми процессорами AMD EPYC, гигабитным сетевым каналом и установкой Docker в один клик.

12. Часто задаваемые вопросы (FAQ)

Вопросы и ответы (FAQ)

Популярные вопросы вебмастеров и сисадминов по данной теме

Что произойдет, если Nginx Proxy Manager упадет или будет перезагружен?
Благодаря директиве restart: unless-stopped в docker-compose.yml, Docker автоматически перезапустит контейнер NPM при системном сбое или перезагрузке самого VDS. Простой займет не более 2–3 секунд. Все данные, конфигурации хостов и сертификаты сохраняются в примонтированных томах ./data и ./letsencrypt, поэтому никакие настройки не теряются.
Как настроить Wildcard SSL сертификат (*.domain.ru) в Nginx Proxy Manager?
Для получения сертификата на все поддомены вида *.example.com стандартная валидация HTTP-01 не подходит. В интерфейсе NPM в разделе SSL Certificates нажмите Add SSL Certificate -> Let's Encrypt, укажите *.example.com и example.com, включите тумблер Use a DNS Challenge, выберите вашего DNS-провайдера (например, Cloudflare) и вставьте ваш DNS API Token. Сертификат будет успешно выпущен и автоматически привязан ко всем поддоменам.
Почему при попытке получить SSL сертификат возникает ошибка Internal Error?
В 90% случаев эта ошибка связана с тем, что: 1) Доменная A-запись еще не указывает на IP-адрес вашего сервера (проверьте через DNS Lookup); 2) Порт 80 закрыт в фаерволе VDS (UFW/iptables) или блокируется провайдером; 3) Вы превысили лимит запросов Let's Encrypt (Failed Validation limit — 5 неудачных попыток в час на один аккаунт/домен).

Читайте также в блоге SysKit

Смежные руководства и полезные технические статьи