DEV Community

Ramer Labs
Ramer Labs

Posted on

7 Tips for Hardening Nginx and Linux Servers in Production

Introduction

Running Nginx on a Linux host is a common pattern for high‑traffic web services, but a mis‑configured stack can become an easy target for attackers. This checklist walks you through seven practical steps you can apply today to tighten TLS, lock down the firewall, automate fail2ban, secure SSH, enable reliable backups, add a lightweight WAF, and keep the system patched. It’s written from the perspective of a DevOps lead who needs repeatable, auditable hardening procedures for production environments.


1. Enforce Strong TLS Settings

TLS is the first line of defense for any public‑facing service. Nginx’s ssl.conf should be trimmed to modern ciphers only and HTTP/2 enabled.

# /etc/nginx/conf.d/ssl.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" always; 
Enter fullscreen mode Exit fullscreen mode
  • Disable TLS 1.0/1.1 – they are deprecated.
  • Prefer server ciphers to avoid weak client‑side selections.
  • Enable HSTS to force browsers onto HTTPS.

After editing, test the configuration with openssl s_client -connect yourdomain.com:443 -tls1_2 and use tools like SSL Labs to verify the grade.


2. Harden the Host Firewall

A minimal iptables (or nftables) rule set reduces the attack surface. The example below blocks everything except HTTP/HTTPS, SSH (restricted to a known IP range), and loopback.

# /etc/iptables.rules *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] # Allow loopback -A INPUT -i lo -j ACCEPT # Allow established connections -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # HTTP/HTTPS -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # SSH from trusted subnet (e.g., 203.0.113.0/24) -A INPUT -p tcp -s 203.0.113.0/24 --dport 22 -j ACCEPT COMMIT 
Enter fullscreen mode Exit fullscreen mode

Load the rules with iptables-restore < /etc/iptables.rules and make the file persistent using your distro’s firewall service (e.g., netfilter-persistent).


3. Deploy Fail2Ban for Brute‑Force Protection

Fail2Ban monitors log files and bans IPs that show malicious signs. A typical jail for Nginx and SSH looks like this:

# /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 with systemctl restart fail2ban. Verify bans via fail2ban-client status sshd.


4. Secure SSH with Key‑Based Authentication Only

Password logins are the weakest link. Enforce public‑key authentication and disable root login.

# /etc/ssh/sshd_config (excerpt) PasswordAuthentication no PubkeyAuthentication yes PermitRootLogin prohibit-password AllowUsers deploy@example.com 
Enter fullscreen mode Exit fullscreen mode

After editing, run ssh-keygen -t ed25519 on the admin machine, copy the ~/.ssh/id_ed25519.pub to the server’s ~/.ssh/authorized_keys, and reload SSH: systemctl reload sshd.


5. Implement Automated Backups

A reliable backup strategy protects you from ransomware and accidental deletions. Below is a simple rsync‑based script that snapshots /var/www and /etc/nginx to a remote SFTP server.

#!/bin/bash # /usr/local/bin/backup-nginx.sh set -euo pipefail REMOTE="backup@example.com" DEST="/backups/$(hostname)/$(date +%Y%m%d)" mkdir -p "$DEST" # Sync web root and config rsync -a --delete /var/www "$DEST/www" rsync -a /etc/nginx "$DEST/nginx" # Push to remote storage sftp "$REMOTE" <<EOF mkdir -p $DEST put -r $DEST/* $DEST/ EOF # Keep last 7 days locally find /backups/$(hostname) -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} + 
Enter fullscreen mode Exit fullscreen mode

Schedule the script with cron (0 2 * * * /usr/local/bin/backup-nginx.sh). Test restoration regularly to ensure integrity.


6. Add a Lightweight Web Application Firewall (WAF)

ModSecurity works well with Nginx and provides rule‑based request filtering. Install the module and enable the OWASP Core Rule Set (CRS).

# Ubuntu/Debian example apt-get install libnginx-mod-http-modsecurity # Enable in nginx.conf modsecurity on; modsecurity_rules_file /etc/modsecurity/modsecurity.conf; 
Enter fullscreen mode Exit fullscreen mode

Edit /etc/modsecurity/modsecurity.conf to set SecRuleEngine On and point Include to the CRS rules directory. Restart Nginx and monitor the audit log (/var/log/modsec_audit.log).


7. Automate Patch Management

Keeping the OS and packages up‑to‑date closes known vulnerabilities. Use unattended upgrades for security‑only updates.

# Install unattended-upgrades apt-get install unattended-upgrades # Enable and configure dpkg-reconfigure --priority=low unattended-upgrades 
Enter fullscreen mode Exit fullscreen mode

For Red Hat‑based systems, enable yum-cron with yum-cron.conf set to apply_updates = yes. Combine this with a daily health check script that alerts on failed updates.


Conclusion

Hardening Nginx and its underlying Linux host is a layered effort: strong TLS, a locked‑down firewall, automated brute‑force mitigation, key‑only SSH, reliable backups, a modest WAF, and continuous patching. By following this checklist you’ll reduce the likelihood of a successful breach and improve compliance posture. For deeper dives into each topic and ready‑made Ansible roles, check out the resources at https://lacidaweb.com.

Top comments (0)