DEV Community

Ramer Labs
Ramer Labs

Posted on

7 Tips for Securing Nginx with TLS and Fail2Ban on Ubuntu 22.04

Introduction

Running Nginx on a public server without proper hardening is a recipe for abuse. Two of the most effective, low‑maintenance defenses are TLS encryption and Fail2Ban. TLS protects data in transit, while Fail2Ban automatically bans IPs that show malicious behavior (e.g., repeated 404s or brute‑force login attempts). This tutorial walks an SRE through a practical, step‑by‑step hardening of an Ubuntu 22.04 Nginx instance.


Why TLS and Fail2Ban Matter for Nginx

  • TLS eliminates eavesdropping and man‑in‑the‑middle attacks. Modern browsers also flag non‑HTTPS sites as insecure, hurting user trust.
  • Fail2Ban watches log files for patterns that indicate attacks (failed logins, repeated 404s, etc.) and adds temporary firewall rules to block the offending IPs.
  • Together they address both data confidentiality and automated abuse, two common vectors in today's threat landscape.

Prerequisites

  • Ubuntu 22.04 server with root or sudo access.
  • Nginx installed (sudo apt install nginx).
  • A domain name pointing to the server's public IP.
  • Basic familiarity with systemctl and editing files under /etc.

1. Install and Configure TLS with Let’s Encrypt

Install Certbot

sudo apt update && sudo apt install -y certbot python3‑certbot‑nginx
Enter fullscreen mode Exit fullscreen mode

Obtain a Certificate

Run Certbot in Nginx mode; it will automatically edit your virtual host files:

sudo certbot --nginx -d example.com -d www.example.com
Enter fullscreen mode Exit fullscreen mode

Answer the prompts (agree to the terms, choose Redirect to enforce HTTPS). Certbot will:

  1. Request a certificate from Let’s Encrypt.
  2. Install the certificate at /etc/letsencrypt/live/....
  3. Add a listen 443 ssl; block and a redirect from port 80.

Verify Renewal

sudo systemctl status certbot.timer
Enter fullscreen mode Exit fullscreen mode

The timer runs twice daily; you can also test a dry‑run:

sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

2. Harden TLS Cipher Suites

Open the default SSL snippet (or create one) at /etc/nginx/snippets/ssl-params.conf and paste the following:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "
  TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:
  TLS_AES_128_GCM_SHA256:EECDH+AESGCM:EDH+AESGCM";
ssl_ecdh_curve secp384r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
Enter fullscreen mode Exit fullscreen mode

Then include this snippet in each server block:

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    include snippets/ssl-params.conf;
    # ... other directives ...
}
Enter fullscreen mode Exit fullscreen mode

Reload Nginx:

sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

3. Install Fail2Ban and Create an Nginx Jail

sudo apt install -y fail2ban
Enter fullscreen mode Exit fullscreen mode

Create a local jail configuration at /etc/fail2ban/jail.local (do not edit jail.conf directly):

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600
findtime = 600

[nginx-botsearch]
enabled = true
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 7200
findtime = 900
Enter fullscreen mode Exit fullscreen mode

Fail2Ban ships with the required filters (nginx-http-auth.conf and nginx-botsearch.conf). Restart the service:

sudo systemctl restart fail2ban
Enter fullscreen mode Exit fullscreen mode

Check the status of the new jails:

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

4. Tighten the Host Firewall with UFW

If you aren't already using UFW, enable it and allow only the necessary ports:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH      # port 22
sudo ufw allow 'Nginx Full' # ports 80 and 443
sudo ufw enable
Enter fullscreen mode Exit fullscreen mode

UFW will now respect the temporary bans Fail2Ban adds via iptables.


5. Testing and Verification

  1. TLS sanity check – Visit https://www.ssllabs.com/ssltest/ and run a scan on your domain. Aim for an "A" rating.
  2. Fail2Ban simulation – From another machine, attempt a protected location:
   curl -I https://example.com/protected
Enter fullscreen mode Exit fullscreen mode

Repeat with wrong credentials until the IP is banned (check sudo fail2ban-client status nginx-http-auth).

  1. UFW rules – Verify that the ufw status numbered output shows the expected allow rules and that Fail2Ban inserted a rule like REJECT for the offending IP.

6. Common Pitfalls and How to Avoid Them

  • Certificate renewal failures – Ensure port 80 is reachable for the HTTP‑01 challenge. If you forced a permanent redirect, add a temporary exception in the Nginx config before renewal.
  • Over‑aggressive Fail2Ban bans – Start with a low bantime and monitor /var/log/fail2ban.log. Adjust maxretry and findtime to suit your traffic pattern.
  • Cipher suite incompatibility – Older browsers may not support TLS 1.3. Keep TLS 1.2 enabled and test with a range of devices.
  • UFW and Docker conflict – If you later add Docker containers, remember Docker manipulates iptables directly; you may need to add explicit ufw allow rules for container ports.

Conclusion

By combining Let’s Encrypt TLS, a hardened cipher suite, Fail2Ban, and a minimal UFW rule set, you dramatically raise the security bar of any Nginx server without sacrificing performance. The steps above are repeatable across multiple hosts, making them ideal for a fleet of web services. For more practical guides and a curated list of security‑focused tools, check out https://lacidaweb.com – it’s a handy reference for busy SREs looking to stay ahead of the curve.

Top comments (0)