DEV Community

Ramer Labs
Ramer Labs

Posted on

7 Tips for Securing Nginx with TLS and Firewall Rules Today

Introduction

If you’re a DevOps lead responsible for a fleet of web servers, the first line of defense is a rock‑solid Nginx configuration paired with a tight firewall. In this tutorial we’ll walk through seven practical steps that bring your Nginx instance from “just working” to “battle‑ready.” The focus is on TLS hardening, firewall rule design, and complementary OS‑level safeguards such as Fail2Ban and SSH key enforcement.


1. Grab a Free, Trusted TLS Certificate

Let’s Encrypt is the de‑facto standard for automated, free certificates. Install the certbot client on your Linux host and request a cert for your domain:

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

The wizard will:

  • Verify domain ownership via HTTP‑01 challenge.
  • Generate a certificate bundle in /etc/letsencrypt/live/example.com/.
  • Auto‑reload Nginx after successful issuance.

Tip: Use the --dry-run flag to test renewal before you go live.


2. Harden the Nginx SSL Configuration

A weak cipher suite or outdated protocol can undo all your hard work. Replace the default ssl.conf with a curated block:

# /etc/nginx/snippets/secure_ssl.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers \
  'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" 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 the snippet in your server block:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    include snippets/secure_ssl.conf;
    server_name example.com www.example.com;
    # … other directives …
}
Enter fullscreen mode Exit fullscreen mode

This configuration:

  • Enforces TLS 1.2/1.3 only.
  • Uses strong, forward‑secrecy ciphers.
  • Enables HSTS with a two‑year max‑age.
  • Adds common security headers.

3. Lock Down the Host Firewall

A well‑crafted firewall reduces the attack surface dramatically. Below we use UFW (Uncomplicated Firewall) for readability, but the same rules translate to iptables or nftables.

# Allow SSH (rate‑limited)
sudo ufw limit OpenSSH
# Allow HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Deny everything else
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Enable the firewall
sudo ufw enable
Enter fullscreen mode Exit fullscreen mode

Why rate‑limit SSH? It caps the number of connection attempts per minute, slowing down brute‑force attacks.


4. Deploy Fail2Ban to Thwart Brute‑Force Attempts

Fail2Ban watches log files for suspicious patterns and automatically inserts temporary iptables blocks. Install and enable a basic jail for Nginx and SSH:

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

Create /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
maxretry = 5
bantime = 3600

[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 7200
Enter fullscreen mode Exit fullscreen mode

Restart the service:

sudo systemctl restart fail2ban
Enter fullscreen mode Exit fullscreen mode

Now any repeated failed login or HTTP auth attempt will be blocked for the specified bantime.


5. Enforce SSH Key Authentication Only

Password logins are a common vector. Convert all user accounts to key‑only access:

# Edit /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
Enter fullscreen mode Exit fullscreen mode

Reload the daemon:

sudo systemctl reload sshd
Enter fullscreen mode Exit fullscreen mode

Distribute public keys via a secure channel (e.g., ssh-copy-id) and keep the private key in a password‑protected vault like ssh‑agent or a hardware token.


6. Automate Certificate Renewal & Reload

Let’s Encrypt certificates are only valid for 90 days. Certbot already installs a systemd timer, but you should verify it runs:

systemctl list-timers | grep certbot
Enter fullscreen mode Exit fullscreen mode

Add a post‑renewal hook to guarantee Nginx picks up the fresh cert without manual reload:

# /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
#!/bin/sh
systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

Make it executable:

sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
Enter fullscreen mode Exit fullscreen mode

7. Back Up Nginx Configurations Regularly

A misconfiguration can bring your site down. Use rsync or a simple cron job to push the /etc/nginx/ directory to a secure backup location:

# /etc/cron.daily/nginx-backup
#!/bin/sh
BACKUP_DIR=/var/backups/nginx-$(date +%F)
mkdir -p "$BACKUP_DIR"
rsync -a /etc/nginx/ "$BACKUP_DIR/"
# Optional: upload to remote storage (e.g., S3)
Enter fullscreen mode Exit fullscreen mode

Store backups off‑site and rotate them weekly to keep storage costs low.


Conclusion

By following these seven steps you’ll have a Nginx front‑end that:

  • Serves traffic over strong TLS only.
  • Rejects unwanted network traffic at the OS level.
  • Automatically blocks brute‑force attempts.
  • Relies on SSH keys instead of passwords.
  • Keeps its own configuration safely versioned and backed up.

Implementing the checklist today will dramatically raise the security posture of any production web service. For deeper dives into Linux hardening and managed hosting, you might find the resources at https://lacidaweb.com useful.

Top comments (0)