Nginx Proxy Manager на Synology: полная настройка
Единая точка входа для всех сервисов на NAS: сертификаты Let's Encrypt, DNS-челлендж без открытого 80-го порта и то, что конфликтует с самим DSM ещё до первого запуска.
- Зачем реверс-прокси, если можно пробросить порты напрямую
- Главная ловушка на Synology: DSM уже занял 80 и 443
- Что понадобится перед стартом
- Шаг 1 — подготовка каталогов
- Шаг 2 — docker-compose.yml
- Шаг 3 — первый вход и смена пароля
- Шаг 4 — Proxy Host: домен, WebSocket, форс-HTTPS
- Шаг 5 — сертификаты без открытого порта 80 (DNS-01)
- Advanced-конфигурация: заголовки безопасности
- Ограничение доступа к панели администратора
- Бэкапы
- Частые проблемы
Зачем реверс-прокси, если можно пробросить порты напрямую
Nginx Proxy Manager (NPM) даёт графический интерфейс для того, что иначе пришлось бы держать в голове и в десятке конфигов nginx вручную: маршрутизацию доменов на внутренние порты контейнеров и автоматическое продление сертификатов Let's Encrypt. Но главная причина держать его перед всеми сервисами — не удобство, а то, что наружу в интернет теперь смотрит один порт 443, а не десяток разных портов для каждого сервиса, каждый со своим сертификатом (или вовсе без него).
Главная ловушка на Synology: DSM уже занял 80 и 443
Если на NAS включены Web Station, стандартный DSM-портал по HTTPS или собственный реверс-прокси в Панели управления → Логин-портал → Дополнительно, порты 80 и 443 уже заняты системой ещё до того, как вы запустите первый контейнер NPM — и он просто не поднимется с ошибкой address already in use.
Что понадобится перед стартом
- Домен, для которого вы управляете DNS-записями (для DNS-01 challenge в шаге 5 это обязательно).
- Проброс портов 80 и 443 на роутере в сторону IP NAS — если провайдер не использует CGNAT (см. врезку в шаге 5, если используется).
- Освобождённые порты 80/443 на самом DSM — см. предыдущий раздел.
Шаг 1 — подготовка каталогов
mkdir -p /volume1/docker/nginx-proxy-manager/data mkdir -p /volume1/docker/nginx-proxy-manager/letsencrypt
Папка data хранит встроенную базу SQLite с настройками всех Proxy Host'ов, а letsencrypt — сами сертификаты и учётные данные ACME. Актуальные версии образа NPM (2.11+) используют встроенный SQLite и не требуют отдельного контейнера с MariaDB — раньше это было обязательным шагом, сейчас лишняя сложность для домашнего использования.
Шаг 2 — docker-compose.yml
services:
app:
image: jc21/nginx-proxy-manager:2.12
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "127.0.0.1:81:81"
environment:
DISABLE_IPV6: "true"
volumes:
- /volume1/docker/nginx-proxy-manager/data:/data
- /volume1/docker/nginx-proxy-manager/letsencrypt:/etc/letsencrypt
mem_limit: 256m
Порт админ-панели 81 забинжен на 127.0.0.1, а не на все интерфейсы — панель управления сертификатами и правилами маршрутизации не должна быть доступна откуда угодно из локальной сети, не говоря уже об интернете. Доступ к ней — через SSH-туннель или отдельный Proxy Host с ограничением по IP (шаг 10).
Шаг 3 — первый вход и смена пароля
После docker compose up -d откройте http://IP_NAS:81 (или через туннель, если порт забинжен локально) и войдите с данными по умолчанию:
Email: admin@example.com Password: changeme
Шаг 4 — Proxy Host: домен, WebSocket, форс-HTTPS
При создании нового Proxy Host для каждого внутреннего сервиса — по аналогии с тем, как это делалось для Vaultwarden — важны три переключателя, которые часто оставляют по умолчанию:
- Websockets Support — без него сервисы вроде Nextcloud, Home Assistant или Vaultwarden либо теряют реалтайм-обновления, либо рвут соединение под нагрузкой.
- Block Common Exploits — встроенный набор правил против типовых инъекций в URL, включайте по умолчанию для всего, что смотрит в интернет.
- Force SSL + HTTP/2 Support — редирект с HTTP на HTTPS и современный протокол без лишней настройки на уровне контейнеров.
Шаг 5 — сертификаты без открытого порта 80 (DNS-01)
Стандартный способ подтверждения домена для Let's Encrypt (HTTP-01) требует, чтобы порт 80 был доступен из интернета. Это не работает в двух частых ситуациях: провайдер использует CGNAT (нет реального внешнего IP) или нужен wildcard-сертификат вида *.мойдомен.ру, который HTTP-01 в принципе не поддерживает.
Решение — DNS-01 challenge через API вашего DNS-провайдера. Для Cloudflare это выглядит так: в NPM при выпуске сертификата выбираете DNS Challenge, провайдера Cloudflare и API-токен с правами на редактирование DNS-зоны:
dns_cloudflare_api_token = ваш_api_токен_с_правами_dns_edit
Zone.DNS: Edit только для нужной зоны — а не полный Global API Key от всего аккаунта Cloudflare. Компрометация NPM в этом случае не даст доступа ко всему остальному аккаунту.
Advanced-конфигурация: заголовки безопасности
Вкладка Advanced в настройках Proxy Host позволяет добавить произвольные директивы nginx поверх сгенерированного конфига. Базовый набор заголовков безопасности, который стоит добавить почти везде:
add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Strict-Transport-Security "max-age=63072000" always;
Strict-Transport-Security добавляйте с осторожностью: браузер запомнит требование HTTPS для домена на указанный срок, и откатиться на обычный HTTP для тестов будет неудобно, пока не истечёт max-age.
Ограничение доступа к панели администратора
Создайте в NPM отдельный Access List с разрешённым диапазоном локальной подсети и привяжите его к Proxy Host, через который вы всё же решите открыть админ-панель наружу (например, для доступа из другого города):
| Параметр | Значение |
|---|---|
| Satisfy | any / all — обычно all с Basic Auth поверх IP-фильтра |
| Allow | 192.168.1.0/24 (локальная подсеть) |
| Deny | all (всё остальное) |
Если удалённый доступ к самой панели вам не нужен в принципе — проще оставить порт 81 забинженным на 127.0.0.1, как в шаге 2, и заходить только через SSH-туннель.
Бэкапы
Как и в остальных сервисах на NAS, бэкапить нужно ровно то, что определяет состояние сервиса — здесь это оба тома целиком:
#!/bin/bash
STAMP=$(date +%Y%m%d-%H%M)
DEST=/volume1/docker/nginx-proxy-manager/backups
mkdir -p "$DEST"
tar -czf "$DEST/npm-$STAMP.tar.gz" \
-C /volume1/docker/nginx-proxy-manager data letsencrypt
find "$DEST" -name "npm-*.tar.gz" -mtime +14 -delete
Восстановление из такого архива на новый NAS занимает пару минут: разворачиваете тома, поднимаете тот же compose-файл — все Proxy Host'ы и сертификаты возвращаются как есть, без повторной ручной настройки каждого домена.
Частые проблемы
| Симптом | Вероятная причина |
|---|---|
| Контейнер не стартует, «address already in use» | порты 80/443 заняты встроенным Web Station или логин-порталом DSM |
| 502 Bad Gateway | неверный внутренний IP/порт в Forward Hostname, либо сам сервис ещё не поднялся |
| Сертификат не выпускается по HTTP-01 | провайдер использует CGNAT — порт 80 недоступен снаружи, нужен DNS-01 |
| Зависает синхронизация / реалтайм-обновления | не включён Websockets Support для этого Proxy Host |
| Бесконечный редирект «too many redirects» | Force SSL включён одновременно с похожей настройкой на самом внутреннем сервисе |
| Не получается зайти в панель :81 снаружи | порт намеренно забинжен на 127.0.0.1 — используйте SSH-туннель или Access List |
После того как встроенный реверс-прокси DSM отключён, домены выпускают сертификаты по DNS-01, а панель администратора закрыта от внешнего доступа — NPM можно спокойно считать единственной точкой входа для всего остального стека на NAS.