When configuring Nginx as a reverse proxy, the proxy_set_header
directives are crucial for passing important client information to backend servers. However, many developers encounter situations where these headers mysteriously vanish. Here's what's happening in your specific case:
# Your current proxy_params file contains:
proxy_set_header Host $http_host;
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;
proxy_set_header X-Frame-Options "deny";
From your curl output, I notice you're using Cloudflare (as evident from the CF-RAY
and cloudflare-nginx
headers). This explains why your Nginx proxy headers aren't appearing - Cloudflare acts as an additional proxy layer before requests reach your server.
Solution 1: Configure Cloudflare Properly
You need to ensure Cloudflare passes through the original headers. In your Cloudflare dashboard:
1. Go to SSL/TLS → Edge Certificates
2. Enable "Origin Server" and "Full (strict)" mode
3. In Rules → Transform Rules, create a rule to pass headers
Solution 2: Modify Your Nginx Configuration
Update your server block to handle Cloudflare-specific headers:
server {
listen 443;
server_name mywebsite.net;
# Cloudflare IP ranges
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 104.16.0.0/12;
# Add all Cloudflare IP ranges here
real_ip_header CF-Connecting-IP;
location / {
proxy_pass http://127.0.0.1:8069;
proxy_set_header Host $host;
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;
proxy_set_header CF-IPCountry $http_cf_ipcountry;
proxy_set_header CF-Connecting-IP $http_cf_connecting_ip;
proxy_set_header CF-RAY $http_cf_ray;
}
}
To confirm your headers are now working:
curl -I -k https://mywebsite.net --header "X-Forwarded-Proto: https"
Or better yet, create a test endpoint that echoes headers:
location /test-headers {
return 200 "$http_x_forwarded_for\n$http_x_real_ip\n";
add_header Content-Type text/plain;
}
Remember that when using multiple proxy layers (Cloudflare → Nginx → Application), each layer might modify or strip headers. Always:
- Check each proxy layer's documentation for header handling
- Use absolute variables ($host instead of $http_host) when possible
- Test with different client IPs to verify IP forwarding
When working with NGINX reverse proxy configurations, the proxy_set_header
directives should pass specified headers to the backend server. However, in cases where Cloudflare is involved, we often encounter situations where these headers don't appear in responses.
Your current configuration shows:
location / {
proxy_pass http://127.0.0.1:8069;
include proxy_params;
}
Yet the curl response shows headers coming from Cloudflare instead of your backend server:
HTTP/1.1 200 OK
Server: cloudflare-nginx
CF-RAY: 2f190f162b2a2dc7-BOM
Several factors could be causing this:
1. Cloudflare acts as a reverse proxy itself, potentially stripping or modifying headers
2. The -I
flag in curl only shows response headers, not request headers received by backend
3. Your backend application might not be echoing the received headers
Method 1: Check headers received by backend
Create a test endpoint that echoes headers:
location /test-headers {
proxy_pass http://127.0.0.1:8069;
include proxy_params;
add_header X-Test-Header "visible";
}
Method 2: Use verbose curl logging
curl -v -k https://mywebsite.net/test-headers
1. Ensure Cloudflare passes original headers:
# In Cloudflare dashboard
Enable "Origin Server Headers" option
2. Modify your NGINX configuration:
location / {
proxy_pass http://127.0.0.1:8069;
proxy_set_header Host $host;
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;
proxy_set_header CF-Connecting-IP $http_cf_connecting_ip;
proxy_pass_request_headers on;
}
Add test headers to verify NGINX processing:
location / {
# ... existing config ...
add_header X-NGINX-Proxy "Active";
add_header X-Forwarded-Proto $scheme always;
}
1. Test without Cloudflare (temporarily pause in dashboard)
2. Check backend logs for received headers
3. Verify headers at different points in the chain using:
curl -k -H "X-Test: value" https://mywebsite.net/test-headers