"Быстрый
<br />
<strong>Nginx Proxy Manager или Traefik — кратко:</strong></p>
<ul>
<li><strong>NPM</strong> — веб-интерфейс, мышка, 5 минут до первого проксирования. Идеально для старта и небольших homelab-стеков</li>
<li><strong>Traefik</strong> — метки в docker-compose, автодискавери контейнеров, SSL без касания мышкой. Для тех, кто живёт в YAML и хочет Infrastructure as Code</li>
<li><strong>Переходить с NPM на Traefik стоит</strong> когда: больше 5-7 сервисов, нужны middlewares, важен GitOps-подход</li>
<li><strong>Оставаться на NPM стоит</strong> когда: команда не-технических людей, простой стек, нет желания вникать в Traefik label syntax</li>
<li>По производительности для homelab — разница незаметна. Оба справятся с любым реалистичным трафиком домашней лаборатории</li>
</ul>
<p>
<h2>В чём реальный конфликт</h2>
<p>Nginx Proxy Manager vs Traefik — это не вопрос «что лучше». Это вопрос «как ты работаешь». И ответ зависит не от характеристик, а от того, как выглядит твой рабочий процесс.</p>
<p>Поднял новый контейнер. Что делаешь дальше?</p>
<p>В NPM: открыл браузер, вбил IP и порт, нажал Save. Готово. Сертификат пришёл сам через минуту. Ты даже не открывал терминал.</p>
<p>В Traefik: добавил 4 строки labels в docker-compose.yml, сделал <code>docker compose up -d</code>. Контейнер поднялся — Traefik его увидел, запросил сертификат, начал проксировать. Ты даже не открывал браузер.</p>
<p>Это не один и тот же процесс через разные интерфейсы. Это принципиально разная философия управления инфраструктурой. Что тебе ближе — то и выбирай.</p>
<h2>Nginx Proxy Manager: сильные стороны и ограничения</h2>
<p>NPM появился в 2018 году как обёртка над боевым Nginx. Идея проста: взять надёжный прокси и убрать необходимость писать конфиги вручную. Получился инструмент с веб-интерфейсом, который добился огромной популярности в selfhosted-сообществе.</p>
<p>Поднимается за три команды:</p>
<pre><code class="language-text">
version: "3"
services:
npm:
image: jc21/nginx-proxy-manager:latest
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
restart: unless-stopped
</code></pre>
<pre><code class="language-bash">
docker compose up -d
</code></pre>
<p>Открываешь <code>http://IP:81</code>, логин <code>admin@example.com</code> / пароль <code>changeme</code>. Меняешь пароль. Добавляешь первый Proxy Host. Готово.</p>
<p>SSL через Let’s Encrypt — галочка в интерфейсе. Wildcard-сертификаты через <a class="wpil_keyword_link" href="https://it-apteka.com/tag/dns/" target="_blank" rel="noopener" title="DNS" data-wpil-keyword-link="linked" data-wpil-monitor-id="2836">DNS</a> Challenge — в том же интерфейсе, выбираешь DNS-провайдера из списка. NPM автоматически обновляет сертификаты. Это работает хорошо и без единой строки конфига.</p>
<h3>Ограничения NPM</h3>
<p>Все <a href="https://it-apteka.com/docker-compose-ustanovka-komandy-i-nastrojka-kontejnerov/" title="Docker Compose — установка, команды и настройка контейнеров" target="_blank" rel="noopener" data-wpil-monitor-id="2827">настройки хранятся в SQLite-базе внутри контейнера</a>. Нет файлов конфига — нет <a class="wpil_keyword_link" href="https://it-apteka.com/tag/git/" target="_blank" rel="noopener" title="Git" data-wpil-keyword-link="linked" data-wpil-monitor-id="2837">Git</a>. Если хочешь перенести NPM на другой <a href="https://it-apteka.com/bjekap-i-vosstanovlenie-servera-the-dude-mikrotik/" title="Бэкап и восстановление сервера The Dude (MikroTik)" target="_blank" rel="noopener" data-wpil-monitor-id="2830">сервер или воспроизвести окружение — делаешь бэкап</a> базы и вручную пересоздаёшь хосты. Привет, ручной труд.</p>
<p>Advanced Config — есть вкладка для сырого Nginx-конфига. Мощно, но это костыль. Чем больше логики туда попадает, тем больше NPM превращается в «а кто и зачем это написал в 2023 году».</p>
<p>Масштабирование — если у тебя 20+ сервисов и каждый имеет свои особенности, интерфейс NPM становится неудобным. Нет поиска по хостам, нет группировки, нет шаблонов.</p>
<h3>Безопасность NPM: что нужно знать</h3>
"Критично:
<br />
NPM имеет историю критических CVE. CVE-2024-46256 (CVSS 9.8) позволяла RCE через функцию добавления Let's Encrypt сертификата без аутентификации. CVE-2025-50579 — CORS misconfiguration, кража JWT-токенов. Обновляй NPM регулярно и не выставляй порт 81 (admin panel) наружу без VPN или Basic Auth.<br />
<pre><code class="language-bash">
# Проверь текущую версию
docker inspect jc21/nginx-proxy-manager:latest | grep -i version
# Обновить
docker compose pull && docker compose up -d
</code></pre>
<h2>Traefik: сильные стороны и ограничения</h2>
<p>Traefik написан на Go командой Traefik Labs. Запущен в 2015-м, сейчас на версии v3. Более 54 000 звёзд на GitHub. Это не хоббийный проект — его используют в production крупные компании.</p>
<p>Ключевая идея: Traefik читает метки <a class="wpil_keyword_link" href="https://it-apteka.com/tag/docker/" target="_blank" rel="noopener" title="Docker" data-wpil-keyword-link="linked" data-wpil-monitor-id="2834">Docker</a>-контейнеров и сам конфигурирует роутинг. Ты не трогаешь конфиг Traefik когда добавляешь новый сервис. Ты добавляешь 4 строки в docker-compose.yml нового сервиса — и всё происходит автоматически.</p>
<p>Минимальный рабочий Traefik v3 с SSL через Let’s Encrypt:</p>
<pre><code class="language-text">
version: "3.8"
services:
traefik:
image: traefik:v3.3
container_name: traefik
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--certificatesresolvers.letsencrypt.acme.email=you@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
restart: unless-stopped
networks:
- proxy
networks:
proxy:
external: true
</code></pre>
<p>Теперь чтобы добавить любой сервис за Traefik — только метки в его docker-compose:</p>
<pre><code class="language-text">
services:
nextcloud:
image: nextcloud:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.rule=Host(`cloud.example.com`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
- "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"
networks:
- proxy
restart: unless-stopped
networks:
proxy:
external: true
</code></pre>
<p>Всё. Traefik увидел контейнер, запросил сертификат, настроил HTTPS-роутинг. Ты не открывал браузер.</p>
<h3>Wildcard SSL через Cloudflare DNS Challenge</h3>
<p>Это то, чем Traefik действительно выделяется. Один wildcard-сертификат на все поддомены — и никаких rate-limit проблем с Let’s Encrypt при большом количестве сервисов.</p>
<pre><code class="language-text">
services:
traefik:
image: traefik:v3.3
environment:
- CF_API_EMAIL=you@example.com
- CF_DNS_API_TOKEN=ваш_cloudflare_api_token
command:
- "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.cloudflare.acme.email=you@example.com"
- "--certificatesresolvers.cloudflare.acme.storage=/letsencrypt/acme.json"
</code></pre>
<p>В метках сервиса добавляешь:</p>
<pre><code class="language-text">
- "traefik.http.routers.myapp.tls.certresolver=cloudflare"
- "traefik.http.routers.myapp.tls.domains[0].main=example.com"
- "traefik.http.routers.myapp.tls.domains[0].sans=*.example.com"
</code></pre>
<h3>Middlewares — то, где NPM отстаёт</h3>
<p>Middlewares в Traefik — это цепочки обработки запросов. Basic Auth, IP whitelist, rate limiting, redirect, headers — всё это декларативно в YAML или labels. Один middleware — переиспользуй в любом роутере.</p>
<pre><code class="language-text">
labels:
# Создаём middleware для Basic Auth
- "traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$10$$hashed_password"
# Применяем к роутеру
- "traefik.http.routers.myapp.middlewares=auth"
</code></pre>
<h3>Ограничения Traefik</h3>
<p>Кривая обучения — первые два часа с Traefik можно потратить на отладку почему не работает роутинг. Labels-синтаксис специфичен, ошибки в именовании молча игнорируются. Dashboard показывает что сконфигурировано, но не всегда очевидно почему что-то не работает.</p>
<p>Docker socket — Traefik читает Docker socket для autodiscovery. Это значит <a href="https://it-apteka.com/avtomaticheskoe-obnovlenie-docker-kontejnerov-polnoe-rukovodstvo-i-primery/" title="Автоматическое обновление Docker контейнеров: полное руководство и примеры" target="_blank" rel="noopener" data-wpil-monitor-id="2826">контейнер Traefik имеет полный</a> доступ к Docker-демону. Для homelab допустимо, для production — монтируй socket через read-only и рассмотри <a href="https://it-apteka.com/ustanovka-i-nastrojka-socks5-proxy-dante-v-docker-compose/" title="Установка и настройка SOCKS5 proxy Dante в Docker Compose" target="_blank" rel="noopener" data-wpil-monitor-id="2828">Docker Socket Proxy</a>.</p>
<p>acme.json — файл с сертификатами хранится в одном файле с правами 600. Если он слетит или повредится — теряешь все сертификаты и запрашиваешь заново. Бэкапить обязательно.</p>
<h2>Архитектура: как оба инструмента работают изнутри</h2>
<pre class="mermaid">
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 60, 'rankSpacing': 60}
}}%%
flowchart LR
subgraph NPM ["Nginx Proxy Manager"]
N1["Web UI :81"] --> N2["SQLite DB"]
N2 --> N3["Nginx config (auto)"]
N3 --> N4["Nginx процесс"]
end
subgraph TR ["Traefik"]
T1["Docker Labels"] --> T2["Traefik Engine"]
T3["traefik.yml"] --> T2
T2 --> T4["Роутеры + Middlewares"]
end
Client["HTTPS запрос"] --> N4
Client --> T4
style N1 fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style T1 fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style N4 fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style T4 fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style N2 fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
style T3 fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
</pre>
<p>Ключевое различие: NPM <a href="https://it-apteka.com/docker-volumes-kak-hranit-dannye-kontejnerov-i-ne-poterjat-ih-posle-prune/" target="_blank" rel="noopener" data-wpil-monitor-id="2865">хранит конфигурацию в базе данных</a>, Traefik — в метаданных контейнеров и файлах. Последний подход дружелюбен к Git, первый — к мышке.</p>
<h2>Таблица сравнения по ключевым критериям</h2>
<table>
<thead>
<tr>
<th>Критерий</th>
<th>Nginx Proxy Manager</th>
<th>Traefik v3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Интерфейс</td>
<td>Веб-UI, мышка</td>
<td>YAML/labels, терминал</td>
</tr>
<tr>
<td>Порог входа</td>
<td>Низкий — 5 минут до результата</td>
<td>Средний — 1-2 часа на понимание</td>
</tr>
<tr>
<td>Infrastructure as Code</td>
<td>Нет (база данных)</td>
<td>Да (labels + YAML файлы)</td>
</tr>
<tr>
<td>Autodiscovery контейнеров</td>
<td>Нет — ручная настройка</td>
<td>Да — автоматически по labels</td>
</tr>
<tr>
<td>Let’s Encrypt HTTP Challenge</td>
<td>Галочка в UI</td>
<td>Параметр в команде</td>
</tr>
<tr>
<td>Let’s Encrypt DNS Challenge</td>
<td>UI + выбор провайдера</td>
<td>ENV переменные + параметры</td>
</tr>
<tr>
<td>Wildcard сертификаты</td>
<td>Да (DNS Challenge)</td>
<td>Да (DNS Challenge)</td>
</tr>
<tr>
<td>Middlewares (auth, rate limit)</td>
<td>Базово через Advanced Config</td>
<td>Полноценные, переиспользуемые</td>
</tr>
<tr>
<td>TCP/UDP проксирование</td>
<td>Нет</td>
<td>Да (встроено)</td>
</tr>
<tr>
<td>Load balancing</td>
<td>Базовый</td>
<td>Полноценный с health checks</td>
</tr>
<tr>
<td>Kubernetes поддержка</td>
<td>Нет</td>
<td>Да (Ingress + CRD)</td>
</tr>
<tr>
<td>Dashboard</td>
<td>Веб-UI со всеми настройками</td>
<td>Read-only dashboard (опционально)</td>
</tr>
<tr>
<td>Мониторинг / Prometheus</td>
<td>Нет из коробки</td>
<td>Встроенные метрики</td>
</tr>
<tr>
<td>История CVE</td>
<td>Активная (несколько критических)</td>
<td>Минимальная</td>
</tr>
<tr>
<td>Потребление RAM</td>
<td>~100-150 MB</td>
<td>~50-80 MB</td>
</tr>
<tr>
<td>Язык</td>
<td>Node.js + Nginx</td>
<td>Go</td>
</tr>
<tr>
<td>Перенос на другой сервер</td>
<td>Бэкап базы + ручное восстановление</td>
<td>Git push + docker compose up</td>
</tr>
</tbody>
</table>
<h2>Системные требования</h2>
<table>
<thead>
<tr>
<th>Параметр</th>
<th>Nginx Proxy Manager</th>
<th>Traefik v3</th>
</tr>
</thead>
<tbody>
<tr>
<td>ОС</td>
<td>Любой <a class="wpil_keyword_link" href="https://it-apteka.com/category/linux/" target="_blank" rel="noopener" title="Linux" data-wpil-keyword-link="linked" data-wpil-monitor-id="2835">Linux</a> с Docker</td>
<td>Любой Linux с Docker</td>
</tr>
<tr>
<td>RAM минимум</td>
<td>256 MB</td>
<td>128 MB</td>
</tr>
<tr>
<td>Docker</td>
<td>20.x+</td>
<td>20.x+</td>
</tr>
<tr>
<td>Docker Compose</td>
<td>v2.x</td>
<td>v2.x</td>
</tr>
<tr>
<td>Актуальная версия (май 2026)</td>
<td>2.12.x</td>
<td>3.3.x</td>
</tr>
</tbody>
</table>
<p>Перед установкой проверяй актуальные релизы: <a href="https://github.com/NginxProxyManager/nginx-proxy-manager/releases" rel="nofollow" target="_blank">NPM releases</a> и <a href="https://github.com/traefik/traefik/releases" rel="nofollow" target="_blank">Traefik releases</a>.</p>
<h2>Таблица портов</h2>
<table>
<thead>
<tr>
<th>Порт</th>
<th>Инструмент</th>
<th>Назначение</th>
<th>Снаружи?</th>
</tr>
</thead>
<tbody>
<tr>
<td>80</td>
<td>Оба</td>
<td>HTTP трафик (редирект на HTTPS)</td>
<td>Да</td>
</tr>
<tr>
<td>443</td>
<td>Оба</td>
<td>HTTPS трафик</td>
<td>Да</td>
</tr>
<tr>
<td>81</td>
<td>NPM</td>
<td>Веб-интерфейс администратора</td>
<td>Нет — только VPN/локалка</td>
</tr>
<tr>
<td>8080</td>
<td>Traefik</td>
<td>Dashboard (опционально)</td>
<td>Нет — только с auth</td>
</tr>
</tbody>
</table>
<h2>Когда что выбирать: матрица решений</h2>
<pre class="mermaid">
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 45, 'rankSpacing': 45}
}}%%
flowchart TD
A["Новый проект или миграция?"] --> B{"Опыт с Docker/YAML"}
B -->|"Базовый - только compose up"| C["NPM"]
B -->|"Уверенный - пишу compose сам"| D{"Сколько сервисов?"}
D -->|"1-5 простых"| E["NPM или оба подойдут"]
D -->|"6+ или растёт"| F{"Нужен GitOps?"}
F -->|"Да - конфиги в git"| G["Traefik"]
F -->|"Нет - всё через UI"| H{"Нужны middlewares?"}
H -->|"Да - auth, rate limit, headers"| G
H -->|"Нет"| C
style C fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style G fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style E fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
</pre>
<h2>Безопасная настройка NPM</h2>
<p>Если выбрал NPM — вот минимум безопасности, который нельзя игнорировать.</p>
"Порт
<br />
Никогда не открывай порт 81 (admin panel NPM) наружу без защиты. Это прямой путь к RCE через CVE. Используй VPN для доступа к admin или ограничь доступ по IP через файрвол.<br />
<pre><code class="language-bash">
# Закрыть порт 81 снаружи через UFW
sudo ufw deny 81/tcp
# Разрешить только с конкретного IP (твой домашний адрес)
sudo ufw allow from 192.168.1.0/24 to any port 81
</code></pre>
<p>Обязательно смени дефолтные креды сразу после первого входа. Включи двухфакторную аутентификацию в настройках профиля NPM.</p>
<p>Следи за обновлениями. NPM имеет активную историю CVE — <a href="https://www.cvedetails.com/vendor/20356/Jc21.html" rel="nofollow" target="_blank">CVE Details</a>. Настрой автообновление или хотя бы ежемесячное ручное обновление образа.</p>
<h2>Безопасный Traefik: минимальный checklist</h2>
"Docker
<br />
Traefik монтирует Docker socket для autodiscovery. Контейнер с доступом к socket имеет права root на всём хосте. В production используй <a href="https://it-apteka.com/docker-compose-dlja-domashnego-servera-struktura-reverse-proxy-sekrety-i-obnovlenija/" title="Docker Compose для домашнего сервера: структура, reverse proxy, секреты и обновления" target="_blank" rel="noopener" data-wpil-monitor-id="2829">Docker Socket Proxy</a> (tecnativa/docker-socket-proxy) как буфер. В homelab — приемлемый риск, но знай об этом.<br />
<p>Закрой dashboard от публичного доступа или защити BasicAuth:</p>
<pre><code class="language-text">
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$hashed_password"
</code></pre>
<p>Сгенерировать хеш пароля для BasicAuth:</p>
<pre><code class="language-bash">
echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g
</code></pre>
<h2>Troubleshooting</h2>
<h3>Traefik: сервис не отвечает, но labels добавлены</h3>
"Симптом"
<br />
Открываешь subdomain.example.com — 404 или Gateway Timeout. В docker compose logs traefik — нет упоминания твоего сервиса.<br />
<p>Проверь — контейнер и Traefik в одной Docker network?</p>
<pre><code class="language-bash">
# Посмотреть сети контейнера
docker inspect имя_контейнера | grep -A 10 "Networks"
# Если сети разные - добавь общую сеть в оба compose файла
# networks:
# proxy:
# external: true
</code></pre>
<p>Проверь что <code>traefik.enable=true</code> есть в labels — если в конфиге Traefik стоит <code>exposedbydefault=false</code>, без этой метки контейнер игнорируется.</p>
<pre><code class="language-bash">
# Посмотреть что Traefik видит
docker exec traefik traefik healthcheck
# Открыть dashboard и проверить Routers
</code></pre>
<h3>Traefik: SSL-сертификат не запрашивается</h3>
<p>Первая причина — домен не резолвится публично. Let’s Encrypt должен достучаться до твоего сервера по HTTP для TLS Challenge.</p>
<pre><code class="language-bash">
# Проверить резолвинг с внешнего сервера
dig +short myapp.example.com @8.8.8.8
# Проверить логи Traefik на ошибки ACME
docker logs traefik 2>&1 | grep -i acme
docker logs traefik 2>&1 | grep -i "certificate"
</code></pre>
<p>Вторая причина — превышен rate limit Let’s Encrypt (5 сертификатов на домен за 7 дней). Используй staging для тестов:</p>
<pre><code class="language-text">
# Добавить в command Traefik для тестирования
- "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
</code></pre>
<h3>NPM: 502 Bad Gateway после добавления хоста</h3>
<p>502 — NPM не может достучаться до backend. Причины:</p>
<ul>
<li>Неправильный IP или порт в настройках Proxy Host</li>
<li>Backend контейнер не запущен или не слушает на нужном порту</li>
<li>NPM и backend в разных Docker-сетях</li>
</ul>
<pre><code class="language-bash">
# Проверить что backend контейнер запущен
docker ps | grep имя_контейнера
# Проверить порт изнутри NPM-контейнера
docker exec -it nginx-proxy-manager sh
# Внутри контейнера:
wget -qO- http://IP_бэкенда:ПОРТ
</code></pre>
<h3>NPM: сертификат не обновляется автоматически</h3>
<pre><code class="language-bash">
# Посмотреть логи NPM
docker logs nginx-proxy-manager 2>&1 | grep -i "certif\|renew\|acme"
# Проверить что порт 80 открыт публично - нужен для HTTP Challenge
curl -v http://твой_домен/.well-known/acme-challenge/test
</code></pre>
<h3>Traefik: метки двойного доллара</h3>
<p>Частая ошибка: хеш пароля для BasicAuth содержит символ <code>$</code>. В docker-compose.yml его нужно экранировать двойным <code>$$</code>. В <code>.env</code> файле — одинарный <code>$</code>. Путаница приводит к «Auth middleware created but not working».</p>
<pre><code class="language-bash">
# Правильно в docker-compose.yml labels:
# admin:$$2y$$10$$abc...
# Правильно в .env файле:
# BASIC_AUTH=admin:$2y$10$abc...
</code></pre>
<h3>Общая ошибка: acme.json имеет неправильные права</h3>
<pre><code class="language-bash">
# Traefik требует chmod 600 на acme.json
chmod 600 ./letsencrypt/acme.json
# Если файл повреждён - удали и дай Traefik создать заново
rm ./letsencrypt/acme.json
touch ./letsencrypt/acme.json
chmod 600 ./letsencrypt/acme.json
docker compose restart traefik
</code></pre>
<h2>Альтернативы: что ещё существует</h2>
<table>
<thead>
<tr>
<th>Инструмент</th>
<th>Плюс</th>
<th>Минус</th>
<th>Ниша</th>
</tr>
</thead>
<tbody>
<tr>
<td>Nginx Proxy Manager</td>
<td>Самый простой старт, UI</td>
<td>CVE история, нет IaC</td>
<td>Homelab, начинающие</td>
</tr>
<tr>
<td>Traefik v3</td>
<td>Autodiscovery, middlewares, Go</td>
<td>Кривая обучения, labels syntax</td>
<td>Docker-native, production</td>
</tr>
<tr>
<td>Caddy v2</td>
<td>Простой Caddyfile, HTTP/3</td>
<td>Менее развитая экосистема</td>
<td>Простые статические сайты</td>
</tr>
<tr>
<td>HAProxy</td>
<td>Максимальная производительность</td>
<td>Нет встроенного SSL</td>
<td>Enterprise, high load</td>
</tr>
<tr>
<td>Nginx (чистый)</td>
<td>Максимальный контроль</td>
<td>Ручная конфигурация всего</td>
<td>Когда точно знаешь что делаешь</td>
</tr>
</tbody>
</table>
<p>Caddy заслуживает отдельного упоминания. У него автоматический HTTPS из коробки, Caddyfile читается как человеческий язык, и он значительно проще Traefik при сопоставимых возможностях для типичного homelab. Если тебе не нужен Docker autodiscovery — посмотри на него.</p>
<h2>Профилактика: бэкап и обновления</h2>
<h3>Бэкап NPM</h3>
<pre><code class="language-bash">
# Остановить NPM
docker compose stop npm
# Бэкап данных
tar -czf npm-backup-$(date +%Y%m%d).tar.gz ./data ./letsencrypt
# Запустить обратно
docker compose start npm
</code></pre>
<h3>Бэкап Traefik</h3>
<p>Если конфиги в Git — бэкап уже есть. Дополнительно сохрани acme.json:</p>
<pre><code class="language-bash">
# Бэкап сертификатов
cp ./letsencrypt/acme.json ./letsencrypt/acme.json.backup-$(date +%Y%m%d)
</code></pre>
<h3>Безопасное обновление</h3>
<pre><code class="language-bash">
# Для обоих инструментов - стандартная процедура
docker compose pull
docker compose up -d
# Проверить версию после обновления
docker inspect traefik:latest | grep -i version
</code></pre>
<h2>FAQ</h2>
<h3>Что лучше nginx proxy manager или traefik для homelab в 2026?</h3>
<p>Зависит от того, как ты работаешь. NPM быстрее стартует и не требует изучения — открыл UI, добавил хост, готово. Traefik требует понять концепцию labels и сетей, но зато весь конфиг живёт в docker-compose.yml рядом с сервисами, версионируется в Git и воспроизводится одной командой. Если начинаешь — NPM. Если растёшь — Traefik.</p>
<h3>Traefik сложный или нет?</h3>
<p>Первые два часа — да, сложный. Потом — нет. Самая частая ошибка начинающих: забыть что Traefik и сервис должны быть в одной Docker-сети. Как только это понял, и освоил синтаксис labels — дальше всё интуитивно. Большинство проблем решаются через dashboard и docker logs traefik.</p>
<h3>Стоит ли переходить с nginx proxy manager на traefik?</h3>
<p>Стоит если: у тебя больше 5-7 сервисов, ты хочешь хранить конфиги в Git, или тебе нужны middlewares (auth, rate limiting, headers). Переход занимает 1-2 часа. Оба можно запустить одновременно на разных портах для параллельной работы во время миграции — NPM на 8080/8443, Traefik на 80/443.</p>
<h3>Почему traefik не видит мой контейнер?</h3>
<p>Три самые частые причины: контейнер и Traefik в разных Docker-сетях, в конфиге Traefik стоит <code>exposedbydefault=false</code> а в labels нет <code>traefik.enable=true</code>, или ошибка в синтаксисе labels — лишний пробел или неправильное имя роутера. Открой dashboard Traefik на :8080 и посмотри раздел Routers — там сразу видно что сконфигурировано.</p>
<h3>Nginx Proxy Manager безопасен?</h3>
<p>NPM имеет реальную историю уязвимостей: CVE-2024-46256 (CVSS 9.8, RCE без аутентификации через Let’s Encrypt функцию), CVE-2025-50579 (CORS misconfiguration, кража токенов). Это не повод избегать NPM — это повод обновляться регулярно и никогда не выставлять порт 81 в публичный интернет. Используй последнюю версию, изолируй admin-панель за VPN.</p>
<h3>Как Traefik работает с несколькими docker-compose файлами?</h3>
<p>Traefik видит все контейнеры через Docker socket независимо от того, в каком compose файле они определены. Главное — контейнер должен быть в той же Docker-сети (external network), которую слушает Traefik. Создай одну общую сеть: <code>docker network create proxy</code>, добавь её в каждый compose-файл как <code>external: true</code>, и Traefik будет видеть все сервисы автоматически.</p>
<h2>Прогноз</h2>
<p>NPM никуда не уйдёт — у него 32 000 звёзд на GitHub и огромная база пользователей. Для быстрого старта и простых стеков это отличный выбор. Но если твой homelab растёт, и ты уже несколько раз пожалел что не можешь сделать <code>git pull</code> чтобы восстановить конфиг на новом сервере — Traefik это решает.</p>
<p>Начни с NPM если сомневаешься. Это правильный первый шаг — понять что такое reverse proxy на практике, не утонув в labels-синтаксисе. Когда NPM начнёт тебя ограничивать — ты сам почувствуешь. Вот тогда и переходи. Миграция займёт вечер, не неделю.</p>
"Помог
<br />
Пиши в комментарии какой стек у тебя — разберём. Если что-то не заработало — укажи версию Docker, версию инструмента и вывод docker logs.<br />
Быстрый ответ
Nginx Proxy Manager или Traefik — кратко:
- NPM — веб-интерфейс, мышка, 5 минут до первого проксирования. Идеально для старта и небольших homelab-стеков
- Traefik — метки в docker-compose, автодискавери контейнеров, SSL без касания мышкой. Для тех, кто живёт в YAML и хочет Infrastructure as Code
- Переходить с NPM на Traefik стоит когда: больше 5-7 сервисов, нужны middlewares, важен GitOps-подход
- Оставаться на NPM стоит когда: команда не-технических людей, простой стек, нет желания вникать в Traefik label syntax
- По производительности для homelab — разница незаметна. Оба справятся с любым реалистичным трафиком домашней лаборатории
В чём реальный конфликт
Nginx Proxy Manager vs Traefik — это не вопрос «что лучше». Это вопрос «как ты работаешь». И ответ зависит не от характеристик, а от того, как выглядит твой рабочий процесс.
Поднял новый контейнер. Что делаешь дальше?
В NPM: открыл браузер, вбил IP и порт, нажал Save. Готово. Сертификат пришёл сам через минуту. Ты даже не открывал терминал.
В Traefik: добавил 4 строки labels в docker-compose.yml, сделал docker compose up -d. Контейнер поднялся — Traefik его увидел, запросил сертификат, начал проксировать. Ты даже не открывал браузер.
Это не один и тот же процесс через разные интерфейсы. Это принципиально разная философия управления инфраструктурой. Что тебе ближе — то и выбирай.
Nginx Proxy Manager: сильные стороны и ограничения
NPM появился в 2018 году как обёртка над боевым Nginx. Идея проста: взять надёжный прокси и убрать необходимость писать конфиги вручную. Получился инструмент с веб-интерфейсом, который добился огромной популярности в selfhosted-сообществе.
Поднимается за три команды:
version: "3"
services:
npm:
image: jc21/nginx-proxy-manager:latest
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
restart: unless-stopped
docker compose up -d
Открываешь http://IP:81, логин admin@example.com / пароль changeme. Меняешь пароль. Добавляешь первый Proxy Host. Готово.
SSL через Let’s Encrypt — галочка в интерфейсе. Wildcard-сертификаты через DNS Challenge — в том же интерфейсе, выбираешь DNS-провайдера из списка. NPM автоматически обновляет сертификаты. Это работает хорошо и без единой строки конфига.
Ограничения NPM
Все настройки хранятся в SQLite-базе внутри контейнера. Нет файлов конфига — нет Git. Если хочешь перенести NPM на другой сервер или воспроизвести окружение — делаешь бэкап базы и вручную пересоздаёшь хосты. Привет, ручной труд.
Advanced Config — есть вкладка для сырого Nginx-конфига. Мощно, но это костыль. Чем больше логики туда попадает, тем больше NPM превращается в «а кто и зачем это написал в 2023 году».
Масштабирование — если у тебя 20+ сервисов и каждый имеет свои особенности, интерфейс NPM становится неудобным. Нет поиска по хостам, нет группировки, нет шаблонов.
Безопасность NPM: что нужно знать
Критично: уязвимости NPM
NPM имеет историю критических CVE. CVE-2024-46256 (CVSS 9.8) позволяла RCE через функцию добавления Let’s Encrypt сертификата без аутентификации. CVE-2025-50579 — CORS misconfiguration, кража JWT-токенов. Обновляй NPM регулярно и не выставляй порт 81 (admin panel) наружу без VPN или Basic Auth.
# Проверь текущую версию
docker inspect jc21/nginx-proxy-manager:latest | grep -i version
# Обновить
docker compose pull && docker compose up -d
Traefik: сильные стороны и ограничения
Traefik написан на Go командой Traefik Labs. Запущен в 2015-м, сейчас на версии v3. Более 54 000 звёзд на GitHub. Это не хоббийный проект — его используют в production крупные компании.
Ключевая идея: Traefik читает метки Docker-контейнеров и сам конфигурирует роутинг. Ты не трогаешь конфиг Traefik когда добавляешь новый сервис. Ты добавляешь 4 строки в docker-compose.yml нового сервиса — и всё происходит автоматически.
Минимальный рабочий Traefik v3 с SSL через Let’s Encrypt:
version: "3.8"
services:
traefik:
image: traefik:v3.3
container_name: traefik
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--certificatesresolvers.letsencrypt.acme.email=you@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
restart: unless-stopped
networks:
- proxy
networks:
proxy:
external: true
Теперь чтобы добавить любой сервис за Traefik — только метки в его docker-compose:
services:
nextcloud:
image: nextcloud:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.rule=Host(`cloud.example.com`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
- "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"
networks:
- proxy
restart: unless-stopped
networks:
proxy:
external: true
Всё. Traefik увидел контейнер, запросил сертификат, настроил HTTPS-роутинг. Ты не открывал браузер.
Wildcard SSL через Cloudflare DNS Challenge
Это то, чем Traefik действительно выделяется. Один wildcard-сертификат на все поддомены — и никаких rate-limit проблем с Let’s Encrypt при большом количестве сервисов.
services:
traefik:
image: traefik:v3.3
environment:
- CF_API_EMAIL=you@example.com
- CF_DNS_API_TOKEN=ваш_cloudflare_api_token
command:
- "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.cloudflare.acme.email=you@example.com"
- "--certificatesresolvers.cloudflare.acme.storage=/letsencrypt/acme.json"
В метках сервиса добавляешь:
- "traefik.http.routers.myapp.tls.certresolver=cloudflare"
- "traefik.http.routers.myapp.tls.domains[0].main=example.com"
- "traefik.http.routers.myapp.tls.domains[0].sans=*.example.com"
Middlewares — то, где NPM отстаёт
Middlewares в Traefik — это цепочки обработки запросов. Basic Auth, IP whitelist, rate limiting, redirect, headers — всё это декларативно в YAML или labels. Один middleware — переиспользуй в любом роутере.
labels:
# Создаём middleware для Basic Auth
- "traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$10$$hashed_password"
# Применяем к роутеру
- "traefik.http.routers.myapp.middlewares=auth"
Ограничения Traefik
Кривая обучения — первые два часа с Traefik можно потратить на отладку почему не работает роутинг. Labels-синтаксис специфичен, ошибки в именовании молча игнорируются. Dashboard показывает что сконфигурировано, но не всегда очевидно почему что-то не работает.
Docker socket — Traefik читает Docker socket для autodiscovery. Это значит контейнер Traefik имеет полный доступ к Docker-демону. Для homelab допустимо, для production — монтируй socket через read-only и рассмотри Docker Socket Proxy.
acme.json — файл с сертификатами хранится в одном файле с правами 600. Если он слетит или повредится — теряешь все сертификаты и запрашиваешь заново. Бэкапить обязательно.
Архитектура: как оба инструмента работают изнутри
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 60, 'rankSpacing': 60}
}}%%
flowchart LR
subgraph NPM ["Nginx Proxy Manager"]
N1["Web UI :81"] --> N2["SQLite DB"]
N2 --> N3["Nginx config (auto)"]
N3 --> N4["Nginx процесс"]
end
subgraph TR ["Traefik"]
T1["Docker Labels"] --> T2["Traefik Engine"]
T3["traefik.yml"] --> T2
T2 --> T4["Роутеры + Middlewares"]
end
Client["HTTPS запрос"] --> N4
Client --> T4
style N1 fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style T1 fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style N4 fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style T4 fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style N2 fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
style T3 fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
Ключевое различие: NPM хранит конфигурацию в базе данных, Traefik — в метаданных контейнеров и файлах. Последний подход дружелюбен к Git, первый — к мышке.
Таблица сравнения по ключевым критериям
| Критерий |
Nginx Proxy Manager |
Traefik v3 |
| Интерфейс |
Веб-UI, мышка |
YAML/labels, терминал |
| Порог входа |
Низкий — 5 минут до результата |
Средний — 1-2 часа на понимание |
| Infrastructure as Code |
Нет (база данных) |
Да (labels + YAML файлы) |
| Autodiscovery контейнеров |
Нет — ручная настройка |
Да — автоматически по labels |
| Let’s Encrypt HTTP Challenge |
Галочка в UI |
Параметр в команде |
| Let’s Encrypt DNS Challenge |
UI + выбор провайдера |
ENV переменные + параметры |
| Wildcard сертификаты |
Да (DNS Challenge) |
Да (DNS Challenge) |
| Middlewares (auth, rate limit) |
Базово через Advanced Config |
Полноценные, переиспользуемые |
| TCP/UDP проксирование |
Нет |
Да (встроено) |
| Load balancing |
Базовый |
Полноценный с health checks |
| Kubernetes поддержка |
Нет |
Да (Ingress + CRD) |
| Dashboard |
Веб-UI со всеми настройками |
Read-only dashboard (опционально) |
| Мониторинг / Prometheus |
Нет из коробки |
Встроенные метрики |
| История CVE |
Активная (несколько критических) |
Минимальная |
| Потребление RAM |
~100-150 MB |
~50-80 MB |
| Язык |
Node.js + Nginx |
Go |
| Перенос на другой сервер |
Бэкап базы + ручное восстановление |
Git push + docker compose up |
Системные требования
| Параметр |
Nginx Proxy Manager |
Traefik v3 |
| ОС |
Любой Linux с Docker |
Любой Linux с Docker |
| RAM минимум |
256 MB |
128 MB |
| Docker |
20.x+ |
20.x+ |
| Docker Compose |
v2.x |
v2.x |
| Актуальная версия (май 2026) |
2.12.x |
3.3.x |
Перед установкой проверяй актуальные релизы: NPM releases и Traefik releases.
Таблица портов
| Порт |
Инструмент |
Назначение |
Снаружи? |
| 80 |
Оба |
HTTP трафик (редирект на HTTPS) |
Да |
| 443 |
Оба |
HTTPS трафик |
Да |
| 81 |
NPM |
Веб-интерфейс администратора |
Нет — только VPN/локалка |
| 8080 |
Traefik |
Dashboard (опционально) |
Нет — только с auth |
Когда что выбирать: матрица решений
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 45, 'rankSpacing': 45}
}}%%
flowchart TD
A["Новый проект или миграция?"] --> B{"Опыт с Docker/YAML"}
B -->|"Базовый - только compose up"| C["NPM"]
B -->|"Уверенный - пишу compose сам"| D{"Сколько сервисов?"}
D -->|"1-5 простых"| E["NPM или оба подойдут"]
D -->|"6+ или растёт"| F{"Нужен GitOps?"}
F -->|"Да - конфиги в git"| G["Traefik"]
F -->|"Нет - всё через UI"| H{"Нужны middlewares?"}
H -->|"Да - auth, rate limit, headers"| G
H -->|"Нет"| C
style C fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style G fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style E fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#c2410c
Безопасная настройка NPM
Если выбрал NPM — вот минимум безопасности, который нельзя игнорировать.
Порт 81 - только в локалке
Никогда не открывай порт 81 (admin panel NPM) наружу без защиты. Это прямой путь к RCE через CVE. Используй VPN для доступа к admin или ограничь доступ по IP через файрвол.
# Закрыть порт 81 снаружи через UFW
sudo ufw deny 81/tcp
# Разрешить только с конкретного IP (твой домашний адрес)
sudo ufw allow from 192.168.1.0/24 to any port 81
Обязательно смени дефолтные креды сразу после первого входа. Включи двухфакторную аутентификацию в настройках профиля NPM.
Следи за обновлениями. NPM имеет активную историю CVE — CVE Details. Настрой автообновление или хотя бы ежемесячное ручное обновление образа.
Безопасный Traefik: минимальный checklist
Docker socket - слабое место
Traefik монтирует Docker socket для autodiscovery. Контейнер с доступом к socket имеет права root на всём хосте. В production используй
Docker Socket Proxy (tecnativa/docker-socket-proxy) как буфер. В homelab — приемлемый риск, но знай об этом.
Закрой dashboard от публичного доступа или защити BasicAuth:
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$hashed_password"
Сгенерировать хеш пароля для BasicAuth:
echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g
Troubleshooting
Traefik: сервис не отвечает, но labels добавлены
Симптом
Открываешь subdomain.example.com — 404 или Gateway Timeout. В docker compose logs traefik — нет упоминания твоего сервиса.
Проверь — контейнер и Traefik в одной Docker network?
# Посмотреть сети контейнера
docker inspect имя_контейнера | grep -A 10 "Networks"
# Если сети разные - добавь общую сеть в оба compose файла
# networks:
# proxy:
# external: true
Проверь что traefik.enable=true есть в labels — если в конфиге Traefik стоит exposedbydefault=false, без этой метки контейнер игнорируется.
# Посмотреть что Traefik видит
docker exec traefik traefik healthcheck
# Открыть dashboard и проверить Routers
Traefik: SSL-сертификат не запрашивается
Первая причина — домен не резолвится публично. Let’s Encrypt должен достучаться до твоего сервера по HTTP для TLS Challenge.
# Проверить резолвинг с внешнего сервера
dig +short myapp.example.com @8.8.8.8
# Проверить логи Traefik на ошибки ACME
docker logs traefik 2>&1 | grep -i acme
docker logs traefik 2>&1 | grep -i "certificate"
Вторая причина — превышен rate limit Let’s Encrypt (5 сертификатов на домен за 7 дней). Используй staging для тестов:
# Добавить в command Traefik для тестирования
- "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
NPM: 502 Bad Gateway после добавления хоста
502 — NPM не может достучаться до backend. Причины:
- Неправильный IP или порт в настройках Proxy Host
- Backend контейнер не запущен или не слушает на нужном порту
- NPM и backend в разных Docker-сетях
# Проверить что backend контейнер запущен
docker ps | grep имя_контейнера
# Проверить порт изнутри NPM-контейнера
docker exec -it nginx-proxy-manager sh
# Внутри контейнера:
wget -qO- http://IP_бэкенда:ПОРТ
NPM: сертификат не обновляется автоматически
# Посмотреть логи NPM
docker logs nginx-proxy-manager 2>&1 | grep -i "certif\|renew\|acme"
# Проверить что порт 80 открыт публично - нужен для HTTP Challenge
curl -v http://твой_домен/.well-known/acme-challenge/test
Traefik: метки двойного доллара
Частая ошибка: хеш пароля для BasicAuth содержит символ $. В docker-compose.yml его нужно экранировать двойным $$. В .env файле — одинарный $. Путаница приводит к «Auth middleware created but not working».
# Правильно в docker-compose.yml labels:
# admin:$$2y$$10$$abc...
# Правильно в .env файле:
# BASIC_AUTH=admin:$2y$10$abc...
Общая ошибка: acme.json имеет неправильные права
# Traefik требует chmod 600 на acme.json
chmod 600 ./letsencrypt/acme.json
# Если файл повреждён - удали и дай Traefik создать заново
rm ./letsencrypt/acme.json
touch ./letsencrypt/acme.json
chmod 600 ./letsencrypt/acme.json
docker compose restart traefik
Альтернативы: что ещё существует
| Инструмент |
Плюс |
Минус |
Ниша |
| Nginx Proxy Manager |
Самый простой старт, UI |
CVE история, нет IaC |
Homelab, начинающие |
| Traefik v3 |
Autodiscovery, middlewares, Go |
Кривая обучения, labels syntax |
Docker-native, production |
| Caddy v2 |
Простой Caddyfile, HTTP/3 |
Менее развитая экосистема |
Простые статические сайты |
| HAProxy |
Максимальная производительность |
Нет встроенного SSL |
Enterprise, high load |
| Nginx (чистый) |
Максимальный контроль |
Ручная конфигурация всего |
Когда точно знаешь что делаешь |
Caddy заслуживает отдельного упоминания. У него автоматический HTTPS из коробки, Caddyfile читается как человеческий язык, и он значительно проще Traefik при сопоставимых возможностях для типичного homelab. Если тебе не нужен Docker autodiscovery — посмотри на него.
Профилактика: бэкап и обновления
Бэкап NPM
# Остановить NPM
docker compose stop npm
# Бэкап данных
tar -czf npm-backup-$(date +%Y%m%d).tar.gz ./data ./letsencrypt
# Запустить обратно
docker compose start npm
Бэкап Traefik
Если конфиги в Git — бэкап уже есть. Дополнительно сохрани acme.json:
# Бэкап сертификатов
cp ./letsencrypt/acme.json ./letsencrypt/acme.json.backup-$(date +%Y%m%d)
Безопасное обновление
# Для обоих инструментов - стандартная процедура
docker compose pull
docker compose up -d
# Проверить версию после обновления
docker inspect traefik:latest | grep -i version
FAQ
Что лучше nginx proxy manager или traefik для homelab в 2026?
Зависит от того, как ты работаешь. NPM быстрее стартует и не требует изучения — открыл UI, добавил хост, готово. Traefik требует понять концепцию labels и сетей, но зато весь конфиг живёт в docker-compose.yml рядом с сервисами, версионируется в Git и воспроизводится одной командой. Если начинаешь — NPM. Если растёшь — Traefik.
Traefik сложный или нет?
Первые два часа — да, сложный. Потом — нет. Самая частая ошибка начинающих: забыть что Traefik и сервис должны быть в одной Docker-сети. Как только это понял, и освоил синтаксис labels — дальше всё интуитивно. Большинство проблем решаются через dashboard и docker logs traefik.
Стоит ли переходить с nginx proxy manager на traefik?
Стоит если: у тебя больше 5-7 сервисов, ты хочешь хранить конфиги в Git, или тебе нужны middlewares (auth, rate limiting, headers). Переход занимает 1-2 часа. Оба можно запустить одновременно на разных портах для параллельной работы во время миграции — NPM на 8080/8443, Traefik на 80/443.
Почему traefik не видит мой контейнер?
Три самые частые причины: контейнер и Traefik в разных Docker-сетях, в конфиге Traefik стоит exposedbydefault=false а в labels нет traefik.enable=true, или ошибка в синтаксисе labels — лишний пробел или неправильное имя роутера. Открой dashboard Traefik на :8080 и посмотри раздел Routers — там сразу видно что сконфигурировано.
Nginx Proxy Manager безопасен?
NPM имеет реальную историю уязвимостей: CVE-2024-46256 (CVSS 9.8, RCE без аутентификации через Let’s Encrypt функцию), CVE-2025-50579 (CORS misconfiguration, кража токенов). Это не повод избегать NPM — это повод обновляться регулярно и никогда не выставлять порт 81 в публичный интернет. Используй последнюю версию, изолируй admin-панель за VPN.
Как Traefik работает с несколькими docker-compose файлами?
Traefik видит все контейнеры через Docker socket независимо от того, в каком compose файле они определены. Главное — контейнер должен быть в той же Docker-сети (external network), которую слушает Traefik. Создай одну общую сеть: docker network create proxy, добавь её в каждый compose-файл как external: true, и Traefik будет видеть все сервисы автоматически.
Прогноз
NPM никуда не уйдёт — у него 32 000 звёзд на GitHub и огромная база пользователей. Для быстрого старта и простых стеков это отличный выбор. Но если твой homelab растёт, и ты уже несколько раз пожалел что не можешь сделать git pull чтобы восстановить конфиг на новом сервере — Traefik это решает.
Начни с NPM если сомневаешься. Это правильный первый шаг — понять что такое reverse proxy на практике, не утонув в labels-синтаксисе. Когда NPM начнёт тебя ограничивать — ты сам почувствуешь. Вот тогда и переходи. Миграция займёт вечер, не неделю.
Помог выбрать?
Пиши в комментарии какой стек у тебя — разберём. Если что-то не заработало — укажи версию Docker, версию инструмента и вывод docker logs.