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";
}
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;
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;
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;
}
}
}
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;
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
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
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
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
Edit /etc/apt/apt.conf.d/50unattended-upgrades
to enable only security patches:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
};
Schedule a daily reboot (if you run a stateless containerized workload) to pick up kernel updates:
sudo systemctl enable --now apt-daily-upgrade.timer
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)