nginx Reverse Proxy and TLS: Upstreams, Headers, and Let’s Encrypt
Put nginx in front of your app with proxy_pass, forward client metadata, redirect HTTP to HTTPS, and outline Certbot for free certificates.
DevOps & infrastructure Advanced 8 min read
·
nginx sits in front of app processes to terminate TLS, enforce timeouts, and map many hostnames to backends. Directives like proxy_set_header X-Forwarded-Proto exist because your app needs to know the original scheme when generating URLs behind TLS termination.
Containers from Docker Compose often publish an internal port; nginx on the host or edge routes public traffic to them.
Basic reverse proxy
Why proxy_pass to 127.0.0.1: Binds traffic to loopback so the app is not exposed on all interfaces without nginx in front.
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
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;
}
}
Why these headers: The app sees original host and client IP for logs and redirects; X-Forwarded-Proto tells frameworks to generate https:// links.
Security note: Trust these headers only from nginx, not from clients on the open internet.
HTTP to HTTPS redirect
Why redirect port 80: Users and bots still hit http://; a 301 to HTTPS prevents accidental cleartext sessions.
Let’s Encrypt and Certbot (overview)
Why automated TLS: Short-lived certificates reduce breach windows; Certbot renews before expiry if DNS and port 80/443 stay reachable.
- Point DNS
A/AAAArecords to your server. - Install Certbot with the nginx plugin for your OS.
- Run
certbot --nginx -d app.example.comto obtain and install certificates. - Enable automatic renewal (usually a systemd timer or cron).
Security headers (brief)
Why HSTS after HTTPS works: Tells browsers never to downgrade to HTTP for that host—only enable once TLS is correct.
Frequently asked questions
nginx vs Apache?
Both are mature; nginx is common as a reverse proxy/CDN edge due to event-driven architecture and simple static file serving.
What is proxy_set_header for?
Your backend sees the original host and client IP through headers; without them logs and redirects may show 127.0.0.1.
Can I terminate TLS in Docker instead?
Yes—Traefik, Caddy, or nginx in a container can handle certificates; keep private keys out of images and use mounted secrets.
Why not expose my app port directly?
A proxy adds rate limiting, gzip, TLS, routing to multiple services, and a smaller attack surface for your application process.