Когда разработчик или вебмастер арендует чистый виртуальный сервер (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 за пару кликов и научимся безопасно проксировать трафик к любым контейнерам.
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).
Правильная архитектура безопасного обратного прокси:
- Единая входная точка (Ingress Gateway): Только контейнер Nginx Proxy Manager публикует во внешний мир порты
80 (HTTP)и443 (HTTPS), а также защищенный административный порт81 (Web UI). - Общая изолированная сеть-мост (Docker Bridge Network): Создается отдельная виртуальная сеть (например,
web_gateway). К ней подключаются NPM и все контейнеры, которые должны отвечать на внешние веб-запросы. - Отсутствие публичных портов у приложений: В файлах
docker-compose.ymlваших клиентских сайтов и сервисов секцияportsполностью удаляется. Контейнеры слушают трафик только внутри локальной сетиweb_gateway. - Маршрутизация по именам сервисов: 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
./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 панели управления:
Способ 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 Гбит/с
Selectel Cloud VPS
Быстрое развертывание Ubuntu 24.04 с предустановленным Docker в 1 клик. Полноценная KVM-виртуализация, выделенные IPv4-адреса, надежный SLA 99.98% и дата-центры уровня Tier III.
Timeweb Cloud VDS
Современные процессоры AMD EPYC с частотой до 5.0 GHz, почасовая оплата, удобная панель управления сервером, моментальное создание снапшотов перед масштабными обновлениями.
Beget VPS
Мгновенный старт сервера, скоростная дисковая подсистема 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:
- В дашборде перейдите в раздел Hosts → Proxy Hosts и нажмите кнопку «Add Proxy Host».
- Вкладка «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-уведомления).
- Domain Names: введите ваш домен
- Вкладка «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).
- Нажмите «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 Port — 80. 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 в один клик.