Skip to main contentSkip to navigation
[email protected]
Client AreaSupport
Hosting Mammoth
HostingMammothYour Data, Our Responsibility
Home
Solutions
Hosting Services
Store
Pricing
About
Blog
API
Contact

Stay Ahead of the Curve

Get the latest insights on cybersecurity, AI innovations, and enterprise data solutions delivered to your inbox.

Hosting Mammoth
HostingMammothEnterprise Solutions

Enterprise-grade data solutions. Hosting, recovery, cybersecurity, and AI-powered services for businesses worldwide.

[email protected]
Sun - Fri, 9:00am - 5:00pm

Services

  • Cloud Hosting
  • Data Recovery
  • Cybersecurity
  • Legal Support
  • MSP Services
  • Web Development
  • AI Services
  • Free Server Migration

Hosting

  • VPS Hosting (NVMe SSD)
  • VDS Hosting (NVMe)
  • Storage VPS (High SSD)
  • GPU Servers
  • Managed Services
  • Cloud Firewall
  • Load Balancer
  • One-Click Apps
  • n8n Hosting
  • Object Storage
  • FAQ

Company

  • Store
  • Pricing
  • About Us
  • Locations
  • Blog
  • Testimonials
  • Contact
  • Affiliate Program
  • White-Label
  • Terms of Service
  • Privacy Policy
  • Browser Cookies
  • SLA

Support

  • Client Area
  • Submit Ticket
  • Knowledge Base
  • Server Status
  • API Documentation

© 2026 Hosting Mammoth. All rights reserved.

Knowledge Base
Getting StartedAccount ManagementVPS HostingGPU ServersStorage VPSCloud FirewallLoad BalancerServer ManagementBilling & PaymentsSupport & TicketsAffiliate ProgramReseller ProgramMarketplace & Appsn8n HostingManaged ServicesServer MigrationAPI & DevelopersSecurityTroubleshootingGlossaryInstall Guides
  1. Home
  2. /
  3. Support
  4. /
  5. Install Guides
  6. /
  7. How To Install Nginx Proxy Manager Ubuntu
GUIDEInstall Guides

How to Install Nginx Proxy Manager on Ubuntu 24.04 VPS: GUI Reverse Proxy

23 min read

How to Install Nginx Proxy Manager on Ubuntu 24.04 VPS — GUI Reverse Proxy with Auto SSL

Managing multiple web services on a single VPS almost always ends up looking the same: a mess of hand-edited Nginx config files, manual Certbot runs, and 2 AM debugging sessions when a certificate renewal silently fails. Nginx Proxy Manager (NPM) replaces all of that with a clean web UI. You point a domain at your server, click a few buttons, and NPM handles the reverse proxy config, the Let's Encrypt certificate, and the auto-renewal for you.

This guide walks you through installing Nginx Proxy Manager on an Ubuntu 24.04 VPS using Docker and Docker Compose, from the first SSH connection to a hardened production deployment serving multiple proxied apps with SSL.

Skip the setup? Deploy Nginx Proxy Manager in one click with our pre-configured app image. Launch a CloudCore Starter VPS now and have your reverse proxy online in under 60 seconds.

