In production, Nginx doesn’t fail for syntax: it fails for details. An ambiguous server_name, a poorly placed header or an unvalidated SSL renewal can bring down your site at the worst possible moment.
Guided practical case
Scenario: a VPS with two apps:
api.midominio.com(Node API),midominio.com(static frontend).
Aim:
- separate vhosts by domain,
- force HTTPS,
- add base security headers,
- validate automatic SSL renewal.
Recommended configuration
/etc/nginx/sites-available/api.midominio.com:
server {
listen 80;
server_name api.midominio.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name api.midominio.com;
ssl_certificate /etc/letsencrypt/live/api.midominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.midominio.com/privkey.pem;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options DENY always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
location / {
proxy_pass http://127.0.0.1:3000;
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_read_timeout 60s;
}
}
Secure operational flow
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d api.midominio.com -d midominio.com
sudo systemctl status certbot.timer
If nginx -t fails, do not reload. First correct and validate again.
Errors that are repeated the most
- Use a default block that captures unexpected domains.
- Do not pass
X-Forwarded-Proto, breaking HTTPS detection in backend. - Mix aggressive caching rules in HTML and API.
- Activate strict headers without testing authentication flows and embeds.
Actionable checklist
- One file per vhost, no ambiguous global rules
- Redirect 80 -> 443 on all public domains
- Valid certificates and verified automatic renewal
-
nginx -tin pipeline or script prior to each reload - Security headers audited in browser and scanner
Happy reading! ☕
Comments