Nginx Proxy Manager: Custom Directives, Streams, and SSL Hardening (Part 2)
Advanced reverse proxy configurations with Nginx Proxy Manager. Configure custom directives, port streams, and secure SSL challenges.
1. Advanced Custom Directives in Location Blocks
Nginx Proxy Manager (NPM) allows you to inject custom directives inside location blocks or globally under the Advanced tab of a proxy host. This capability is crucial for tuning performance, overriding upstream behaviors, and applying granular access controls.
Client Request Buffering and Body Limits
Large file uploads (such as Nextcloud or media servers) often fail with 413 Request Entity Too Large or exhibit slow performance due to disk buffering. Use these directives to tune client body size and buffer size:
# Allow uploads up to 10GB
client_max_body_size 10G;
# Increase client body buffer size to handle in-memory uploads up to 16MB before writing to temp files
client_body_buffer_size 16M;
# Disable proxy buffering to speed up file transfers (best for streaming/large uploads)
proxy_buffering off;
proxy_request_buffering off;
Rate Limiting and Traffic Shaping
To protect backend services from denial-of-service (DoS) attacks or brute-force attempts, you can define rate-limiting zones in Nginx. Note that the zone definition (limit_req_zone) must go in the global HTTP context (using NPM's custom configuration file or global settings), but the enforcement happens within the location block:
# Add the following in a custom configuration or within the proxy host's advanced tab
# limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
# Inside the NPM location block / advanced settings:
limit_req zone=api_limit burst=10 nodelay;
limit_req_status 429;
IP Access Control (Whitelisting and Blacklisting)
Restrict access to sensitive internal paths (like /admin or /dashboard) to specific IP addresses or subnets:
# Deny block
allow 192.168.1.0/24; # Allow local network
allow 10.0.0.0/8; # Allow internal VPC
allow 203.0.113.50; # Allow a specific external admin IP
deny all; # Deny everyone else
WebSocket and Connection Upgrades
If NPM's GUI "Websockets Support" toggle is insufficient or needs manual override:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
2. TCP and UDP Stream Forwarding
Nginx Proxy Manager isn't limited to HTTP/HTTPS. It can route raw TCP and UDP streams. This is essential for exposing non-HTTP services like databases, game servers (e.g., Minecraft, Rust), SSH, DNS, or MQTT brokers.
Database Stream Forwarding (MySQL/PostgreSQL)
Exposing database instances securely via NPM allows centralizing SSL termination and port routing. Below is a raw TCP stream configuration:
# TCP Stream for PostgreSQL (Port 5432)
stream {
upstream pgsql_backend {
server 10.0.0.15:5432;
}
server {
listen 5432;
proxy_pass pgsql_backend;
proxy_connect_timeout 5s;
proxy_timeout 30s;
}
}
Note: Stream configurations inside NPM are managed through the Streams tab in the admin UI, which automatically generates these blocks outside the standard HTTP context.
Game Server Stream Forwarding (Minecraft & UDP Streams)
For games like Minecraft (TCP 25565) or UDP-based services (like WireGuard VPN on UDP 51820), specify the transport protocol explicitly:
# Minecraft TCP stream
server {
listen 25565;
proxy_pass mc_backend:25565;
proxy_buffer_size 16k;
}
# WireGuard UDP stream
server {
listen 51820 udp;
proxy_pass wg_backend:51820;
proxy_responses 0; # UDP traffic does not require response tracking in some setups
}
3. Wildcard SSL Certificates via DNS Challenges
Wildcard SSL certificates (*.yourdomain.com) cover all subdomains without exposing individual subdomain names to public Certificate Transparency logs. Let's Encrypt requires a DNS-01 challenge to prove ownership of the base domain for wildcard requests.
Configuring the Cloudflare DNS Challenge API
Cloudflare is the most common DNS provider used with NPM for automated wildcard SSL generation.
- Generate a Cloudflare API Token:
- Log into Cloudflare, navigate to My Profile > API Tokens.
- Create a token using the Edit zone DNS template.
- Limit the token's scope to the specific zone (domain) you wish to secure.
- Configure NPM SSL Panel:
- In NPM, go to SSL Certificates > Add SSL Certificate > Let's Encrypt.
- Enter your domains:
yourdomain.comand*.yourdomain.com. - Toggle Use a DNS Challenge to ON.
- Select Cloudflare from the DNS Provider list.
- Replace the default configuration template with your generated token:
# Cloudflare API token used by Let's Encrypt (certbot)
dns_cloudflare_api_token = 8a7b6c5d4e3f2g1h0i_your_actual_token_here
- DNS Propagation Time:
- Set Propagation Delay to
120seconds. Cloudflare is generally fast, but DNS replication globally requires buffer time to prevent validation timeouts.
Handling Multi-Provider Challenges
If your domain uses registrar-specific DNS (e.g., Namecheap, Route53, DuckDNS), match the specific credentials template in NPM: - Route53 (AWS) requires IAM policy access keys: ini aws_access_key_id = AKIAIOSFODNN7EXAMPLE aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - DuckDNS requires a simple API token: ini dns_duckdns_token = 12345678-abcd-1234-abcd-1234567890ab
4. Hardening Security Headers
Implementing security headers protects your clients against Cross-Site Scripting (XSS), Clickjacking, MIME-type sniffing, and data leakage. Add these headers inside the Advanced tab of your HTTP proxy hosts in NPM.
Essential Security Header Suite
Inject the following configurations into your host's Nginx configuration block to achieve an A+ security rating:
# Prevent clickjacking by forbidding embedding of this site in frames
add_header X-Frame-Options "SAMEORIGIN" always;
# Prevent MIME-type sniffing
add_header X-Content-Type-Options "nosniff" always;
# Control how much referrer information is shared with destination sites
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Strict-Transport-Security (HSTS) - Enforce HTTPS for 1 year including subdomains
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Disable browser features and APIs (e.g., camera, microphone, geolocation)
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
Implementing a Strict Content Security Policy (CSP)
A CSP limits the sources from which resources (such as scripts, images, and stylesheets) can be loaded. Adapt this strict starter template to prevent malicious scripts from running:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';" always;
Overriding/Removing Upstream Server Headers
To obfuscate backend technologies and decrease target footprint, prevent Nginx and backend services from leaking their version numbers:
# Hide Nginx version details globally or locally
server_tokens off;
# Remove headers added by upstream applications
proxy_hide_header X-Powered-By;
proxy_hide_header Server;