Understanding the Problem
When you route traffic through NGINX Proxy Manager (NPM), the reverse proxy acts as an intermediary between the visitor and your Synology Docker containers or services. By default, NPM forwards requests using its own internal network interface. Consequently, any application listening on that port sees the source IP as the internal container gateway or the NPM host itself, rather than the true public IP of the user.
This behavior breaks several important functionalities. Many web applications use the client IP for rate limiting, access control lists, or analytics. If every request appears to come from a single internal IP, these systems fail to function correctly. Additionally, security logs become useless because they cannot distinguish between different users or identify potential attacks originating from distinct external sources.
Configuring NGINX Proxy Manager Headers
The solution lies in configuring NPM to append standard HTTP headers that convey the original client information. Most modern web servers and frameworks recognize these headers automatically if they are present. You need to modify the configuration for each specific host within the NGINX Proxy Manager interface.
- Navigate to the Hosts menu in NGINX Proxy Manager.
- Select the domain or subdomain associated with your service.
- Click on the Advanced tab within the host configuration window.
- Locate the field labeled
Custom Nginx Configuration.
In this text area, you must insert directives that tell NGINX to pass the relevant headers. The most common and reliable method involves setting the X-Forwarded-For, X-Real-IP, and X-Forwarded-Proto variables. These headers are industry standards supported by Apache, Nginx, Node.js, Python, and PHP backends.
Required Configuration Directives
Add the following lines to the Custom Nginx Configuration box. These lines ensure that the original client IP is preserved and passed down the chain.
# Pass the original client IP
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;
The $remote_addr variable captures the immediate connection source, which will be the NPM container when processed by the backend. However, because we also set X-Forwarded-For, many frameworks parse this header to find the leftmost IP, which represents the original client. The X-Forwarded-Proto header informs the backend whether the original request was HTTP or HTTPS, ensuring that redirects and secure cookies work correctly.
Verifying the Setup
After saving the changes, it is essential to verify that the headers are being transmitted correctly. You can do this by checking the access logs of your backend application or by using a simple diagnostic endpoint.
- If your application provides a debug page or API endpoint that echoes request headers, visit it via the proxied domain.
- Look for the
X-Real-IPandX-Forwarded-Forfields in the response. - The value should match your current public IP address, not an internal RFC1918 address like 172.x.x.x or 10.x.x.x.
If the values are still incorrect, clear your browser cache and ensure that no other proxy layers (such as Cloudflare) are stripping or modifying these headers before they reach NPM. In some cases, you may need to restart the NPM container or the Synology NAS to apply deep network changes, though usually, the hot-reload feature of NPM applies these custom configurations immediately.
Common Pitfalls and Troubleshooting
Sometimes, even with correct headers, the backend application might ignore them due to misconfiguration. For instance, older versions of certain software require explicit plugins or modules to trust forwarded headers. Ensure that your application is configured to trust the proxy. In Apache, this might involve loading the mod_remoteip module. In Node.js applications using Express, you need to set app.set('trust proxy', true).
Another issue arises if you have multiple proxies in front of NPM. If Cloudflare is used, the real IP is often found in the CF-Connecting-IP header rather than X-Forwarded-For. In such scenarios, you might need to adjust the NPM configuration to prioritize the Cloudflare header. Refer to our guide on NGINX X-Accel-Redirect 404 Error: Path Config Seems Correct for more insights on handling complex header chains and path resolutions.
Additionally, check for syntax errors in the custom configuration block. A single misplaced character can cause NPM to reject the configuration or fall back to defaults, silently failing to add the headers. Always review the NPM logs for error messages after saving changes.
Security Implications
Passing real IP addresses enhances security by allowing accurate blocking of malicious actors. However, it also exposes your infrastructure to IP spoofing if not handled properly. Since you are controlling the entire stack on Synology DSM, the risk is minimal compared to public-facing setups. Still, ensure that your backend applications validate these headers and do not blindly trust them if exposed directly to the internet without NPM.
By correctly implementing these header passes, you restore full visibility into your user base, enabling precise logging, effective rate limiting, and accurate geographic analytics across all services hosted on your Synology NAS.
Frequently Asked Questions
Why does my application still show the internal IP after adding headers?
Your application likely needs to be explicitly configured to read and trust the forwarded headers. Simply sending the headers is not enough; the backend software must have logic enabled to parse X-Forwarded-For or X-Real-IP instead of relying solely on the socket connection address.
Can I use this method for all hosts in NGINX Proxy Manager?
Yes, you can apply these custom configurations to any host individually. However, if you manage many similar services, consider creating a template or using global default server blocks if your version of NPM supports it, to avoid repetitive manual entry.
What if I am behind Cloudflare, which header should I use?
If Cloudflare is in front of NPM, the X-Forwarded-For header may contain Cloudflare's IPs. You should configure NPM to pass the CF-Connecting-IP header to your backend, or configure your backend to trust Cloudflare's IP ranges and read the first IP in the X-Forwarded-For list.
Does this affect performance significantly?
No, adding these headers has negligible impact on performance. They are lightweight string manipulations performed by NGINX during the proxying process and do not introduce measurable latency or increased CPU usage.
How do I reset the custom configuration if it breaks the site?
If the custom configuration causes a 502 Bad Gateway or prevents NPM from starting, simply edit the host again and delete the contents of the Custom Nginx Configuration box. Save the changes, and NPM will revert to its default header handling, restoring connectivity.