DEV Community

Ramer Lacida
Ramer Lacida

Posted on

7 Tips for Hardening Nginx on Ubuntu 22.04 for High‑Traffic Sites

Introduction

Running Nginx as a front‑end web server on Ubuntu 22.04 gives you a rock‑solid, low‑latency stack. But when you start serving high‑traffic applications, a single misconfiguration can become a security nightmare. This guide walks you through seven practical hardening steps that any SRE or DevOps lead can apply in minutes, while keeping performance intact.


1. Enforce TLS 1.3‑Only Connections

Older TLS versions are riddled with known weaknesses (e.g., POODLE, BEAST). Ubuntu’s openssl package ships with TLS 1.2 enabled by default, but you can lock Nginx down to TLS 1.3 for the best security and latency.

server {
    listen 443 ssl http2;
    ssl_certificate     /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;

    # TLS 1.3 only
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256";
}
Enter fullscreen mode Exit fullscreen mode

Why it matters: TLS 1.3 reduces handshake round‑trips, improves forward secrecy, and drops legacy ciphers that attackers love.


2. Harden SSL Settings with Strong Cipher Suites

Even within TLS 1.3, you should explicitly list strong ciphers. The snippet above already does that, but for environments that still need TLS 1.2 fallback (e.g., older browsers), add a safe TLS 1.2 block:

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384";
    ssl_ecdh_curve secp384r1;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
Enter fullscreen mode Exit fullscreen mode

Avoid !aNULL, !MD5, and !RC4 – they’re already excluded by the modern cipher list.


3. Deploy a Strict Content Security Policy (CSP)

A well‑crafted CSP stops XSS and data‑injection attacks before they reach your backend. Place the header in the http block so it applies to every virtual host.

add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header Referrer-Policy no-referrer-when-downgrade;
Enter fullscreen mode Exit fullscreen mode

Tailor the policy to your asset pipeline – the example above allows scripts from Cloudflare’s CDN only.


4. Limit Request Size and Rate‑Limit Connections

High‑traffic sites are prime targets for DoS attacks. Nginx can throttle abusive clients without pulling in a heavyweight WAF.

http {
    client_max_body_size 2M;                # reject giant uploads
    limit_req_zone $binary_remote_addr zone=one:10m rate=30r/s;

    server {
        location / {
            limit_req zone=one burst=10 nodelay;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation: client_max_body_size caps POST payloads, while limit_req_zone caps requests per IP to 30 per second with a burst of 10.


5. Harden File Permissions and Run as a Non‑Root User

By default, Nginx starts as root to bind to ports < 1024, then drops privileges to the www-data user. Verify the user and group in /etc/nginx/nginx.conf:

user www-data www-data;
worker_processes auto;
pid /run/nginx.pid;
Enter fullscreen mode Exit fullscreen mode

Next, lock down the configuration directory:

sudo chown -R root:root /etc/nginx
sudo chmod -R 750 /etc/nginx
sudo chmod 640 /etc/nginx/nginx.conf
Enter fullscreen mode Exit fullscreen mode

Never store private keys in a world‑readable location; keep them under /etc/ssl/private with 600 permissions.


6. Enable Fail2Ban for Nginx‑Specific Patterns

Fail2Ban can automatically ban IPs that repeatedly trigger 4xx/5xx responses. Create a jail for Nginx error logs:

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

And the corresponding filter (/etc/fail2ban/filter.d/nginx-http-auth.conf):

[Definition]
failregex = ^<HOST> -.*"GET .*/wp-login.php HTTP/.*" 401
            ^<HOST> -.*"POST .*/xmlrpc.php HTTP/.*" 401
Enter fullscreen mode Exit fullscreen mode

This bans brute‑force attempts against WordPress login endpoints, a common vector on shared Nginx hosts.


7. Automate Patch Management with Unattended‑Upgrades

Security is a moving target. Ubuntu’s unattended-upgrades package can automatically apply critical updates without manual intervention.

sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
Enter fullscreen mode Exit fullscreen mode

Edit /etc/apt/apt.conf.d/50unattended-upgrades to enable only security patches:

Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
};
Enter fullscreen mode Exit fullscreen mode

Schedule a daily reboot (if you run a stateless containerized workload) to pick up kernel updates:

sudo systemctl enable --now apt-daily-upgrade.timer
Enter fullscreen mode Exit fullscreen mode

Conclusion

Hardening Nginx on Ubuntu 22.04 doesn’t have to be a heavyweight project. By applying the seven steps above—TLS 1.3 only, strong cipher suites, CSP headers, request throttling, strict file permissions, Fail2Ban integration, and automated security patches—you’ll dramatically reduce the attack surface while keeping latency low for high‑traffic workloads.

If you need a quick checklist or a managed environment that follows these best practices out of the box, check out https://lacidaweb.com for reliable hosting solutions tailored to developers.

Top comments (0)