How to Set Up Nginx Proxy Manager on Docker: A Beginner-Friendly Guide to Reverse Proxies and HTTPS
Learn how to set up Nginx Proxy Manager on Docker, add Let's Encrypt SSL, and proxy self-hosted apps with a beginner-friendly step-by-step guide.
Author
David Okonkwo
FTC disclosure: This article contains affiliate links. If you purchase through these links, we may earn a commission at no extra cost to you.
Key Takeaways
- Nginx Proxy Manager gives you a web UI for reverse proxies, SSL certificates, redirects, and access rules.
- For a single-node homelab, the built-in SQLite setup is usually enough to get started.
- Ports 80 and 443 matter because Let’s Encrypt HTTP-01 validation depends on them.
- A shared Docker network makes it much easier to proxy one container to another cleanly.
- Your first goal is not perfection - it is getting one test app online with HTTPS and understanding why it works.
If you have ever looked at a reverse proxy guide, seen ten blocks of Nginx config, and immediately wanted to close the tab, you are not alone. Reverse proxies are one of those homelab topics that sound more complicated than they need to be.
The good news is that Nginx Proxy Manager removes most of the manual Nginx work. Think of it like the front desk in a hotel. Visitors arrive at one address, and the front desk sends each person to the right room. In homelab terms, one public domain reaches your server, and the proxy sends traffic to the right app.
In this guide, we will set up Nginx Proxy Manager on Docker, connect it to a test container, and cover the DNS and SSL details that usually trip beginners. I will keep the commands real, the explanations plain, and the danger signs obvious before you hit them.
If you want broader context first, read our reverse proxy comparison for homelabs. If your Docker Compose habits are still forming, our Docker Compose best practices guide is worth bookmarking too.
What Nginx Proxy Manager actually does
Nginx Proxy Manager is a web-based control panel that sits in front of your self-hosted services. Instead of hand-editing Nginx configuration files, you fill out forms in the admin UI.
Why this matters: beginners usually do not fail because reverse proxies are impossible. They fail because one typo in a config file can break routing, SSL, or redirects. Nginx Proxy Manager reduces that friction so you can learn the pattern before learning the raw syntax.
With it, you can:
- route
app.example.comto a Docker container - issue a free Let’s Encrypt certificate
- force HTTPS
- create access lists for internal-only services
- manage several apps from one place
Official references you should keep open:
What you need before you start
Before we touch Docker Compose, make sure you have:
- Docker and Docker Compose installed
- A Linux server, mini PC, VM, or Raspberry Pi that stays on
- A domain name you control if you want public HTTPS
- Ports 80 and 443 available on the host
- A basic idea of whether your service will be local-only or internet-reachable
Why this matters: Nginx Proxy Manager is easy to deploy, but certificates are not magic. If your domain does not point to your home IP, or your ISP blocks port 80, Let’s Encrypt may fail no matter how correct your Compose file is.
If you are still getting comfortable with Docker networking, our Pi-hole on Docker guide is another good example of containerized service setup from start to finish.
Recommended hardware
You do not need a monster server for this. A reverse proxy is more like a traffic cop than a database cluster.
- Beelink N100 mini PC - a great low-power Docker host for a small homelab
https://www.amazon.com/s?k=beelink+n100+mini+pc&tag=homelabaddiction-20 - Raspberry Pi 5 8GB starter kit - fine for lightweight proxy and utility workloads
https://www.amazon.com/s?k=raspberry+pi+5+8gb+starter+kit&tag=homelabaddiction-20 - APC Back-UPS 1500VA - worth it if this proxy is the doorway to several services
https://www.amazon.com/s?k=apc+back-ups+1500va&tag=homelabaddiction-20
Step 1: Check your ports and decide your access model
Why this matters
Before you start the container, decide whether this proxy will serve:
- only your local network
- or your public domain over the internet
That decision changes how DNS and SSL behave. A local-only lab can work with internal DNS and self-signed or DNS-based certificate strategies. A public setup usually expects ports 80 and 443 to reach your server.
Run these checks
ss -tulpn | grep -E ':80 |:81 |:443 '
If you get no output, those ports are probably free. If you see Apache, Caddy, Traefik, or another Nginx instance already listening, stop and resolve that first.
You should also confirm Docker is healthy:
docker version
docker compose version
What could go wrong:
- If port 80 is already in use, Nginx Proxy Manager will fail to start.
- If port 443 is already in use, HTTPS termination will fail.
- If port 81 is already in use, the admin panel will need a different host port.
Step 2: Create a shared Docker network and project directory
Why this matters
A shared Docker network is like putting your containers in the same neighborhood. When services share a network, Nginx Proxy Manager can reach them by container name instead of hard-coded IP addresses.
That matters because container IPs change. Names are stable. Stable names make your future self much happier.
Create the network
docker network create proxy
If Docker says the network already exists, that is fine.
Create your project folder
mkdir -p ~/apps/nginx-proxy-manager/{data,letsencrypt}
cd ~/apps/nginx-proxy-manager
Step 3: Create the Docker Compose file
Why this matters
For a small homelab, the default SQLite-based deployment is the simplest place to start. You can move to MariaDB or Postgres later if you have a reason. Starting simple is not laziness. It is good operational hygiene.
Create compose.yaml:
services:
npm:
image: jc21/nginx-proxy-manager:2.15.1
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80"
- "81:81"
- "443:443"
environment:
TZ: UTC
DISABLE_IPV6: "true"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- proxy
networks:
proxy:
external: true
If you prefer to create the file from the terminal, you can use:
cat > compose.yaml <<'EOF'
services:
npm:
image: jc21/nginx-proxy-manager:2.15.1
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80"
- "81:81"
- "443:443"
environment:
TZ: UTC
DISABLE_IPV6: "true"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- proxy
networks:
proxy:
external: true
EOF
A note on databases: the official docs also show MySQL, MariaDB, and Postgres options. For a first working homelab install, SQLite is perfectly reasonable.
Step 4: Start the stack and confirm it is healthy
Why this matters
This is where you verify the container can actually claim the ports, mount its storage, and come up cleanly. We want a healthy base before touching DNS or certificates.
Start the stack:
docker compose up -d
Check status:
docker compose ps
Then check logs:
docker compose logs -f npm
Once you see the container settle down, open the admin interface in your browser:
http://YOUR_SERVER_IP:81
Default credentials are usually:
- Email:
admin@example.com - Password:
changeme
You will be prompted to change them after first login.
What could go wrong:
- If the admin page never loads, check that port 81 is reachable from your browser.
- If the container restarts repeatedly, inspect
docker compose logs npmfor port conflicts or permission issues. - If your server has a firewall, allow ports 80, 81, and 443.
Step 5: Create a test app so you can prove the proxy works
Why this matters
Do not point your first proxy host at something precious. Use a disposable test app first. It is the same reason electricians test a circuit before plugging in expensive gear.
Deploy a tiny test container on the same network:
docker run -d \
--name whoami \
--network proxy \
--restart unless-stopped \
traefik/whoami
Confirm it is running:
docker ps --filter name=whoami
At this point, Nginx Proxy Manager should be able to reach the service by hostname whoami on port 80.
Step 6: Point DNS at your server
Why this matters
A reverse proxy routes traffic after the traffic reaches your server. DNS is what gets the traffic there in the first place.
Create an A record like this at your DNS provider:
whoami.example.com-> your public IP
If your home IP changes often, use dynamic DNS. That keeps your domain pointed at the right place without manual updates.
For local-only labs, you can use internal DNS instead. In that case, public Let’s Encrypt HTTP-01 validation may not work unless your domain still resolves publicly and port 80 is reachable.
This is where many beginners get stuck. The container is fine. Docker is fine. The domain is the broken part.
Step 7: Create your first proxy host
Why this matters
This is the moment the front desk gets its first guest. We are telling Nginx Proxy Manager which domain should route to which backend service.
In the Nginx Proxy Manager UI:
- Click Hosts
- Click Proxy Hosts
- Click Add Proxy Host
- Enter your domain, for example
whoami.example.com - Set Scheme to
http - Set Forward Hostname / IP to
whoami - Set Forward Port to
80 - Enable Block Common Exploits
- Save
Why whoami works: because both containers are on the shared proxy Docker network. Docker provides DNS for container names on the same network.
If your real app lives outside Docker on the same host or on another machine, you can use the server IP or hostname instead.
Step 8: Add HTTPS with Let’s Encrypt
Why this matters
HTTPS is not just a padlock for appearances. It protects credentials, session cookies, and private traffic between you and your services.
In the proxy host you just created:
- Open the SSL tab
- Choose Request a new SSL Certificate
- Enable Force SSL
- Enable HTTP/2 Support
- Optionally enable HSTS if you understand the implications
- Save
If everything is lined up, Nginx Proxy Manager will request the certificate and attach it to the host.
Why port 80 matters here
Let’s Encrypt HTTP-01 validation expects a token to be reachable on port 80. That is why so many homelab SSL attempts fail. People open 443 and forget 80, or their ISP blocks 80, or they are behind CGNAT.
If you are unsure which challenge to use, Let’s Encrypt says HTTP-01 is the default choice in most normal cases. DNS-01 is better when you need wildcard certificates or cannot expose port 80.
Step 9: Verify from the outside
Why this matters
A lot of setups work from inside the house and fail everywhere else. You want to test the actual reader experience, not just your optimistic interpretation of it.
From another device, visit:
https://whoami.example.com
You should see the whoami output page with request details. That confirms:
- DNS points correctly
- Nginx Proxy Manager is routing correctly
- SSL is valid
- the backend container is reachable
You can also verify the containers:
docker compose ps
docker logs nginx-proxy-manager --tail 50
docker logs whoami --tail 50
Common mistakes
1. Forgetting the shared Docker network
If Nginx Proxy Manager cannot resolve your app container name, make sure both services are on the same network.
2. Port 80 is blocked
This is one of the biggest Let’s Encrypt failure modes in homelabs. Some ISPs block it, and some users only forward 443.
3. The domain points to the wrong IP
If your DNS still points to an old address, certificate issuance and routing will both fail.
4. Forwarding to localhost
Inside a container, localhost means the container itself, not your Docker host. That mistake wastes a shocking amount of time.
5. Leaving the default admin password too long
Change it immediately. You do not want admin@example.com / changeme guarding the doorway to your services.
6. Publishing every backend port unnecessarily
If Nginx Proxy Manager can reach a service over the Docker network, you often do not need to expose that backend app directly to the host.
When to use SQLite, and when to move on
For one homelab node and a sensible number of services, SQLite is fine. It keeps the stack small and easy to back up.
Move to MariaDB or Postgres when you want tighter separation, already run a database anyway, or need a setup that matches a larger operational standard. Beginners often overbuild this part. Do not build a tiny enterprise just to proxy Jellyfin.
Securing the setup after day one
Once the basics work, your next improvements should be practical:
- change the admin credentials immediately
- add a strong password manager entry for them
- restrict admin access with firewall rules or VPN where possible
- back up the
dataandletsencryptdirectories - consider adding SSO later for sensitive apps
If you want to go further with identity and access control, our Authelia SSO guide is the logical next step.
FAQ
Do I need a domain name to use Nginx Proxy Manager?
For the cleanest experience, yes. You can use it without a public domain in some local-only scenarios, but public HTTPS is much easier when you control a real domain.
Can I use Nginx Proxy Manager with Docker Compose services on the same host?
Yes. That is one of the best use cases. Put the proxy and your apps on a shared Docker network, then forward to the app by service or container name.
Should I use SQLite or MariaDB for a beginner setup?
Use SQLite first unless you already know why you need a separate database. It is simpler and completely acceptable for a small homelab deployment.
Why is the admin panel on port 81?
Because ports 80 and 443 are reserved for proxied web traffic, while port 81 is used for the management UI.
What if Let’s Encrypt keeps failing?
Check DNS first, then port forwarding, then whether port 80 is reachable publicly. If your ISP blocks port 80 or you are behind CGNAT, you may need a DNS-01 workflow instead.
What to learn next
A simple mental model to keep
When this setup feels confusing, remember the traffic path in order: DNS points the visitor to your server, Nginx Proxy Manager receives the request, the proxy host rule matches the domain, and Docker networking delivers the request to the right container. If one of those four steps is broken, the whole chain feels broken.
Once this works, you are ready for the more interesting parts of self-hosting:
- compare proxy options in our Caddy vs Traefik vs Nginx Proxy Manager guide
- tighten your Compose habits with our Docker Compose best practices article
- front a real service like Pi-hole on Docker
- add authentication in front of internal apps with Authelia SSO
If homelab networking still feels fuzzy, that is normal. A reverse proxy is one of those concepts that clicks after the first successful deployment. Once you watch one domain land on the right app with a valid certificate, the mystery disappears fast.
