Хочу (На 07.10.2025
) приобщиться к использованию Nginx Proxy Manager
для своих сервисов, а где свои сервисы, там и по работе пригодится.
Вычитал, что Nginx Proxy Manager
— это обратный прокси-сервер (reverse proxy
) с поддержкой Web
-интерфейса, разработанный для упрощения настройки и управлением обратными прокси на основе веб-сервера Nginx.
Сервис используется для организации доступа к различным веб-приложениям через единую точку входа (в качестве единой точки входа может выступать, например, доменное имя или IP
-адрес) с дальнейшей маршрутизацией до конечного приложения.
Хотя если так посмотреть, что даже без Web
-оболочки я уже такое использую, если вспомнить мои заметки:
"OpenVPN доступ к Proxmox через Nginx Proxy"
"Обратный прокси для Headwind MDM"
"Fail2ban к Nginx Proxy для OwnCloud"
они не плохо отрабатывают, а тут просто удобство, но раз есть такое, так почему-бы не приобщиться к чему-то новому, да и плюсом будет не редактирование вручную конфигурационных файлов, а через Web
. К тому же проект бесплатный, я за Open Source.
На заметку: Минимальные системные требования под систему:
CPU: не менее 2 ядер
RAM: не менее 2Gb
HDD: не менее 30Gb
Шаг №1:
Создаем виртуальную машину в тестовом полигоне Debian 12 + Proxmox 8.4.12
с характеристиками:
CPU: 2
RAM: 2
HDD: 50Gb
OS: Ubuntu 22.04 Server LTS
ekzorchik@srv-us2204a:~$ uname -a && lsb_release -a
Linux srv-us2204a 5.15.0-157-generic #167-Ubuntu SMP Wed Sep 17 21:35:53 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.5 LTS
Release: 22.04
Codename: jammy
Шаг №2:
Поднимаем надстройку над правилами iptables
в лице firewalld
и разрешаем доступ к системе по портам:
80, 81 и 443 - tcp/udp
22 - tcp
где 81
— это Административный Web
-интерфейс
ekzorchik@srv-us2204a:~$ apt-cache show firewalld | grep Version
Version: 1.1.1-1ubuntu1
ekzorchik@srv-us2204a:~$ sudo apt-get install -y firewalld
ekzorchik@srv-us2204a:~$ sudo ufw disable
Firewall stopped and disabled on system startup
ekzorchik@srv-us2204a:~$ sudo systemctl enable firewalld
ekzorchik@srv-us2204a:~$ sudo systemctl start firewalld
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --state
running
ekzorchik@srv-us2204a:~$ ip r | awk '{print $5}' | head -n1
ens18
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --zone public --change-interface=ens18 --permanent
success
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --reload
success
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --zone public --add-port=80/tcp --permanent
success
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --zone public --add-port=22/tcp --permanent
success
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --zone public --add-port=81/tcp --permanent
success
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --zone public --add-port=443/tcp --permanent
success
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --reload
success
ekzorchik@srv-us2204a:~$
ekzorchik@srv-us2204a:~$ sudo firewall-cmd --zone public --remove-service=ssh --permanent
Шаг №3:
Для работы с Nginx Proxy Manager
потребуется Docker & Docker Compose:
опираюсь на свои наработки устанавливаю
ekzorchik@srv-us2204a:~$ docker -v
Docker version 28.5.0, build 887030f
ekzorchik@srv-us2204a:~$ docker compose version
Docker Compose version v2.5.0
ekzorchik@srv-us2204a:~$ ip r
default via 172.33.33.100 dev ens18 proto dhcp src 172.33.33.10 metric 100
8.8.8.8 via 172.33.33.100 dev ens18 proto dhcp src 172.33.33.10 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.33.33.0/24 dev ens18 proto kernel scope link src 172.33.33.10 metric 100
172.33.33.100 dev ens18 proto dhcp scope link src 172.33.33.10 metric 100
Шаг №4:
В качестве теста буду использовать три контейнера Docker
с развернутым внутри Web
—сервисом nginx.
У каждого запущенного контейнера свой уникальный порт, при обращении к которому будет отображаться своя фраза. Цель будет заключаться в следующем: используя Nginx Proxy Manager
, «опубликовать» все три сервиса, чтобы они были доступны пользователям в рамках частной сети по доменным именам и возвращали пользователям свой уникальный контент.
Так как все действия производятся сугубо для тестирования, мы воспользуемся локальными доменами, а именно пропишем тестовые доменные в файле /etc/hosts.
По умолчанию, Docker
создает свою подсеть с адресом 172.17.0.1:
ekzorchik@srv-us2204a:~$ sudo nano /etc/hosts
172.17.0.1 srv-nginx1.polygon.local
172.17.0.1 srv-nginx2.polygon.local
172.17.0.1 srv-nginx3.polygon.local
Шаг №5:
Создаем новую директорию, где будет храниться конфигурация для трех контейнеров в виде docker-compose
—файла:
ekzorchik@srv-us2204a:~$ mkdir nginx-test
ekzorchik@srv-us2204a:~$ cd nginx-test/
На заметку: File Naming: Compose prefers compose.yaml as the canonical file name, but it also supports docker-compose.yml and docker-compose.yaml for backward compatibility. If both compose.yaml and docker-compose.yml exist, compose.yaml will be preferred
ekzorchik@srv-us2204a:~/nginx-test$ nano docker-compose.yml
services:
nginx1:
image: nginx:alpine3.21
ports:
- "8081:80"
volumes:
- ./nginx1/html:/usr/share/nginx/html
command: ["/bin/sh", "-c", "echo 'Hello from nginx1!' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
nginx2:
image: nginx:alpine3.21
ports:
- "8082:80"
volumes:
- ./nginx2/html:/usr/share/nginx/html
command: ["/bin/sh", "-c", "echo 'Hello from nginx2!' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
nginx3:
image: nginx:alpine3.21
ports:
- "8083:80"
volumes:
- ./nginx3/html:/usr/share/nginx/html
command: ["/bin/sh", "-c", "echo 'Hello from nginx3!' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"]
После нажимаем Ctrl + O, Enter - Ctrl + X
(для выхода из редактора).
Шаг №6:
Для создания контейнеров используем команду:
ekzorchik@srv-us2204a:~/nginx-test$ docker-compose up -d
services must be a mapping (сервисы должны быть сопоставлены)
Т.к. что-то не так, а что?
Вычитал, что
Фраза "services must be a mapping"
означает, что в файле конфигурации (например, Docker Compose
), раздел services
должен представлять собой словарь (map или dictionary), где каждому имени службы соответствует ее конфигурация, а не список (array).
Решение: все что ниже services
сдвинул на один пробел и после успешно запустилось:
ekzorchik@srv-us2204a:~/nginx-test$ docker-compose up -d
[+] Running 11/11
✔ nginx1 Pulled 9.9s
✔ nginx2 Pulled 9.9s
✔ f18232174bc9 Pull complete 1.7s
✔ 61ca4f733c80 Pull complete 2.0s
✔ b464cfdf2a63 Pull complete 2.2s
✔ d7e507024086 Pull complete 2.4s
✔ 81bd8ed7ec67 Pull complete 2.5s
✔ 197eb75867ef Pull complete 2.7s
✔ 34a64644b756 Pull complete 2.9s
✔ 39c2ddfd6010 Pull complete 7.3s
✔ nginx3 Pulled 9.9s
[+] Running 4/4
✔ Network nginx-test_default Created 0.1s
✔ Container nginx-test-nginx2-1 Started 0.7s
✔ Container nginx-test-nginx3-1 Started 0.8s
✔ Container nginx-test-nginx1-1 Started 0.8s
ekzorchik@srv-us2204a:~/nginx-test$
Смотрим какие образы запущены:
ekzorchik@srv-us2204a:~/nginx-test$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
nginx-test-nginx1-1 "/docker-entrypoint.…" nginx1 running 0.0.0.0:8081->80/tcp, :::8081->80/tcp
nginx-test-nginx2-1 "/docker-entrypoint.…" nginx2 running 0.0.0.0:8082->80/tcp, :::8082->80/tcp
nginx-test-nginx3-1 "/docker-entrypoint.…" nginx3 running 0.0.0.0:8083->80/tcp, :::8083->80/tcp
ekzorchik@srv-us2204a:~/nginx-test$
или так:
ekzorchik@srv-us2204a:~/nginx-test$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28b91c6778a4 nginx:alpine3.21 "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp nginx-test-nginx1-1
c564d3a6d460 nginx:alpine3.21 "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:8083->80/tcp, [::]:8083->80/tcp nginx-test-nginx3-1
767bd973bacd nginx:alpine3.21 "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:8082->80/tcp, [::]:8082->80/tcp nginx-test-nginx2-1
ekzorchik@srv-us2204a:~/nginx-test$
ekzorchik@srv-us2204a:~/nginx-test$ cd ~
ekzorchik@srv-us2204a:~$
Шаг №7:
Не лишним будет проверить, что все три службы Nginx
обращаюсь на IP (Docker0):<PORT>
возвращают содержимое своего index.html:
ekzorchik@srv-us2204a:~$ curl 172.17.0.1:8081
Hello from nginx1!
ekzorchik@srv-us2204a:~$ curl 172.17.0.1:8082
Hello from nginx2!
ekzorchik@srv-us2204a:~$ curl 172.17.0.1:8083
Hello from nginx3!
ekzorchik@srv-us2204a:~$
Отлично.
Шаг №8:
Разворачиваем NPM (Nginx Proxy Manager):
ekzorchik@srv-us2204a:~$ mkdir nginx-proxy-manager
ekzorchik@srv-us2204a:~$ cd nginx-proxy-manager/
ekzorchik@srv-us2204a:~/nginx-proxy-manager$ nano docker-compose.yml
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
После нажимаем Ctrl + O, Enter - Ctrl + X
(для выхода из редактора).
запускаем NPM (Nginx Proxy Manager)
на основе составленного выше docker-compose.yml
ekzorchik@srv-us2204a:~/nginx-proxy-manager$ docker-compose up -d
[+] Running 36/36
✔ app Pulled 87.7s
[+] Running 2/2
✔ Network nginx-proxy-manager_default Created 0.1s
✔ Container nginx-proxy-manager-app-1 Started 0.8s
ekzorchik@srv-us2204a:~/nginx-proxy-manager$
ekzorchik@srv-us2204a:~/nginx-proxy-manager$ cd ~
ekzorchik@srv-us2204a:~$
По итогу у нас будет запущен один контейнер с Nginx Proxy Manager
, у которого проброшены порты 80, 81
и 443.
Шаг №9:
Далее настройка происходит уже через Web
—интерфейс, для этого открываем браузер с основной системы и в строке URL
адреса указываю http://IP&DNS:81
(после URL
трансформируется в http://172.33.33.10:81/login
) системы с осью Ubuntu 22.04 Server
где разворачиваем Nginx Proxy Management
и видим окно авторизации:
На заметку: По умолчанию дефолтные данные авторизации
Email address: admin@example.com
Password: changeme
и нажимаю "Sign in"
после появляется всплывающее окно где мастер первоначальной настройки просит указать:
Full name: Administrator (указано по умолчанию)
Nickname: Admin (указано по умолчанию)
Email: admin@example.com (указано по умолчанию)
пока ничего не меня и нажимаю "Save"
, но увы не прокатило, вижу надпись "Default email address must be changed"
, ну ладно изменяю на support@ekzorchik.com
и нажимаю "Save"
Затем еще окно, но в нем нужно изменить дефолтный пароль "changeme"
на свой
Current Password: changeme
New Password: 712mbddr@
Confirm Password: 712mbddr@
и нажимаю "Save"
Получается теперь для входа в Web
-интерфейс нужно будет указывать support@ekzorchik.com
и пароль 712mbddr@
По итогу наблюдаем — Web
-интерфейс управления:
Шаг №10:
Теперь настроим схему работы с тремя запущенными сервисами Nginx:
http://172.33.33.10:81 - email&pass
— переходим "Dashboard" - "0 Proxy Hosts" - "Add Proxy Host"
Domain Names: srv-nginx1.polygon.local
Scheme: http
Forward Hostname/IP: 172.17.0.1
Forward Port: 8081
и нажимаем «Save»
по аналогии добавляю и для двух других сервисом не забывая изменить порт и domain name
. В итоге должно получиться следующее:
Шаг №11:
Как проверить, если из консоли хоста где развернут Nginx Proxy Manager
обратиться через CURL
к внутреннего имени хоста, т.е. к srv-nginx[1-3].polygon.local
то должен прийти ответ содержимым index.html
файла:
ekzorchik@srv-us2204a:~$ curl http://srv-nginx1.polygon.local
Hello from nginx1!
ekzorchik@srv-us2204a:~$ curl http://srv-nginx2.polygon.local
Hello from nginx2!
ekzorchik@srv-us2204a:~$ curl http://srv-nginx3.polygon.local
Hello from nginx3!
ekzorchik@srv-us2204a:~$
Т.е. если раньше я обращался на IP:Port
и получал тоже самое что выше, то теперь я обращаюсь на DNS
имя.
Если хочется посмотреть на результат обращения по DNS
имя с системы на которой открывали Web
-интерфейс, но т.к. в локальной сети нет собственного DNS
-сервера, то нужно прописать, к примеру, на Windows
в файл c:\windows\system32\drivers\ets\hosts
строки
172.33.33.10 srv-nginx1.polygon.local
172.33.33.10 srv-nginx2.polygon.local
172.33.33.10 srv-nginx3.polygon.local
и уже через браузер обратившись на URL: http://srv-nginx1.polygon.local
О… удобно и вроде как теперь стало понятно, как работает Nginx Proxy Manager
, т.е. получаю содержимое nginx.html
в зависимости куда обращаюсь.
Что могу по итогу сказать, я взял за основу одну заметку в интернете и самолично ее прошел попутно для себя останавливаясь на определенных моментах и визуализируя их скриншотами дабы в последствии обратиться к этой заметке и вспомнить, как и что. Теперь я смогу переделать некоторые свои наработки на работу через Docker
, но это в планах. А пока заметку завершаю, если что будет продолжение, на этом все, с уважением автор блога Олло Александр aka ekzorchik.