How-To: Secure Nginx Proxy Manager Admin UI with Your Own SSL Certificates

This article walks you through using Nginx Proxy Manager (NPM) to secure its own administrative interface (port 81) with a custom SSL certificate, instead of using Let’s Encrypt.


1. Prerequisites

  • Nginx Proxy Manager deployed via Docker Compose.
  • A valid .crt (certificate) and .key (private key) for your FQDN, e.g., innerweb.linux.matthewdavidson.us.
  • Your domain’s DNS A record pointing to the server running NPM.
  • Docker and Docker Compose installed on your host (tested with Docker CLI v2+).

Directory layout assumes:

~/nginx-proxy-manager/
├── docker-compose.yml
├── data/
│   └── custom_ssl/
│       ├── innerweb.linux.matthewdavidson.us.crt
│       └── innerweb.linux.matthewdavidson.us.key
└── letsencrypt/   # used by NPM for LE storage (unused here)

2. Prepare Docker Compose

  1. Open your docker-compose.yml under ~/nginx-proxy-manager/.
  2. Use host networking so the container binds directly to the host’s ports:
version: '3'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
  1. Save and recreate the container:
cd ~/nginx-proxy-manager
docker compose up -d --force-recreate app

Why:

  • network_mode: host allows NPM to listen on host ports 80, 81, and 443 directly, simplifying proxying.

3. Import Your Custom Certificate

  1. Log into the NPM UI at http://<server-IP>:81.
  2. Navigate to SSL CertificatesAdd SSL CertificateCustom.
  3. Fill in:
  • Name: innerweb.linux.matthewdavidson.us
  • Domain Names: innerweb.linux.matthewdavidson.us
  • Certificate: either paste the contents of innerweb.linux.matthewdavidson.us.crt or click Select and choose /data/custom_ssl/innerweb.linux.matthewdavidson.us.crt.
  • Key: paste or select /data/custom_ssl/innerweb.linux.matthewdavidson.us.key.
  1. Click Save.

Your certificate is now stored in NPM under /data/ssl/.


4. Create a Self‑Proxy Host for the Admin UI

  1. In the NPM UI go to HostsProxy HostsAdd Proxy Host.
  2. On the Details tab:
  • Domain Names: innerweb.linux.matthewdavidson.us
  • Scheme: http
  • Forward Hostname / IP: app
    (This matches the service name in Docker Compose.)
  • Forward Port: 81
  1. Check Block Common Exploits if desired.
  2. Switch to the SSL tab:
  • Enable SSL
  • Custom SSL → select your certificate “innerweb.linux.matthewdavidson.us”
  • Force SSL
  • HTTP/2
  • HSTS (optional)
  • Leave any Let’s Encrypt options unchecked.
  1. On the Advanced tab (or Advanced → Custom Nginx Configuration), add:
# Rewrite internal admin UI redirects back to external FQDN
proxy_redirect http://192.168.0.244:81/ https://innerweb.linux.matthewdavidson.us/;
  1. Click Save.

Tip: Adjust the internal IP 192.168.0.244 if your host’s IP differs.


5. Finalize and Test

  1. Ensure your DNS A record for innerweb.linux.matthewdavidson.us points to your server’s public or LAN IP.
  2. In your browser, visit:
  • HTTPhttp://innerweb.linux.matthewdavidson.us (should redirect to HTTPS)
  • HTTPShttps://innerweb.linux.matthewdavidson.us
  1. You should see the NPM login page with your custom SSL certificate properly presented.

6. Troubleshooting

  • 502 Bad Gateway:
  • Verify you used expose: '81' in Compose, not ports: for 81.
  • Confirm Forward Hostname is app (matching the Docker service name).
  • Tail NPM logs: docker compose logs -f app or check /data/logs/proxy_host-<ID>.error.log.
  • Certificate Mismatch / Redirects:
  • Ensure your Advanced proxy_redirect line matches the internal URL your UI listens on.
  • Double‑check that Force SSL is enabled under SSL settings.

Conclusion

You have now secured the Nginx Proxy Manager administrative interface behind your own SSL certificate. All traffic flows through port 443 on your FQDN, and the internal admin port remains hidden from direct access.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *