Table of Contents
Nginx Proxy Manager is a tool for managing and configuring Nginx reverse proxies through a user-friendly web interface. It offers support for multiple domains, HTTPS/SSL certificates, and automatic Let’s Encrypt integration. Whether you are a technical user looking to set up and manage your own Nginx proxy server or a non-technical user looking for an easy way to get started with Nginx, Nginx Proxy Manager is a great choice.
- Public domain or at least a DynDNS domain (e.g. DuckDNS) pointing to your routers public interface
- Port Forwarding for HTTP (80/tcp) and HTTPS (443/tcp) Traffic
Port Forwarding #
For your Reverse Proxy to work it is necessary that any http(s) traffic
https://myservice.domain.tld) is pointed to the host you’re running Nginx Proxy Manager on. This requires a public domain or at least a Dynamic DNS domain pointing to the public interface (in other words your public IP Address) of your router. Now all you have to do is forwarding the ports
443/tcp to the host of Nginx Proxy Manager.
The way you do this depends on your router, just google something like
port forwarding <ROUTER_MODEL>.
Create a external
docker network called
Adding our services and Nginx Proxy Manager to the same
docker network later on makes sure, our Reverse Proxy can redirect to them without the need of exposing ports for every single service. More on that
docker network create reverse-proxy
Create a installation directory for Nginx Reverse Proxy.
version: "3" services: app: image: 'jc21/nginx-proxy-manager:latest' restart: unless-stopped container_name: nginx-proxy-manager ports: # These ports are in format <host-port>:<container-port> - '80:80' # Public HTTP Port - '443:443' # Public HTTPS Port - '81:81' # Admin Web Port # Add any other Stream port you want to expose # - '21:21' # FTP environment: DB_MYSQL_HOST: "db" DB_MYSQL_PORT: 3306 DB_MYSQL_USER: "npm" DB_MYSQL_PASSWORD: "password" DB_MYSQL_NAME: "npm" # Uncomment this if IPv6 is not enabled on your host # DISABLE_IPV6: 'true' volumes: - /opt/nginx-proxy-manager/data:/data - /opt/nginx-proxy-manager/letsencrypt:/etc/letsencrypt depends_on: - db db: image: 'jc21/mariadb-aria:latest' restart: unless-stopped container_name: nginx-proxy-manager_db environment: MYSQL_ROOT_PASSWORD: 'root' MYSQL_DATABASE: 'npm' MYSQL_USER: 'npm' MYSQL_PASSWORD: 'password' volumes: - /opt/nginx-proxy-manager/data/mysql:/var/lib/mysql networks: default: external: name: reverse-proxy
networksblock adds Nginx Proxy Manager to the earlier created docker network
Spin the container up with:
docker-compose up -d
In case of troubleshooting see the docker logs with:
docker logs nginx-proxy-manager.
You now should be able to browse to http://<host_ip_address>:81 and log in with the default credentials:
Email: email@example.com Password: changeme
Right after your first login you’ll be requested to change your account details and set a new password.
You’re now able to start setting up your SSL certificates and create your first proxy hosts.
SSL Certificates #
Why are we using a Reverse Proxy in the first place?
We want to access our services in a secure and trusted way, this is where SSL Certificates come into play to help us keep user data secure by verifying ownership of a website and therefor preventing Man-in-the-middle attacks.
With Nginx Proxy Manager and its integrated Certbot you can either create SSL Certificates per Proxy Host (like
service.domain.tld) or implement a single Wildcard Certificate which can be used for all Proxy Hosts within your domain (like
*.domain.tld). Since having a dedicated SSL Certificate for every service you’re running can get quite messy with time I recommend using a much more convinient Wildcard Certificate.
Wildcard Certificate (Cloudflare) #
To do so we need to create an API Token from our DNS provider, in this case we are using Cloudflare.
Follow this link to your Cloudflare profile and click on Create Token and create a Custom Token.
This should generate an API Token you can use for Nginx Proxy Manager to interact with your Cloudflare account.
Now let’s create a Wildcard Certificate in Nginx Proxy Manager, to do so click Add SSL Certificate in the SSL Certificates tab.
Fill out all the necessary information and click on save.
This process can take a few minutes but if everything goes right your should be presented with your newly created Wildcard Certificate, which can be used for all future proxy hosts you create within your domain.
Restricting Access #
Since the majority of your services for security reasons should not directly be published to the internet Nginx Proxy Manager allows to implement Access Lists. With these Access Lists we can restrict access by defining IP Address Whitelists and Blacklists or forcing Authorization.
Before publishing your services to the internet check the following post about WireGuard, set up your own VPN and securely access your self-hosted services…
For your services to be reachable via a Proxy Host you need some kind of local DNS service pointing to Nginx Proxy Manager since you won’t create a public DNS record for them ( Pi-hole for example comes with local DNS too).
In this step we will create a Access List called
local and therefor restrict access to local subnets by clicking on Add Access List in the Access Lists tab.
Fill in the details and whitelist the local subnets
You can now select this Access List when creating a Proxy Host.
Your first Proxy Host #
We can finally create our first Proxy Host, click on Add Proxy Host in the tab Hosts –> Proxy Hosts.
Define the Domain Name and the destination (Hostname / IP Address and Port of your service).
Select the SSL Certificate we created earlier and click on Save.
We should now be able to browse our service securely via the defined URL
Pro Tip #
As long as your instance of Nginx Proxy Manager and the service you want to create a Proxy Host for are running on the same host, you can join them in the same
docker network and reach your service without the need of exposing ports.
To do so we have to join our service (in this case Uptime Kuma) the same
docker network as Nginx Proxy Manager and comment out the port exposure.
Add the following code to join your service to the
docker network called
networks: default: external: name: reverse-proxy
docker-compose.yml should look something like this:
version: "3.8" services: app: container_name: uptime-kuma image: louislam/uptime-kuma:1 restart: unless-stopped volumes: - uptime-kuma:/app/data # ports: # - "50001:3001" volumes: uptime-kuma: driver: local networks: default: external: name: reverse-proxy
container_namefor your service too since this is the hostname Nginx Proxy Manager will be redirecting to.
Recreate the docker container with the following command:
docker compose up -d --force-recreate
container portyou can always check with
We can now adjust the Proxy Host for our service by entering the
container_name as Forward Hostname / IP and the
container port as Forward Port.
If everything works as expected you are now able to access your service without exposing any ports of the docker container.
Final Thoughts #
Besides Nginx Proxy Manager there are many popular Reverse Proxy services out there, for example
Caddy just to name a few.
The convinience of an easy-to-use Web GUI and the solid functionality never gave me a reason to consider changing to any other Reverse Proxy solution.
Nginx Proxy Manager is beginner-friendly and doesn’t leave you hanging even when your requirements might get more advanced, it’s all in all a great choice.
Consider leaving a ⭐ at the GitHub Repo if you like Nginx Proxy Manager.