18.4 Nginx Reverse Proxy and TLS Certificate Provisioning
Rather than exposing Spring Boot directly on port 443, placing Nginx in front to handle SSL termination is vastly more secure and efficient.
1. Nginx Configuration
server {
listen 80;
server_name myapp.com www.myapp.com;
return 301 https://$host$request_uri; # HTTP → HTTPS redirect
}
server {
listen 443 ssl http2;
server_name myapp.com www.myapp.com;
ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://localhost:8080;
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;
}
}
2. Free SSL Certificate via Let's Encrypt (Certbot)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d myapp.com -d www.myapp.com
sudo certbot renew --dry-run # Test auto-renewal (runs every 90 days via cron)
3. Trusting Forwarded Headers in Spring
When behind Nginx, Spring sees all requests coming from 127.0.0.1. Real client IPs arrive in X-Forwarded-For headers — tell Spring to trust them:
server:
forward-headers-strategy: native
Without this, IP-based access control and security logs will incorrectly attribute all traffic to the same local IP.