Table of Contents

  • What is Nginx Proxy Manager?
  • Why Use NPM Instead of Raw Nginx?
  • Prerequisites
  • Step 1: Update System Packages
  • Step 2: Install Docker and Docker Compose
  • Step 3: Create the Docker Compose File
  • Step 4: Start Nginx Proxy Manager
  • Step 5: Log In and Complete the First-Time Wizard
  • Step 6: Add Your First Proxy Host
  • Step 7: Request a Let's Encrypt Certificate
  • Step 8: Access Lists, Redirection Hosts, and Streams
  • Step 9: Backup, Upgrade, and Security Hardening
  • Troubleshooting
  • FAQ
  • Next Steps
  • What is Nginx Proxy Manager?

    Nginx Proxy Manager is an open-source web application that gives you a friendly GUI on top of Nginx. Under the hood, it runs an actual Nginx instance — the same battle-tested server that powers a large portion of the public internet — but you never have to touch a .conf file unless you want to. Every proxy host, redirect, SSL certificate, and access rule is configured through a browser dashboard.

    The core feature set covers almost everything most users need from a reverse proxy. You can create proxy hosts that forward requests from a public domain to any upstream service running on your LAN, on the host, or in another container. You can request and manage Let's Encrypt certificates with a single click, including wildcard certificates via DNS-01 challenges. You can define access lists that restrict who can reach a given host, either by IP allowlist or HTTP basic authentication. You can set up redirection hosts that 301 old domains to new ones, 404 hosts that serve a clean landing page for unmapped subdomains, and streams that pass raw TCP or UDP traffic through to backend services like game servers, databases, or SSH bastions.

    Typical use cases include fronting a Home Assistant server with SSL, exposing a self-hosted Vaultwarden or Nextcloud instance to the internet, publishing multiple apps (Plex, Jellyfin, Portainer, Grafana) on subdomains of a single VPS, or sitting in front of a Docker-based homelab to provide one unified entrypoint on ports 80 and 443. Any time you would reach for Traefik or raw Nginx but prefer a web UI, NPM is the right tool.

    Why Use NPM Instead of Raw Nginx?

    Raw Nginx is powerful and fast, but the ergonomics are rough if you are not a full-time sysadmin. NPM solves a handful of very specific pains:

    • No config file editing — Every proxy host, SSL cert, and access rule is a form in the UI. NPM writes the Nginx config for you and reloads the process atomically.
    • Automatic Let's Encrypt — Request a cert with two clicks. NPM handles the HTTP-01 or DNS-01 challenge, installs the cert, and renews it on a schedule. No certbot cron job to babysit.
    • Wildcard certificates out of the box — Pick your DNS provider from a dropdown (Cloudflare, Route 53, DigitalOcean, DuckDNS, and dozens more) and NPM completes the DNS-01 challenge for *.yourdomain.com automatically.
    • Access lists built in — IP allowlists and basic auth are checkboxes, not custom Nginx blocks. Great for admin dashboards you do not want exposed publicly.
    • Multi-user with audit log — Invite team members, each with their own login. Every change is logged, so you know who edited which host and when.
    • Streams support — Proxy non-HTTP traffic (TCP/UDP) for game servers, databases, or custom protocols — something most Nginx-on-a-GUI tools do not support.
    • Custom Nginx snippets — You are never locked in. Each proxy host has an "Advanced" tab where you can paste arbitrary Nginx directives if you need something NPM's UI does not expose.
    If you are administering three or more services behind a single IP, NPM will save you hours every month compared to hand-rolled Nginx.

    Nginx Proxy Manager vs. Alternatives

    ToolUIAuto SSLStreams (TCP/UDP)Docker-nativeBest For
    Nginx Proxy ManagerFull web UIYes (HTTP-01 + DNS-01)YesYesSelf-hosters, homelabs, small SaaS
    TraefikDashboard (read-only)YesYes (v3+)YesDynamic Docker/Kubernetes environments
    CaddyNone (config file)Yes (automatic)LimitedPartialMinimalists, single-binary deployments
    Raw Nginx + CertbotNoneManual (cron)YesNoPower users, custom setups
    HAProxyEnterprise UI (paid)ManualYesPartialHigh-throughput load balancing
    For most VPS users, NPM is the sweet spot between "set it and forget it" and "I can still drop into Nginx directives when I need to."

    Prerequisites

    Before you begin, make sure you have:

    • A VPS running Ubuntu 24.04 LTS with root or sudo access
    • SSH access to your server
    • A domain name pointing an A record at your VPS IP (required for Let's Encrypt)
    • Ports 80, 443, and 81 open on your firewall and cloud provider security group
    • At least 1 GB of RAM (NPM itself is lightweight, but the Let's Encrypt renewal job spikes briefly)
    • 2-5 GB of free disk space for the NPM container, database, and certificate storage
    Recommended Plan: CloudCore Starter
    >
    For a reverse proxy fronting a handful of self-hosted apps, the CloudCore Starter plan is more than enough:
    >
    - 4 vCPU cores
    - 8 GB RAM
    - 50 GB NVMe SSD
    - 32 TB bandwidth
    - EUR 7.99/month
    >
    This leaves plenty of headroom to run NPM alongside the backend apps it proxies (Vaultwarden, Nextcloud, Grafana, etc.) all on the same box.

    Connect to your server via SSH to get started:

    bash
    ssh root@your-server-ip

    Step 1: Update System Packages

    Start by updating your package index and upgrading installed packages so you are on the latest kernel and security patches.

    bash
    sudo apt update && sudo apt upgrade -y

    Expected output (abbreviated):

    text
    Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
    Reading package lists... Done
    Building dependency tree... Done
    Calculating upgrade... Done
    0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

    If the kernel was updated, reboot before continuing:

    bash
    sudo reboot

    Step 2: Install Docker and Docker Compose

    Nginx Proxy Manager ships as a Docker image, so you need a working Docker and Docker Compose installation. If you have already set these up, skip to Step 3.

    Install Docker Engine using the official convenience script:

    bash
    curl -fsSL https://get.docker.com | sh

    Docker Compose v2 is included as a plugin with modern Docker installations, so no separate install is required. Verify both are working:

    bash
    docker --version
    docker compose version

    Expected output:

    text
    Docker version 27.3.1, build ce12230
    Docker Compose version v2.29.7

    If you prefer a manual install or need more detail (rootless mode, alternative distros, post-install hardening), see our full walkthroughs:

    • How to Install Docker on Ubuntu 24.04
    • How to Install Docker Compose on Ubuntu
    Add your current user to the docker group so you can run commands without sudo:

    bash
    sudo usermod -aG docker $USER
    newgrp docker

    Confirm Docker is running:

    bash
    sudo systemctl status docker

    Step 3: Create the Docker Compose File

    Create a dedicated directory for your NPM deployment. Keeping it in /opt is a common convention and keeps your home directory clean.

    bash
    sudo mkdir -p /opt/npm
    cd /opt/npm

    Create the docker-compose.yml file:

    bash
    sudo nano docker-compose.yml

    Paste the following configuration. This uses the official jc21/nginx-proxy-manager image and the optional MariaDB backend (recommended for production over the built-in SQLite):

    yaml
    services:
      app:
        image: 'jc21/nginx-proxy-manager:latest'
        container_name: npm-app
        restart: unless-stopped
        ports:
          - '80:80'      # HTTP traffic
          - '443:443'    # HTTPS traffic
          - '81:81'      # Admin UI
        environment:
          DB_MYSQL_HOST: "db"
          DB_MYSQL_PORT: 3306
          DB_MYSQL_USER: "npm"
          DB_MYSQL_PASSWORD: "CHANGE_ME_STRONG_PASSWORD"
          DB_MYSQL_NAME: "npm"
          DISABLE_IPV6: 'true'
        volumes:
          - ./data:/data
          - ./letsencrypt:/etc/letsencrypt
        depends_on:
          - db

    db: image: 'jc21/mariadb-aria:latest' container_name: npm-db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: 'CHANGE_ME_ROOT_PASSWORD' MYSQL_DATABASE: 'npm' MYSQL_USER: 'npm' MYSQL_PASSWORD: 'CHANGE_ME_STRONG_PASSWORD' MARIADB_AUTO_UPGRADE: '1' volumes: - ./mysql:/var/lib/mysql

    Save and exit (Ctrl+O, Enter, Ctrl+X).

    About the Three Ports

    • Port 80 — Public HTTP. NPM listens here to serve unencrypted traffic, handle redirects to HTTPS, and complete HTTP-01 Let's Encrypt challenges.
    • Port 443 — Public HTTPS. All your proxied apps are served through this port with SSL.
    • Port 81 — Admin UI. This is the web dashboard where you configure everything. Never expose this port publicly without protection — lock it down with a firewall rule or put it behind an allowlist.

    SQLite vs. MariaDB

    NPM can run with a built-in SQLite database for simple deployments — just remove the db service and the DB_MYSQL_* environment variables, and NPM defaults to SQLite stored in ./data/database.sqlite. SQLite works fine for small homelabs with a handful of hosts. For anything production-facing, or if you plan to manage more than ~20 proxy hosts, use the MariaDB setup above. It performs better under concurrent writes and is easier to back up cleanly.

    Replace both CHANGE_ME_* passwords before starting the stack. Use a strong random generator:

    bash
    openssl rand -base64 24

    Step 4: Start Nginx Proxy Manager

    From /opt/npm, bring the stack up:

    bash
    sudo docker compose up -d

    Expected output:

    text
    [+] Running 3/3
     ✔ Network npm_default  Created
     ✔ Container npm-db     Started
     ✔ Container npm-app    Started

    The first startup takes 30-60 seconds as NPM initializes the database schema. Watch the logs to confirm everything is healthy:

    bash
    sudo docker compose logs -f app

    You should see lines like:

    text
    [4/16/2026] [10:00:00 AM] [Global    ] › ✖ migrate DB
    [4/16/2026] [10:00:05 AM] [Migrate   ] › ℹ Current database version: 20240427161436
    [4/16/2026] [10:00:05 AM] [Setup     ] › ℹ Logrotate Timer initialized
    [4/16/2026] [10:00:05 AM] [IP Ranges ] › ℹ Fetching IP Ranges from online services...
    [4/16/2026] [10:00:07 AM] [Global    ] › ✔ Backend PID 247 listening on port 3000 ...

    Press Ctrl+C to stop tailing once you see the "listening on port 3000" line.

    Open the admin UI in your browser:

    text
    http://your-server-ip:81

    Step 5: Log In and Complete the First-Time Wizard

    The default credentials for the first login are:

    • Email: [email protected]
    • Password: changeme
    NPM will immediately force you through a first-time setup wizard where you must change both values. Use a real email address (Let's Encrypt notices and password reset links go here) and a strong password.

    After saving, you land on the NPM dashboard. The main navigation has four sections:

    • Hosts — Proxy Hosts, Redirection Hosts, Streams, 404 Hosts
    • SSL Certificates — Let's Encrypt and custom certs
    • Access Lists — IP and basic-auth rules reusable across hosts
    • Audit Log — Every change made in the UI, with timestamp and user

    Step 6: Add Your First Proxy Host

    This is where the magic happens. Say you have a Grafana instance running on the same VPS at 127.0.0.1:3000 and you want it accessible at https://grafana.yourdomain.com.

    First, make sure the DNS A record for grafana.yourdomain.com points to your VPS public IP. DNS propagation can take anywhere from seconds to a couple of hours depending on your provider and TTL.

    In the NPM UI:

  • Go to Hosts → Proxy Hosts → Add Proxy Host
  • Details tab:
  • - Domain Names: grafana.yourdomain.com (hit Enter to add) - Scheme: http - Forward Hostname / IP: 127.0.0.1 (or the container name if NPM is on the same Docker network as Grafana) - Forward Port: 3000 - Enable Cache Assets, Block Common Exploits, and Websockets Support (the last one is important — without it, real-time features in Grafana, Home Assistant, Portainer, etc. will not work)
  • Click Save
  • Forwarding to Other Docker Containers

    If your backend service runs in a Docker container on the same host, you have two good options:

    • Option A: Put them on the same Docker network. Add networks: - npm_default to the backend's compose file and use the container name as the forward hostname (e.g., grafana instead of 127.0.0.1). This is cleaner and more resilient to IP changes.
    • Option B: Bind the backend to 127.0.0.1:PORT on the host and use host.docker.internal or the Docker bridge IP (typically 172.17.0.1) as the forward hostname. NPM's container needs extra_hosts: - "host.docker.internal:host-gateway" added to the compose file for this to work reliably.

    Step 7: Request a Let's Encrypt Certificate

    With the proxy host saved, edit it again and jump to the SSL tab.

    • SSL Certificate: Choose Request a new SSL Certificate
    • Enable Force SSL, HTTP/2 Support, and HSTS Enabled
    • Email Address for Let's Encrypt: your real email (for expiry notifications)
    • Agree to the Let's Encrypt Terms of Service
    • Click Save
    NPM completes the HTTP-01 challenge automatically. Within 10-30 seconds, you get a valid Let's Encrypt certificate, auto-renewing every 60 days.

    Visit https://grafana.yourdomain.com — you should see the Grafana login page served over HTTPS with a valid cert.

    Wildcard Certificates via DNS-01

    For a wildcard certificate like *.yourdomain.com, use the DNS-01 challenge. In the same SSL tab:

  • Enable Use a DNS Challenge
  • Pick your DNS Provider from the dropdown (Cloudflare, Route 53, DigitalOcean, DuckDNS, Namecheap, Hetzner, and dozens more)
  • Paste your API credentials in the Credentials File Content field following the template NPM shows
  • For Cloudflare, the credentials look like:

    ini
    dns_cloudflare_api_token=your_cloudflare_api_token_here

    Create the token in the Cloudflare dashboard with Zone:DNS:Edit permissions scoped to the domain you want to issue certs for.

    Once saved, NPM issues the wildcard cert and you can attach it to any proxy host for that domain without needing a separate HTTP-01 challenge per subdomain.

    Common SSL Pitfalls

    • Rate limits — Let's Encrypt allows 5 failed validations per hostname per hour and 50 certs per registered domain per week. If you are testing, use the staging environment first (not currently exposed in the NPM UI — swap to it via a custom certificate workflow if you need it).
    • DNS not propagated — If the A record was changed within the last hour, Let's Encrypt's validation servers may still see the old value. Wait and retry.
    • Port 80 blocked — HTTP-01 requires port 80 to be publicly reachable. Check your cloud provider security group and UFW rules.

    Step 8: Access Lists, Redirection Hosts, and Streams

    With the basics working, NPM's more advanced features cover the remaining 20% of reverse proxy use cases.

    Access Lists (IP Allowlist + Basic Auth)

    Perfect for admin dashboards (Portainer, Grafana admin, Kibana) you want gated behind an IP allowlist or a password prompt.

  • Go to Access Lists → Add Access List
  • Give it a name (e.g., "Home Office Only")
  • Authorization tab: add basic auth users if you want a password prompt
  • Access tab: add IP addresses or CIDR ranges to allow (203.0.113.50 or 192.168.1.0/24). Set "Satisfy Any" to require any one condition, or leave it off to require all.
  • Save, then edit any proxy host and assign the access list under Details → Access List
  • Redirection Hosts

    Permanently redirect an old domain to a new one with a 301. Useful for domain migrations, consolidating aliases, or forcing www → apex (or vice versa).

  • Hosts → Redirection Hosts → Add Redirection Host
  • Domain Names: old-domain.com
  • Forward Domain: new-domain.com
  • HTTP Code: 301 Moved Permanently
  • Enable Preserve Path if you want /blog/post-1 to redirect to the same path on the new domain
  • Streams (TCP/UDP Pass-Through)

    For non-HTTP protocols — game servers (Minecraft, Valheim), databases exposed over VPN, SSH bastion hosts, WireGuard on a non-standard port, etc.

  • Hosts → Streams → Add Stream
  • Incoming Port: the public port (remember to open it in your firewall and on the Docker Compose file)
  • Forward Host / Port: the backend target
  • Choose TCP, UDP, or both
  • Streams require exposing additional ports from the NPM container. Edit /opt/npm/docker-compose.yml and add the port to the app service:

    yaml
    ports:
          - '80:80'
          - '443:443'
          - '81:81'
          - '25565:25565'   # Minecraft stream

    Then sudo docker compose up -d to recreate the container with the new port mapping.

    404 Host

    Catch-all for any hostname that hits your server but is not configured as a proxy host. Good for presenting a clean "not found" page instead of a default Nginx welcome screen to bot traffic.

    Custom Nginx Config Per Host

    Every proxy host has an Advanced tab where you can paste arbitrary Nginx directives that get merged into the generated config. Use this for things like:

    • client_max_body_size 100m; for large file uploads (Nextcloud, photo upload apps)
    • proxy_read_timeout 600s; for long-polling or slow backends
    • Custom add_header rules (CSP, Permissions-Policy)
    • Rate limiting: limit_req zone=mylimit burst=20 nodelay;
    NPM validates the config on save — if you paste something invalid, it refuses to apply the change and keeps the previous working version live.

    Step 9: Backup, Upgrade, and Security Hardening

    Backing Up NPM

    All NPM state lives in three directories under /opt/npm:

    • ./data — application state, SQLite DB (if used), custom Nginx snippets
    • ./letsencrypt — issued certificates and account keys
    • ./mysql — MariaDB data (if you used the MariaDB setup)
    A full backup is a tarball of those three plus the compose file:

    bash
    sudo tar -czvf /root/npm-backup-$(date +%Y%m%d).tar.gz \
      -C /opt/npm docker-compose.yml data letsencrypt mysql

    Schedule it daily via cron and ship the tarball to off-box storage (S3, Backblaze B2, rsync to another VPS). To restore, stop the stack, extract the tarball into a fresh /opt/npm, and bring it back up — everything resumes exactly where it was, cert renewals included.

    Upgrading NPM

    NPM publishes frequent releases. Upgrade by pulling the latest image and recreating the containers:

    bash
    cd /opt/npm
    sudo docker compose pull
    sudo docker compose up -d

    Docker Compose keeps your named volumes, so no data is lost. Always take a backup first.

    Security Hardening

    Nginx Proxy Manager is a powerful tool with complete control over your public web surface. Treat the admin UI like the root shell it effectively is.

    • Never expose port 81 publicly — If you must reach the admin UI remotely, either:
    - Restrict port 81 with UFW to specific IPs: sudo ufw allow from 203.0.113.50 to any port 81 && sudo ufw deny 81 - Proxy the admin UI through NPM itself on a random subdomain (e.g., admin-abcd1234.yourdomain.com) with an access list attached, and then firewall off the direct port 81 entirely - Access it over a VPN (WireGuard, Tailscale) or SSH tunnel
    • Use a strong admin password — 20+ characters, generated, not reused. Store it in a password manager.
    • Enable 2FA on your DNS provider and email — NPM's recovery flow ultimately depends on email access and DNS control.
    • Put NPM behind Cloudflare — Optional but valuable. Cloudflare shields your origin IP, provides DDoS mitigation, and lets you enforce access rules at the edge. Enable "Full (strict)" SSL mode so Cloudflare still validates NPM's Let's Encrypt cert.
    • Keep Docker and the host patched — sudo apt update && sudo apt upgrade -y weekly, and docker compose pull to stay current on NPM itself.
    • Configure UFW — Allow only what you need:
    bash
    sudo ufw allow 22/tcp
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw deny 81
    sudo ufw enable

    For deeper Nginx-specific tuning and hardening tips, see our companion article: How to Install and Configure Nginx on Ubuntu.

    Troubleshooting

    ProblemCauseSolution
    Let's Encrypt request fails with "too many certificates already issued"Hit the 50 certs/week/domain rate limitWait up to 7 days. Use a wildcard cert (DNS-01) to cover all subdomains with a single issuance.
    Let's Encrypt fails with "Invalid response from http://..."Port 80 is blocked, DNS points elsewhere, or another service is binding port 80Verify curl http://yourdomain.com/.well-known/acme-challenge/test from outside the server reaches NPM. Check firewall, cloud security group, and DNS A record.
    502 Bad Gateway on a proxy hostUpstream backend is unreachable, offline, or bound to the wrong interfacedocker ps to confirm the backend is running. From inside NPM container: docker exec npm-app curl -I http://backend:port. Check the forward hostname — localhost/127.0.0.1 from inside the container is the container itself, not the host.
    Websocket connections fail (real-time features break)"Websockets Support" toggle disabled on the proxy hostEdit the proxy host → Details tab → enable Websockets Support → Save.
    Admin UI at port 81 not loadingUFW blocking, wrong port mapping, or container crashedsudo docker compose ps to confirm npm-app is up. sudo ufw status. sudo docker compose logs app.
    Certificate renewed but browser shows old certNginx did not reload after renewalRare — normally NPM reloads automatically. Force it: sudo docker exec npm-app nginx -s reload
    Forgot admin passwordLocked out of UIReset directly in the DB. For MariaDB: docker exec -it npm-db mysql -u root -p then USE npm; UPDATE user SET is_disabled = 0 WHERE email='[email protected]'; and reset via the password reset flow.
    "Internal Error" on saving a hostInvalid custom Nginx config in Advanced tabRemove the Advanced config snippet, save, then re-add one directive at a time to isolate the bad line.

    Viewing Logs

    Stream NPM's logs in real time:

    bash
    cd /opt/npm
    sudo docker compose logs -f app

    Nginx access and error logs live inside the container:

    bash
    sudo docker exec npm-app tail -f /data/logs/default-host_access.log
    sudo docker exec npm-app tail -f /data/logs/fallback_error.log

    Per-host logs are in /data/logs/proxy-host-<id>_access.log and _error.log.

    FAQ

    Is Nginx Proxy Manager free?

    Yes. NPM is fully open source under the MIT license. There is no paid tier, no feature gate, and no phone-home telemetry. The only costs are your VPS and (optionally) a domain name.

    Can I use Nginx Proxy Manager without Docker?

    Not officially. NPM is designed and distributed as a Docker image, and the project does not support bare-metal installs. If you strongly prefer native Nginx, use raw Nginx with Certbot instead — see our Nginx install guide.

    Does NPM work with Cloudflare's orange cloud (proxied DNS)?

    Yes, with one caveat. When Cloudflare proxies your domain, the HTTP-01 Let's Encrypt challenge can fail because Cloudflare terminates the challenge connection. Use the DNS-01 challenge with Cloudflare's API token instead — NPM has built-in support and it works flawlessly with proxied records.

    How many proxy hosts can one NPM instance handle?

    In practice, several hundred. Nginx itself scales to thousands of virtual hosts with minimal overhead. The real limits are your VPS RAM (each proxied connection uses a small buffer) and the NPM admin UI responsiveness, which starts to feel sluggish past ~500 hosts. For homelabs and small-to-mid SaaS, you will never hit those limits.

    Can I run multiple NPM instances for high availability?

    Yes, but it takes some care. Run two NPM containers on separate VPS instances, point them at the same external MariaDB (with replication), and use a simple DNS round-robin or a TCP load balancer (HAProxy, cloud provider LB) in front. Certificate storage needs to be shared — use a network filesystem (NFS, GlusterFS) or sync ./letsencrypt between nodes. For most users, this is overkill; a single well-backed-up NPM is more than enough.

    What happens when my VPS reboots?

    The NPM containers are set to restart: unless-stopped in the compose file, so they come back up automatically on boot. All certificates, hosts, and settings persist in the mounted volumes. You should be online within 10-20 seconds of the server finishing boot.

    Next Steps

    With Nginx Proxy Manager handling your reverse proxy, SSL, and access control, you have a solid foundation for self-hosting. Recommended next steps:

    • Deploy your first self-hosted app behind NPM — Vaultwarden, Nextcloud, or Home Assistant all pair beautifully with NPM. Spin them up in Docker, add a proxy host, request a cert, done.
    • Set up monitoring with Uptime Kuma — Uptime Kuma runs in a single Docker container, fronted by NPM, and monitors every endpoint you publish. Get Telegram/Discord/email alerts if any host goes down.
    • Add Authelia or Authentik for SSO — NPM's basic auth is fine for personal use, but if you want unified single sign-on across all your self-hosted apps, drop in Authelia or Authentik. Both integrate with NPM via forward-auth.
    • Automate backups with Restic or BorgBackup — Schedule nightly backups of /opt/npm to off-site storage and test restores monthly.
    • Read the official docs — The Nginx Proxy Manager documentation covers advanced topics like custom DNS providers, offline Docker installs, and multi-stage proxy chains.

    Skip the Manual Install — Get NPM Pre-Installed
    >
    Our CloudCore Starter VPS plans come with Nginx Proxy Manager one-click deployable: Docker, NPM, MariaDB, and UFW rules configured, a generated admin password in your welcome email, and ports 80/443/81 already locked down correctly.
    >
    - NPM + MariaDB running in Docker Compose
    - Admin UI protected by firewall rule (your IP only)
    - UFW and fail2ban pre-configured
    - Automated weekly backups of /opt/npm included
    - Optional wildcard cert setup with your DNS provider
    >
    Deploy Your CloudCore Starter VPS Now — Plans start at EUR 7.99/month.

    Was this article helpful?

    ← Back to Install GuidesBrowse all categories →

    Still have questions?

    Contact Support →Submit a Ticket