DEV Community

Ramer Labs
Ramer Labs

Posted on

7 Tips for Securing Your Nginx Server with TLS and Fail2Ban

Introduction

Running a public web service on Nginx is great for performance, but it also makes you a target. A single mis‑configuration can expose sensitive data or open the door to brute‑force attacks. This guide walks you through a practical checklist to harden an Nginx instance on a Linux server using TLS, a strict firewall, Fail2Ban, and automated backups. The steps are written for a DevOps lead who wants reproducible, auditable security.

1. Enforce TLS with Modern Cipher Suites

TLS is the first line of defense. Use letsencrypt for free certificates, but the real work is in the Nginx configuration.

# /etc/nginx/conf.d/ssl.conf server { listen 443 ssl http2; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # Only TLS 1.2+ and strong ciphers ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH"; # Enable OCSP stapling for faster revocation checks ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # HSTS – tell browsers to always use HTTPS add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # Your usual location blocks go here } 
Enter fullscreen mode Exit fullscreen mode
  • Why these settings? TLS 1.2 and 1.3 drop legacy protocols vulnerable to POODLE and BEAST. The cipher list favours forward secrecy (ECDHE) and AEAD encryption (AES‑GCM). HSTS prevents downgrade attacks.

2. Redirect All HTTP Traffic to HTTPS

A simple server block catches plain HTTP and issues a 301 redirect.

server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; } 
Enter fullscreen mode Exit fullscreen mode

3. Harden the Firewall (UFW Example)

Only expose ports you need. For a typical web stack, that's 80, 443, and 22 (SSH). Block everything else.

sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp # SSH – consider limiting to your IP range sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable 
Enter fullscreen mode Exit fullscreen mode

Tip: Use ufw status numbered to verify the rule order. Consider moving SSH to a non‑standard port or using key‑based auth only.

4. Deploy Fail2Ban to Thwart Brute‑Force Attempts

Fail2Ban watches Nginx logs for repeated 4xx/5xx responses and bans the offending IP via iptables.

# /etc/fail2ban/jail.d/nginx-http-auth.conf [nginx-http-auth] enabled = true port = http,https filter = nginx-http-auth logpath = /var/log/nginx/error.log maxretry = 5 bantime = 3600 ; 1 hour 
Enter fullscreen mode Exit fullscreen mode

Create the matching filter (/etc/fail2ban/filter.d/nginx-http-auth.conf):

[Definition] failregex = ^<HOST> -.*"GET .* HTTP/.*" 401 ^<HOST> -.*"POST .* HTTP/.*" 401 
Enter fullscreen mode Exit fullscreen mode

Restart Fail2Ban:

sudo systemctl restart fail2ban sudo fail2ban-client status nginx-http-auth 
Enter fullscreen mode Exit fullscreen mode

5. Secure SSH Access

  • Disable password authentication: PasswordAuthentication no
  • Enforce key‑based login: PubkeyAuthentication yes
  • Limit users: AllowUsers deploy
  • Optional: Use AllowTcpForwarding no and PermitRootLogin no.

Apply changes with systemctl reload sshd.

6. Automated Backups of Certs and Configs

A broken TLS chain is worse than a compromised server. Use rsnapshot or a simple cron job to copy /etc/nginx/, /etc/letsencrypt/, and /etc/fail2ban/ to a remote storage bucket.

# /etc/cron.daily/nginx-backup #!/bin/bash TIMESTAMP=$(date +%F) DEST="s3://my-backup-bucket/nginx-$TIMESTAMP/" aws s3 sync /etc/nginx $DEST/nginx --delete aws s3 sync /etc/letsencrypt $DEST/letsencrypt --delete aws s3 sync /etc/fail2ban $DEST/fail2ban --delete 
Enter fullscreen mode Exit fullscreen mode

Rotate backups with a lifecycle policy (e.g., keep 30 days).

7. Keep the System Patched Automatically

On Debian/Ubuntu, enable unattended upgrades for security patches:

sudo apt-get install unattended-upgrades sudo dpkg-reconfigure --priority=low unattended-upgrades 
Enter fullscreen mode Exit fullscreen mode

For Red Hat/CentOS, use yum-cron:

sudo yum install yum-cron sudo systemctl enable --now yum-cron 
Enter fullscreen mode Exit fullscreen mode

Regularly audit the /var/log/unattended-upgrades/ directory to ensure updates are applied.

Monitoring and Alerting

Combine Nginx status metrics with Fail2Ban bans in a Prometheus + Grafana stack. A simple exporter can expose nginx_upstream_response_time and fail2ban_banned_ips. Set alerts for:

  • TLS certificate expiration within 30 days.
  • Sudden spikes in 4xx/5xx errors.
  • New IP bans exceeding a threshold.

Conclusion

Hardening Nginx is a layered effort: TLS configuration, firewall rules, intrusion‑prevention with Fail2Ban, and disciplined backup and patch processes. By following these seven steps you’ll dramatically reduce the attack surface while keeping your web service performant and reliable. For more hands‑on tutorials and community‑driven best practices, check out https://lacidaweb.com.

Top comments (0)