TL;DR — Quick Summary
A comprehensive how-to guide for setting up Nginx Proxy Manager via Docker Compose to expose self-hosted services securely with Let's Encrypt SSL.
If you are running a home lab or a self-hosted cloud on a VPS, you eventually face a common problem: how do you access multiple web services on the same server when you only have one public IP address and port 443?
The answer is a Reverse Proxy. Instead of manually writing Nginx configuration files and managing Let’s Encrypt certificates via terminal commands, Nginx Proxy Manager (NPM) gives you a beautiful web UI to manage everything.
In this guide, we will set up Nginx Proxy Manager using Docker Compose, forward ports, and expose your first internal service to the internet securely over HTTPS.
Prerequisites
- A Linux host containing Docker and Docker Compose (see our guide: How to Install Docker on Ubuntu)
- A domain name that you control (e.g.,
example.com) - Access to your home router to forward ports (if hosting at home)
Step 1: Create the docker-compose.yml file
We will deploy Nginx Proxy Manager using Docker Compose because it makes updates painless. SSH into your host server and create a directory for the application data:
mkdir -p ~/nginx-proxy-manager
cd ~/nginx-proxy-manager
Create a new docker-compose.yml file using nano or your favorite editor:
nano docker-compose.yml
Paste the following configuration. By default, this uses a lightweight SQLite database which is more than sufficient for home labs with under 50 hosts.
version: '3.8'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
# These ports are in format <host-port>:<container-port>
- '80:80' # Public HTTP Port
- '81:81' # Admin Web Port
- '443:443' # Public HTTPS Port
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
Save and exit the file.
Step 2: Start Nginx Proxy Manager
Now, bring up the container in detached mode:
docker compose up -d
Docker will pull the official image and start the service. You can check the logs to ensure the database initialized correctly:
docker compose logs -f
Step 3: Access the Web Dashboard
Once the container is running securely, open a web browser on your computer and navigate to:
http://<your-server-ip>:81
You will be greeted by the Nginx Proxy Manager login screen. Use the default administrative credentials:
- Email:
admin@example.com - Password:
changeme
Immediately upon logging in, NPM will force you to update the Administrator details (Name, Email) and change the password to something secure.
Step 4: Configure DNS and Router Port Forwarding
Before exposing a service, you must point DNS to your IP and open ports on your network firewall.
- DNS Settings: Go to your domain registrar (e.g., Cloudflare, Namecheap) and create an
A Recordfor your subdomain (likeapp.example.com) pointing to your home’s Public IP address. - Router Port Forwarding: Log into your physical home router. Forward incoming traffic on Port
80(TCP) and Port443(TCP) to the internal IP address of the Linux server running Nginx Proxy Manager.
(Note: Do not forward port 81 to the internet. Keep the admin dashboard local-only for security).
Step 5: Add a Proxy Host and Request an SSL Certificate
Now we will link app.example.com to an internal service (like a local Plex server running on port 32400).
- In the Web UI, go to Hosts > Proxy Hosts.
- Click Add Proxy Host.
- Domain Names: Enter
app.example.comand hit Enter. - Scheme: Leave as
http(unless your internal app forcefully requireshttps). - Forward Hostname / IP: Enter the internal IP of the server running your app (e.g.,
192.168.1.50). - Forward Port: Enter the port your app uses (e.g.,
32400). - Check the boxes for Block Common Exploits and Websockets Support if needed by your app.
Enabling HTTPS
Before clicking save, switch to the SSL tab:
- SSL Certificate: Select “Request a new SSL Certificate”.
- Check the box for Force SSL (this redirects all HTTP traffic to HTTPS).
- Enter your email address for Let’s Encrypt expiration notices.
- Agree to the Terms of Service.
- Click Save.
Nginx Proxy Manager will reach out to Let’s Encrypt behind the scenes, perform the HTTP-01 challenge to verify you own the domain, issue the certificate, and reload Nginx automatically.
In about 10 seconds, your site is securely available over HTTPS!
Troubleshooting
- Internal Error when requesting SSL: This almost always means Let’s Encrypt could not reach NPM on port 80 over the internet. Verify that port 80 is forwarded correctly through your router to your NPM server, and that your ISP isn’t blocking port 80.
- 502 Bad Gateway: NPM received the traffic, but NPM cannot reach your internal app. Check the “Forward Hostname/IP” and ensure no internal firewalls (like
ufw) are blocking traffic between NPM and the destination service.
Conclusion
Nginx Proxy Manager has brought the power of enterprise reverse proxies to homelabbers without the steep learning curve of writing configuration code. You can now expose as many services as you want securely, with automated SSL renewals keeping your connections private.