DEV Community

Ramer Labs
Ramer Labs

Posted on

7 Tips for Securing Nginx with TLS and Fail2Ban on Production Servers

Introduction

Running Nginx as a front‑end web server is common, but without proper hardening it can become an easy target for attackers. This guide walks you through seven practical steps to lock down Nginx using TLS, a robust firewall, and Fail2Ban. The checklist is written from the perspective of a DevOps lead who needs repeatable, auditable security controls for production workloads.


1. Enforce TLS 1.2+ and Strong Cipher Suites

Outdated TLS versions (1.0/1.1) are deprecated and vulnerable to POODLE, BEAST, and other attacks. Edit your nginx.conf (or a dedicated snippet in /etc/nginx/conf.d/) to force TLS 1.2 and TLS 1.3 only:

# /etc/nginx/conf.d/ssl.conf ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers \ "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1h; 
Enter fullscreen mode Exit fullscreen mode

Why it matters: Strong ciphers protect data in‑flight and improve your SSL Labs grade.

2. Enable HTTP Strict Transport Security (HSTS)

HSTS tells browsers to only use HTTPS for your domain, preventing protocol downgrade attacks.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; 
Enter fullscreen mode Exit fullscreen mode

Add the header in the same block where you terminate TLS. Remember to test with curl -I https://example.com before submitting to the HSTS preload list.

3. Deploy Free, Auto‑Renewing Certificates with Certbot

Manual certificate management is error‑prone. Use certbot to obtain and renew certificates automatically.

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx sudo certbot --nginx -d example.com -d www.example.com --agree-tos --no-eff-email 
Enter fullscreen mode Exit fullscreen mode

Certbot will edit your Nginx config, add the ssl_certificate directives, and set up a systemd timer for renewal.

4. Harden the Underlying OS Firewall

Even with Nginx locked down, an open firewall can expose services you don’t intend to publish. Use ufw (or iptables) to allow only HTTP/HTTPS and SSH from trusted IPs.

sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp from 203.0.113.0/24 comment "Admin SSH" sudo ufw allow 80/tcp comment "HTTP" sudo ufw allow 443/tcp comment "HTTPS" sudo ufw enable 
Enter fullscreen mode Exit fullscreen mode

Review the rules regularly with ufw status numbered.

5. Install and Configure Fail2Ban for Nginx

Fail2Ban can automatically ban IPs that trigger repeated 4xx/5xx responses, such as brute‑force attempts on API endpoints.

  1. Install:
 sudo apt-get install -y fail2ban 
Enter fullscreen mode Exit fullscreen mode
  1. Create a jail for Nginx:
 # /etc/fail2ban/jail.d/nginx.conf  [nginx-http-auth] enabled = true filter = nginx-http-auth logpath = /var/log/nginx/error.log maxretry = 3 bantime = 86400 findtime = 600 
Enter fullscreen mode Exit fullscreen mode
  1. Restart the service:
 sudo systemctl restart fail2ban 
Enter fullscreen mode Exit fullscreen mode

Fail2Ban will now monitor the error log for authentication failures and block offending IPs via iptables.

6. Restrict Access to Sensitive Locations

Never expose the Nginx status page or internal APIs to the public internet. Use allow/deny directives or IP‑based ACLs.

location /nginx_status { stub_status; allow 127.0.0.1; deny all; } 
Enter fullscreen mode Exit fullscreen mode

Similarly, protect /admin or /api endpoints with basic auth or OAuth, and always limit them to known client IP ranges.

7. Enable Logging and Centralized Monitoring

Security is only as good as your ability to detect anomalies. Configure Nginx to log in JSON format and ship logs to a centralized system like ELK or Grafana Loki.

log_format json '{"time":"$time_iso8601",' '"remote_addr":"$remote_addr",' '"request":"$request",' '"status":$status, ' '"body_bytes_sent":$body_bytes_sent, ' '"http_referrer":"$http_referer",' '"http_user_agent":"$http_user_agent"}'; access_log /var/log/nginx/access.json json; 
Enter fullscreen mode Exit fullscreen mode

Feed the logs into your SIEM of choice and set alerts for spikes in 4xx/5xx responses.


Putting It All Together

Below is a minimal but complete server block that incorporates the hardening steps discussed:

server { listen 80 default_server; listen [::]:80 default_server; server_name example.com www.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name example.com www.example.com; # TLS configuration (ssl.conf is included) include /etc/nginx/conf.d/ssl.conf; # HSTS header add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; root /var/www/html; index index.html index.htm; location / { try_files $uri $uri/ =404; } # Restrict status page location /nginx_status { stub_status; allow 127.0.0.1; deny all; } } 
Enter fullscreen mode Exit fullscreen mode

Deploy the configuration, test with nginx -t, and reload:

sudo nginx -t && sudo systemctl reload nginx 
Enter fullscreen mode Exit fullscreen mode

Conclusion

Hardening Nginx is a layered process: enforce modern TLS, lock down the OS firewall, automate certificate management, and add reactive defenses like Fail2Ban. By following these seven tips you’ll significantly reduce the attack surface of your web tier while keeping operational overhead low. For deeper dives into Nginx security patterns and managed hosting options, you might find the resources at https://lacidaweb.com helpful.

Top comments (0)