Хочу (На 07.10.2025) приобщиться к использованию Nginx Proxy Manager для своих сервисов, а где свои сервисы, там и по работе пригодится.

Вычитал, что Nginx Proxy Manager — это обратный прокси-сервер (reverse proxy) с поддержкой Web-интерфейса, разработанный для упрощения настройки и управлением обратными прокси на основе веб-сервера Nginx. Сервис используется для организации доступа к различным веб-приложениям через единую точку входа (в качестве единой точки входа может выступать, например, доменное имя или IP-адрес) с дальнейшей маршрутизацией до конечного приложения.

Хотя если так посмотреть, что даже без Web-оболочки я уже такое использую, если вспомнить мои заметки:

они не плохо отрабатывают, а тут просто удобство, но раз есть такое, так почему-бы не приобщиться к чему-то новому, да и плюсом будет не редактирование вручную конфигурационных файлов, а через 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 и видим окно авторизации:

Окно авторизации в 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@

Изменяю пароль с дефолтного changeme на свой, к примеру на 712mbddr@

и нажимаю "Save"

Получается теперь для входа в Web-интерфейс нужно будет указывать support@ekzorchik.com и пароль 712mbddr@

По итогу наблюдаем — Web-интерфейс управления:

По итогу наблюдаем - Web-интерфейс управления Nginx Proxy Management

Шаг №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

Создаю настройки перенаправления при обращении на Domain Name

и нажимаем «Save»

по аналогии добавляю и для двух других сервисом не забывая изменить порт и domain name. В итоге должно получиться следующее:

Настроенные перенаправления при обращении по Domain Name для трех nginx сервисов.

Шаг №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

При обращении через браузер на узел srv-nginx1.polygon.local отрабатывает Proxy до index.html

О… удобно и вроде как теперь стало понятно, как работает Nginx Proxy Manager, т.е. получаю содержимое nginx.html в зависимости куда обращаюсь.

Что могу по итогу сказать, я взял за основу одну заметку в интернете и самолично ее прошел попутно для себя останавливаясь на определенных моментах и визуализируя их скриншотами дабы в последствии обратиться к этой заметке и вспомнить, как и что. Теперь я смогу переделать некоторые свои наработки на работу через Docker, но это в планах. А пока заметку завершаю, если что будет продолжение, на этом все, с уважением автор блога Олло Александр aka ekzorchik.