NPM Setup

Last Edit: 2025.07.19

Overview

Setup Nginx Proxy Manager on Podman or Docker.

Assumptions

Configure System

Configure the host system based for the NPM deployment.

Privileged Ports

NPM requires port 443 and optionally port 80 to handle HTTP/HTTPS traffic. These are privileged ports that need to be added to the sysctl configuration because they are below 1024. Create a new file in sysctl.d, defining the lowest port that will be used.

sudo vim /etc/sysctl.d/90-unprivileged-port-start.conf

Define lowest required port. Use 80 if using 80/443, 443 if only using 443. Multiple definitions will override each other. The default value for this definition is 1024.

net.ipv4.ip_unprivileged_port_start=443
#net.ipv4.ip_unprivileged_port_start=80

Apply sysctl changes.

sudo sysctl --system

Firewall

Open the NPM admin dashboard port (8181), and the HTTPS port (443). Optionally, open the HTTP port (80) if enabling it.

sudo firewall-cmd --permanent --zone=public --add-port=8181/tcp
sudo firewall-cmd --permanent --zone=public --add-port=443/tcp
sudo firewall-cmd --permanent --zone=public --add-port=80/tcp

Reload the firwall to apply changes.

sudo firewall-cmd --reload

Compose File

Create a compose file to deploy Nginx Proxy Manager. When using Portainer, deploy it as a Stack. Uncomment and define container_name for explicit container names. Uncomment 80:80 to enable HTTP to HTTPS forwards. Consider changing the restart policy to on-failure after verifying everything works.

services:
  npm:
    image: jc21/nginx-proxy-manager:latest
    #container_name: npm
    restart: unless-stopped
    #restart: on-failure:5
    security_opt:
      - no-new-privileges:true
    cap_add:
      - NET_BIND_SERVICE
    ports:
      #- 80:80
      - 443:443
      - 8181:81
    environment:
      DB_SQLITE_FILE: /data/database.sqlite
      DISABLE_IPV6: false
    volumes:
      - npm_data:/data
      - npm_certs:/etc/letsencrypt
    networks:
      - npm_local
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:81/']
      interval: 60s
      timeout: 10s
      retries: 5
      start_period: 30s

volumes:
  npm_data:
  npm_certs:

networks:
  npm_local:

NPM Login

When Nginx Proxy Manager enters the Running state, navigate to the dashboard in a browser window. Replace 172.16.13.13 with the system IP address. Initial connection and configuration must be made over HTTP.

Default Credentials:

http://172.16.13.13:8181/

Nginx Proxy Manager dashboard.

After logging in with the default credentials, a prompt will present for modifying the admin user and the admin password.

Define a new email address and generate a secure password. This password should be changed again after HTTPS has been setup, since all traffic to NPM is currently unencrypted.

Change Admin EmailChange Admin Password
Nginx Proxy Manager edit admin user.Nginx Proxy Manager edit admin password.

Cloudflare API Token

Create an API token to interact with a Cloudflare Zone.

Navigate to the My Profile page and select the API Tokens tab.

Select Create Token. Configure the token with permission to edit Zone DNS. Only allow access to the zone resource required.

SettingValueDescription
Token Nameexample-api-tokenChoose a name to identify the token.
PermissionsZone - DNS - EditGrant edit permissions for zone DNS.
Zone ResourcesInclude - Specific - example.comOnly include the zone that will utilize the token.

Cloudflare API token creation tool.

Continue to summary and review the configuration, select Create Token.

When presented, copy the generated Cloudflare API token.

Cloudflare API token.

NPM Certificate Configuration

Generate a new certificate within the Nginx Proxy Manager dashboard. This example will complete ACME verification via DNS using a Cloudflare API key. Adjust the configuration for the domain DNS provider.

From the Nginx Proxy Manager dashboard, select SSL Certificates.

Select Add SSL Certificate and choose Let's Encrypt.

Create a wildcard certificate request for the domain of choice.

