DEV Community

Ramer Labs
Ramer Labs

Posted on

7 Tips for Securing Nginx with TLS and Firewall Rules Now

Introduction

If you’re a DevOps lead responsible for public‑facing services, Nginx is probably the front‑line web server or reverse proxy in your stack. While it’s lightning‑fast, a mis‑configured instance can become an easy target for attackers. This tutorial walks you through a practical, step‑by‑step hardening checklist that covers TLS best practices, firewall rules, and a few often‑overlooked Linux tweaks.


1. Obtain a Strong TLS Certificate

Use Let’s Encrypt for Automation

# Install certbot (Debian/Ubuntu example) sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx # Request a certificate for example.com and www.example.com sudo certbot --nginx -d example.com -d www.example.com 
Enter fullscreen mode Exit fullscreen mode
  • Certbot automatically edits your Nginx config to enable HTTPS.
  • It also sets up a systemd timer for automatic renewal.

Prefer ECDSA Over RSA

If your client base includes modern browsers, generate an ECDSA key for better performance:

sudo openssl ecparam -genkey -name secp384r1 -out /etc/ssl/private/example.com.key sudo openssl req -new -key /etc/ssl/private/example.com.key -out /etc/ssl/csr/example.com.csr # Then use certbot with the --key-type ecdsa flag sudo certbot --nginx --key-type ecdsa -d example.com -d www.example.com 
Enter fullscreen mode Exit fullscreen mode

2. Harden the Nginx TLS Configuration

Create a dedicated snippet called ssl-strong.conf and include it in your server blocks.

# /etc/nginx/snippets/ssl-strong.conf 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"; 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; preload" always; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options DENY; add_header X-XSS-Protection "1; mode=block"; 
Enter fullscreen mode Exit fullscreen mode

Then reference it:

server { listen 443 ssl http2; server_name example.com www.example.com; include snippets/ssl-strong.conf; # …rest of config… } 
Enter fullscreen mode Exit fullscreen mode

3. Enable HTTP/2 and Brotli Compression

HTTP/2 reduces latency, while Brotli offers better compression ratios than gzip.

# Enable HTTP/2 in the listen directive (already shown above) # Install Brotli module (Debian example) sudo apt-get install -y nginx-module-brotli # Add Brotli settings brotli on; brotli_comp_level 6; brotli_types text/plain text/css application/javascript application/json image/svg+xml; 
Enter fullscreen mode Exit fullscreen mode

4. Restrict Access with a Host‑Based Firewall

Using UFW (Uncomplicated Firewall)

sudo ufw default deny incoming sudo ufw default allow outgoing # Allow SSH (limit to 5 attempts per minute) sudo ufw limit 22/tcp # Allow HTTP/HTTPS sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable 
Enter fullscreen mode Exit fullscreen mode

Fine‑Grained iptables Example

If you need more control, drop traffic from known malicious IP ranges:

# Block a CIDR (example) sudo iptables -A INPUT -s 185.220.101.0/24 -j DROP # Log and drop malformed packets sudo iptables -A INPUT -p tcp --tcp-flags ALL NONE -j LOG --log-prefix "[DROP NULL] " sudo iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP 
Enter fullscreen mode Exit fullscreen mode

Persist rules with iptables-persistent or netfilter-persistent.

5. Deploy Fail2Ban for Brute‑Force Protection

Fail2Ban monitors log files and bans IPs that show malicious signs.

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

Create a custom jail for Nginx:

# /etc/fail2ban/jail.d/nginx-http-auth.conf [nginx-http-auth] enabled = true filter = nginx-http-auth logpath = /var/log/nginx/error.log maxretry = 3 bantime = 3600 
Enter fullscreen mode Exit fullscreen mode

The built‑in nginx-http-auth filter catches repeated 401 responses.

6. Secure File Permissions and Ownership

# Nginx binary and config files should be owned by root:root sudo chown -R root:root /etc/nginx sudo chmod -R 644 /etc/nginx/*.conf sudo chmod 600 /etc/ssl/private/*.key # Serve static content with a non‑privileged user (www-data) sudo chown -R www-data:www-data /var/www/html 
Enter fullscreen mode Exit fullscreen mode

Avoid running Nginx as root; the master process runs as root only to bind privileged ports, while workers run as www-data.

7. Automate Monitoring and Renewal

SSL Certificate Renewal

Certbot already creates a systemd timer, but verify it:

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

Health Checks

Add a simple /healthz endpoint that returns 200 OK:

location = /healthz { access_log off; return 200 "OK"; add_header Content-Type text/plain; } 
Enter fullscreen mode Exit fullscreen mode

Integrate this endpoint with your monitoring stack (Prometheus node exporter, UptimeRobot, etc.) to get instant alerts if Nginx crashes.


Conclusion

Hardening Nginx is a combination of cryptographic hygiene, network‑level gating, and disciplined operational practices. By following these seven tips—obtaining a strong TLS certificate, tightening cipher suites, enabling HTTP/2 and Brotli, locking down the firewall, adding Fail2Ban, tightening file permissions, and automating monitoring—you’ll dramatically reduce the attack surface of any web service.

If you’re looking for a reliable partner to review your Nginx hardening checklist or need hands‑on assistance with cloud‑native deployments, consider checking out https://lacidaweb.com for practical guidance and support.

Top comments (0)