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.

  1. DNS Settings: Go to your domain registrar (e.g., Cloudflare, Namecheap) and create an A Record for your subdomain (like app.example.com) pointing to your home’s Public IP address.
  2. Router Port Forwarding: Log into your physical home router. Forward incoming traffic on Port 80 (TCP) and Port 443 (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).

  1. In the Web UI, go to Hosts > Proxy Hosts.
  2. Click Add Proxy Host.
  3. Domain Names: Enter app.example.com and hit Enter.
  4. Scheme: Leave as http (unless your internal app forcefully requires https).
  5. Forward Hostname / IP: Enter the internal IP of the server running your app (e.g., 192.168.1.50).
  6. Forward Port: Enter the port your app uses (e.g., 32400).
  7. 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:

  1. SSL Certificate: Select “Request a new SSL Certificate”.
  2. Check the box for Force SSL (this redirects all HTTP traffic to HTTPS).
  3. Enter your email address for Let’s Encrypt expiration notices.
  4. Agree to the Terms of Service.
  5. 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.