Introduction
If you’re a DevOps lead responsible for high‑traffic web services, securing the front‑end proxy is non‑negotiable. Nginx sits at the edge of most modern stacks, acting as a reverse proxy, load balancer, and static file server. A single misconfiguration can expose sensitive data or open the door to denial‑of‑service attacks. This checklist walks you through seven practical steps to harden Nginx with TLS, firewall rules, and complementary security tools.
1. Enforce Strong TLS Settings
TLS is the first line of defense against eavesdropping. Use the latest stable OpenSSL version and configure Nginx to prefer modern cipher suites.
# /etc/nginx/conf.d/ssl.conf
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers \
"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
- Why it matters – Disabling TLS 1.0/1.1 eliminates known weaknesses. The cipher list above follows Mozilla’s "Intermediate" recommendation and avoids RSA key‑exchange, which is vulnerable to log‑jam attacks.
2. Redirect All HTTP Traffic to HTTPS
A stray HTTP endpoint can leak cookies and allow man‑in‑the‑middle attacks. Add a catch‑all server block that issues a 301 redirect.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
Make sure the block is placed before any other server
directives, otherwise Nginx may never evaluate it.
3. Harden the Underlying Linux Firewall
Even with TLS in place, you should restrict which ports are reachable from the internet. A typical Nginx host only needs ports 80, 443, and SSH (22) for admin access.
# Using ufw (Ubuntu/Debian)
ufw default deny incoming
ufw default allow outgoing
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 22/tcp comment "SSH for admin"
ufw enable
If you prefer iptables
:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Tip: Keep a copy of your firewall rules in version control. It makes rollback after a bad change painless.
4. Deploy Fail2Ban to Thwart Brute‑Force SSH Attempts
While Nginx itself isn’t vulnerable to password guessing, a compromised SSH key can give an attacker full control of the server. Fail2Ban monitors log files and bans IPs that exceed a threshold.
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
Restart the service:
systemctl restart fail2ban
You can add a similar jail for Nginx’s error.log
to block repeated 404 or 403 responses that look like scanning attempts.
5. Enable HTTP Security Headers
Headers such as Content‑Security‑Policy
, X‑Content‑Type‑Options
, and Referrer-Policy
reduce the attack surface for XSS and click‑jacking.
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header Referrer-Policy "no-referrer-when-downgrade";
add_header Content-Security-Policy "default-src 'self' https:; script-src 'self' 'unsafe-inline'";
Apply these directives inside the server
block that serves your public site.
6. Regularly Rotate TLS Certificates and Automate Renewal
Manual certificate updates are error‑prone. Use certbot (Let’s Encrypt) or a commercial ACME client to schedule automatic renewal.
# Install certbot and obtain a cert for example.com
apt-get install certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com
# Verify renewal works
certbot renew --dry-run
Add a cron job (or rely on the systemd timer installed by certbot) to run certbot renew
twice daily.
7. Keep Nginx and System Packages Patched
Security patches are released frequently. Enable unattended upgrades for non‑critical updates, but schedule a weekly maintenance window for major Nginx version bumps.
# Ubuntu example – enable unattended upgrades
apt-get install unattended-upgrades
dpkg-reconfigure unattended-upgrades
During the maintenance window, run:
apt-get update && apt-get upgrade -y
systemctl restart nginx
Always test the new binary in a staging environment before production rollout.
Checklist Summary
✅ | Action |
---|---|
1 | Use TLS 1.2/1.3 with a modern cipher suite |
2 | Force HTTP → HTTPS redirects |
3 | Lock down the firewall to only required ports |
4 | Deploy Fail2Ban for SSH and Nginx logs |
5 | Add essential security headers |
6 | Automate TLS certificate renewal |
7 | Apply regular OS and Nginx patches |
Following these seven steps will give you a robust, production‑ready Nginx deployment that resists common network‑level attacks while staying performant.
For deeper dives into server hardening, consider checking out the resources on https://lacidaweb.com, which offers practical guides tailored for developers and SREs.
Top comments (0)