# ALTERNATIVE to nginx-direct.example.conf; never enable both for the same host. # Remote edge -> TLS -> this nginx on the CMS host -> loopback CMS. # Replace hotel.example/certificate paths and BOTH occurrences of 203.0.113.10/32. # The example peer is reserved documentation space, so it permits no real edge. # Requires ngx_http_realip_module. The remote edge MUST overwrite X-Forwarded-For # with one verified client IP and enforce the public HTTPS/Host configuration. geo $realip_remote_addr $cms_trusted_edge { default 0; 203.0.113.10/32 1; } server { listen 443 ssl; listen [::]:443 ssl; server_name hotel.example; if ($host != hotel.example) { return 444; } if ($cms_trusted_edge = 0) { return 403; } ssl_certificate /etc/letsencrypt/live/hotel.example/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/hotel.example/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; client_max_body_size 64m; set_real_ip_from 203.0.113.10/32; real_ip_header X-Forwarded-For; real_ip_recursive off; location / { proxy_pass http://127.0.0.1:3002; proxy_http_version 1.1; proxy_set_header Host hotel.example; proxy_set_header X-Forwarded-Host hotel.example; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-Port 443; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_set_header CF-Connecting-IP ""; proxy_set_header X-Real-Client-IP ""; proxy_set_header Forwarded ""; proxy_set_header Connection ""; proxy_buffering off; proxy_read_timeout 300s; proxy_cache off; } } # Cloudflare variant: use this same restricted-edge mode, NOT the direct mode. # Replace the documentation peer in BOTH geo/set_real_ip_from lists with the # current verified Cloudflare IPv4 AND IPv6 CIDRs, then change real_ip_header to # CF-Connecting-IP. Use Full (strict) TLS and review authenticated origin pulls. # CF-Connecting-IP is still removed before forwarding to the CMS: nginx sends # only its normalized, trusted result in X-Forwarded-For and X-Real-IP.