SettingValueDescription
Domain Names*.system.example.comPointing this domain at the server is not required with the DNS challenge.
Email Address[email protected]Public email address for the request.
Use a DNS ChallengetrueUse DNS to complete ACME challenge.
DNS ProviderCloudflareThe DNS provider, Cloudflare in this example.
Credentials File Contentdns_cloudflare_api_token=GeneratedCloudflareAPITokenCloudflare API token generated in previous step.
Propagation SecondsLeave blank for default.

Add Let’s Encrypt certificate.

Save the certificate and wait for the request process to complete. The new certificate will be listed on the Nginx Proxy Manager SSL Certificate page.

SSL certificates list.

NPM Access Lists

Create an access list to restrict access to Nginx hosts to the local network.

From the Nginx Proxy Manager dashboard, select Access Lists.

Select Add Access List and configure a name for the list, local in this example.

Switch to the Access tab and add a new allow rule. Specifiy the network and subnet based on the local network, 172.16.13.0/24. If connections to services fail, test the service without this access rule to verify it is an issue with the container and not the access list blocking traffic.

Nginx new access list.

NPM Proxy Host

Add a proxy host for the Nginx Proxy Manager dashboard.

From the Nginx Proxy Manager dashboard, select Proxy Hosts under Hosts.

Select Add Proxy Host from the Proxy Hosts dashboard.

Proxy Host Details

Configure the new proxy host details.

SettingValueDescription
Domain Namesnpm.system.example.comHostname for the Nginx Proxy Manager dashboard.
Forward Hostname / IP127.0.0.1Use the loopback address.
Forward Port81Use the internal Docker port, not the mapped port, because the loopback address is the hostname.
Cache Assetsfalse
Block Common Exploitstrue
Websockets Supportfalse
Access ListlocalUse the configured access list to limit devices that can connect.

Nginx proxy host details.

Proxy Host SSL

Switch to the SSL tab for the new proxy host and configure it to use the generated certificate.

SettingValueDescription
SSL Certificate*.system.example.comUse the generated certificate.
Force SSLtrue
HTTP/2 Supporttrue
HSTS Enabledtrue
HSTS Subdomainstrue

Nginx Proxy Manager proxy host SSL.

Proxy Host Connect

View the added host in the proxy hosts list.

Nginx proxy host page.

If a local DNS server is setup, add an entry for the proxy host domain(s).

If there is no local DNS server yet, add a custom host entry to /etc/hosts.

sudo nano /etc/hosts

Add the required domain(s) and point them to the host system IP address.

172.16.13.13 system.example.com
172.16.13.13 npm.system.example.com

Navigate to the Nginx Proxy Manager dashboard with the configured domain, no port required if Nginx Proxy Manager was assigned port 80/443.

https://npm.system.example.com/

NPM Finalisation

Now the connection to NPM is encrypted. Consider generating a new Cloudflare API Token and changing the admin password, since the information was entered over cleartext previously. The firewall port for the admin interface can also be closed to force all connections through the HTTPS connection. If there is ever an issue accessing the dashboard, open the port back up and connect on the dashboard port manually again.

sudo firewall-cmd --permanent --zone=public --remove-port=8181/tcp

Reload the firwall to apply changes.

sudo firewall-cmd --reload

Errors

User / Service Failure

If the compose file is too restrictive, an error may present about failing to configure the NPM user, or the service being unable to start. A possible cause for this is having cap_drop - ALL defined or a similar configuration, restricting the containers ability to function properly.

❯ Configuring npm user ...
useradd warning: npm's uid 0 outside of the UID_MIN 1000 and UID_MAX 60000 range.
useradd: failure while writing changes to /etc/shadow
s6-rc: warning: unable to start service prepare: command exited 1
/run/s6/basedir/scripts/rc.init: warning: s6-rc failed to properly bring all the services up! Check your logs (in /run/uncaught-logs/current if you have in-container logging) for more information.

References

1 2 3


  1. Nginx Proxy Manager. Nginx Proxy Manager Documentation. 2024. ↩︎

  2. Nginx Proxy Manager. “Nginx Proxy Manager GitHub.” 2024. ↩︎

  3. Red Hat. “Rootless podman is unable to use host ports less than 1024.” 2024. ↩︎