nginx real-IP fix — handoff for Brad
From: Mike / Claude (TerraPulse)
Date: 2026-06-22
Scope: terrapulse.info vhost only. Does not touch nginx.conf or any other tenant's vhost.
Status: drafted, NOT applied. Brad owns /etc/nginx; please review + apply.
Problem
terrapulse.info.access.log records $remote_addr = 192.168.1.1 for every request — the
LAN gateway, not the visitor. That means TerraPulse's web nginx sits behind a reverse proxy at
192.168.1.1, and the real client IP arrives in an incoming X-Forwarded-For header that our
nginx currently ignores. Net effect: unique-visitor counts are unmeasurable (every human
collapses to one IP), and we can't tell real readers from crawlers by IP.
Fix
Add three real_ip directives to the terrapulse server block(s). nginx then trusts the gateway
and rewrites $remote_addr to the true client IP. The existing realip log_format
($remote_addr ...) starts logging real IPs immediately — no log_format change required,
so nothing global changes and other vhosts using the shared realip format are unaffected.
Diff against /etc/nginx/sites-enabled/terrapulse.info.conf
In both server blocks (the :80 redirect block and the :443 block), right after the
server_name line, add:
# Resolve real client IP from the upstream reverse proxy at the gateway.
set_real_ip_from 192.168.1.1; # <-- confirm: trusted front-proxy address/CIDR
real_ip_header X-Forwarded-For;
real_ip_recursive on;
That's the whole change. ngx_http_realip_module is compiled into stock Debian/Ubuntu nginx,
so no rebuild.
Two things for Brad to confirm
Trusted source.
set_real_ip_from 192.168.1.1trusts exactly the gateway. If the front proxy can present a different source address (or a small range), widen to the right CIDR (e.g.192.168.1.0/24). Trust must be narrow — anything trusted can spoof client IPs.Does the gateway actually send the real client IP in XFF? This fix only recovers the IP if the proxy at
192.168.1.1is putting the true client intoX-Forwarded-For. If it isn't, no change on our nginx can recover it — that's a setting on the gateway proxy (your side). The deploy below is self-verifying: if IPs stay192.168.1.1after reload, the gateway isn't forwarding and needs XFF enabled there.
Apply + verify
sudo nginx -t # syntax check
sudo systemctl reload nginx # zero-downtime reload
# watch a few real hits land:
sudo tail -f /var/log/nginx/terrapulse.info.access.log
Success: the leading IP field shows varied public addresses instead of 192.168.1.1.
Still 192.168.1.1: the gateway proxy isn't sending XFF — fix that there, then recheck.
Rollback
Remove the three lines and sudo systemctl reload nginx. No state, no migration; logs simply
revert to showing the gateway IP.
Note on privacy
Once real IPs land in the logs we'll be storing visitor IPs (personal data). Default log rotation already ages them out. If we ever want analytics without retaining raw IPs, the alternative is a first-party page-counter on the Astro frontend (TerraPulse's own lane, no Brad involvement) — flagged here only as the other option Mike considered.