NPM Setup
Overview
Setup Nginx Proxy Manager on Podman or Docker.
Assumptions
- Podman Setup completed.
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:
- Username:
[email protected]
- Password:
changeme
http://172.16.13.13:8181/
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 Email | Change 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.
Setting | Value | Description |
---|---|---|
Token Name | example-api-token | Choose a name to identify the token. |
Permissions | Zone - DNS - Edit | Grant edit permissions for zone DNS. |
Zone Resources | Include - Specific - example.com | Only include the zone that will utilize the token. |
Continue to summary
and review the configuration, select Create Token
.
When presented, copy the generated 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.
Setting | Value | Description |
---|---|---|
Domain Names | *.system.example.com | Pointing 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 Challenge | true | Use DNS to complete ACME challenge. |
DNS Provider | Cloudflare | The DNS provider, Cloudflare in this example. |
Credentials File Content | dns_cloudflare_api_token=GeneratedCloudflareAPIToken | Cloudflare API token generated in previous step. |
Propagation Seconds |
| Leave blank for default. |
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.
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.
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.
Setting | Value | Description |
---|---|---|
Domain Names | npm.system.example.com | Hostname for the Nginx Proxy Manager dashboard. |
Forward Hostname / IP | 127.0.0.1 | Use the loopback address. |
Forward Port | 81 | Use the internal Docker port, not the mapped port, because the loopback address is the hostname. |
Cache Assets | false | |
Block Common Exploits | true | |
Websockets Support | false | |
Access List | local | Use the configured access list to limit devices that can connect. |
Proxy Host SSL
Switch to the SSL
tab for the new proxy host and configure it to use the generated certificate.
Setting | Value | Description |
---|---|---|
SSL Certificate | *.system.example.com | Use the generated certificate. |
Force SSL | true | |
HTTP/2 Support | true | |
HSTS Enabled | true | |
HSTS Subdomains | true |
Proxy Host Connect
View the added host in the proxy hosts list.
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
Nginx Proxy Manager. Nginx Proxy Manager Documentation. 2024. ↩︎
Nginx Proxy Manager. “Nginx Proxy Manager GitHub.” 2024. ↩︎
Red Hat. “Rootless podman is unable to use host ports less than 1024.” 2024. ↩︎