Skip to main content
Scraper API

How to Set Up Nginx Proxy Manager: A Complete 2026 Guide

7 min read

How to Set Up Nginx Proxy Manager: The 2025 Implementation Guide

For modern web infrastructure, few tools bridge the gap between complex server administration and usability as effectively as Nginx Proxy Manager (NPM). Whether you are exposing a Python Flask API, securing a Home Assistant server, or managing multiple WordPress instances, NPM removes the overhead of writing Nginx configuration files by hand.

This guide provides a technical deep-dive into setting up, securing, and optimizing NPM using Docker and Ubuntu 24.04.

Prerequisites and Architecture

Before deploying, ensure your environment meets the following standards:

1. Operating System: Ubuntu 24.04 LTS or Debian 12. 2. Dependencies: Docker Engine 25+ and Docker Compose v2. 3. Networking: A public static IP or a local DNS resolver (like Pi-hole) pointing to your host. 4. Firewall: UFW (Uncomplicated Firewall) configured to allow traffic.

The NPM Architecture

NPM consists of a Node.js application handling the UI and API, while the backend uses a custom build of Nginx. When you click "Save" in the UI, the application dynamically generates Nginx configuration files and reloads the service without downtime.

---

Part 1: Docker Deployment (The Standard Method)

Running NPM in a Docker container ensures isolation and simplifies updates. We will use a docker-compose.yml file for reproducibility.

Step 1: Directory Structure

Create a dedicated directory for your persistence data to survive container recreation.

mkdir -p ~/npm/data

mkdir -p ~/npm/letsencrypt

Step 2: The Docker Compose Configuration

Create a file named docker-compose.yml:

version: '3.8'

services: nginx-proxy-manager: image: 'jc21/nginx-proxy-manager:latest' container_name: nginx-proxy-manager restart: unless-stopped ports: - '80:80' # Public HTTP - '443:443' # Public HTTPS - '81:81' # Admin Interface environment: # Disable the DB inside the container if using an external DB, # but for this standard setup, we use SQLite internally. DB_SQLITE_FILE: "/data/database.sqlite" volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt # Optional: Add IP to see the real client IP in logs # extra_hosts: # - "host.docker.internal:host-gateway"

Step 3: Launching the Stack

Execute the following command to pull the image and start the service:

docker compose up -d

Step 4: Initial Access & Credential Reset

1. Navigate to http://:81. 2. Default Credentials: * Email: admin@example.com * Password: changeme 3. You will be immediately prompted to set your full name and a new secure password.

---

Part 2: Configuring Reverse Proxies and SSL

The core function of NPM is to listen on port 80/443 and forward traffic to a backend container (upstream) running on a different port, such as a Python scraper or a Node.js app.

Scenario: Hosting a Python Flask App

Let's assume you have a Python application running on port 5000.

1. Dashboard Navigation: Go to Hosts > Proxy Hosts. 2. Add Proxy Host: * Domain Names: api.yourdomain.com * Scheme: http * Forward Hostname / IP: 172.17.0.1 (Docker bridge IP) or the container name if on the same network. * Forward Port: 5000 3. SSL Configuration: * Select the SSL tab. * Certificate: Select "Request a new SSL Certificate". * Force SSL: Enable this (HSTS) to ensure all HTTP traffic redirects to HTTPS. * Agree to the Let's Encrypt Terms of Service.

The Importance of Cache Assets

In the Advanced tab of the Proxy Host configuration, you can inject custom Nginx location blocks. For web scraping or API servers, you might want to control headers:

Nginx Custom Location Configuration

location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }

---

Part 3: Proxying to a Subfolder (Path Rewriting)

A common use case is mapping a service to a subfolder (e.g., example.com/tools instead of tools.example.com).

1. Set the Domain to example.com. 2. Set the Scheme, Forward IP, and Port as usual. 3. Crucial Step - Advanced Tab: NPM handles the external routing, but your internal application needs to know it is serving from a subfolder. You must append the path in the location box:

location /tools {

proxy_pass http://172.17.0.1:3000/tools; # Or simply proxy_pass http://172.17.0.1:3000/; if the app handles the path }

> Note: Many modern web apps (like Grafana or Home Assistant) have specific configuration settings (e.g., base_url) that must match this folder path for assets to load correctly.

---

Part 4: Security Hardening with CrowdSec

As of 2025, exposing NPM directly to the internet invites brute-force attacks. The reference knowledge data suggests interest in the CrowdSec Nginx Proxy Manager Bouncer.

CrowdSec is a security automation engine that parses logs and detects aggressive behavior. Integrating it with NPM prevents attackers from ever reaching your login page.

Installing the CrowdSec Bouncer

If you are running NPM on the host (rather than in Docker, or using host networking for logs), you can install the bouncer to read the Nginx logs.

1. Install CrowdSec:

    curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash

sudo apt install crowdsec

2. Install the Nginx Bouncer:

    sudo apt install crowdsec-nginx-bouncer

3. Configuration: The bouncer will hook into /var/log/nginx/access.log. When CrowdSec detects an IP scanning for SQLi or attempting auth bypass, it sends a command to the firewall (usually nftables or iptables) to drop the packets.

For Dockerized NPM, you must mount the Nginx logs from the container to the host so CrowdSec can read them. In your docker-compose.yml:

volumes:

- ./data/logs:/var/log/nginx # Maps container logs to host

You then configure the CrowdSec acquisition file to point to ./data/logs/access.log.

---

Part 5: Troubleshooting Common Issues (2025 Edition)

Nginx Proxy Manager Not Redirecting

If HTTPS redirection loops or fails: 1. Check DNS: Ensure your A Record (@) points to the NPM server IP, not a CNAME. 2. Port Conflicts: Ensure no other services (like Apache or a previous Nginx install) are hogging port 80/443.

    sudo lsof -i :80

3. Let's Encrypt Limits: If testing frequently, you might hit the "Certificates per registered domain" limit (usually 5 per week). Use the "Staging" checkbox in NPM SSL settings to test without burning actual certificates.

Access List Configuration

The "Access List" tab in NPM allows you to password-protect a site without touching the application itself.

  • Basic Auth: Username/Password prompt (Browser native).
  • Allowlist: Only specific IP addresses can access the site.
  • Satisfy Any: Useful for developers: "Allow access if the IP is in the allowlist OR if they provide the correct password."

Conclusion

Setting up Nginx Proxy Manager transforms a complex web server configuration into a manageable web interface. By leveraging Docker Compose for deployment and integrating tools like CrowdSec for security, you create a robust gateway for your web scraping agents, APIs, or self-hosted services. As you scale, remember to monitor your log files and utilize the "Stream" feature for non-HTTP traffic (like TCP or UDP forwarding) often required by game servers or databases.

Share: