DEV Community

Ramer Labs
Ramer Labs

Posted on

7 Tips for Securing Nginx on Ubuntu Servers in Production Environments

Overview

Running Nginx as a front‑end web server on Ubuntu is a common choice for high‑traffic applications. However, the default installation leaves several attack surfaces wide open: weak TLS ciphers, missing security headers, and no rate‑limiting, to name a few. This tutorial walks an SRE through seven practical steps to harden Nginx without sacrificing performance.


1. Enforce Strong TLS

TLS is the first line of defense. Use TLS 1.3 where possible and drop legacy protocols. A minimal nginx.conf snippet for modern TLS looks like this:

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;

    # TLS 1.3 only, fallback to TLS 1.2 with strong ciphers
    ssl_protocols TLSv1.3 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256";

    # Enable OCSP stapling for faster revocation checks
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
}
Enter fullscreen mode Exit fullscreen mode
  • Why it matters – Strong ciphers prevent downgrade attacks and improve forward secrecy.
  • Tip – Test your configuration with sslscan or Qualys SSL Labs.

2. Harden the Firewall

A properly scoped firewall reduces the attack surface dramatically. On Ubuntu, ufw (Uncomplicated Firewall) is a friendly wrapper around iptables.

# Allow HTTP/HTTPS traffic only
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

If you run SSH on a non‑standard port, add a rule for it as well. Keep the rule set minimal; each open port is a potential entry point.


3. Deploy Fail2Ban for Brute‑Force Protection

Fail2Ban watches log files and bans IPs that exhibit suspicious behavior. A simple jail for Nginx looks like this (/etc/fail2ban/jail.d/nginx.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

The accompanying filter (/etc/fail2ban/filter.d/nginx-http-auth.conf) matches typical 401/403 responses. Restart the service:

sudo systemctl restart fail2ban
Enter fullscreen mode Exit fullscreen mode

Now any IP that fails to authenticate more than five times within an hour gets blocked for an hour.


4. Add Security Headers

HTTP security headers tell browsers how to treat your content. Insert the following block into the server context:

add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline';" always;
Enter fullscreen mode Exit fullscreen mode
  • X‑Content‑Type‑Options stops MIME sniffing.
  • X‑Frame‑Options prevents click‑jacking.
  • Content‑Security‑Policy mitigates XSS.

These headers are lightweight and add virtually no latency.


5. Limit Request Size and Rate

Large payloads and burst traffic can exhaust resources. Use client_max_body_size to cap uploads and limit_req_zone/limit_req for rate limiting.

# Global limits (in http context)
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/s;

server {
    ...
    client_max_body_size 5M;

    location /login {
        limit_req zone=one burst=5 nodelay;
        proxy_pass http://backend;
    }
}
Enter fullscreen mode Exit fullscreen mode

This configuration allows a maximum of 30 requests per second per IP, with a burst of five extra requests for legitimate spikes.


6. Run Nginx with Systemd Hardening

Systemd offers several hardening options that sandbox the service. Edit the override file (/etc/systemd/system/nginx.service.d/hardening.conf):

[Service]
# Drop privileges
User=www-data
Group=www-data

# Restrict filesystem access
ProtectSystem=full
ProtectHome=true
ReadWriteDirectories=-/var/log/nginx

# Limit capabilities
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE

# Prevent core dumps
LimitCORE=0
Enter fullscreen mode Exit fullscreen mode

Reload systemd and restart Nginx:

sudo systemctl daemon-reload
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

These settings ensure Nginx cannot write to arbitrary paths, cannot gain extra capabilities, and cannot produce core dumps that might leak memory.


7. Automate Patching and Backups

Security is a moving target. Use unattended-upgrades for automatic security updates and a simple rsnapshot configuration for daily Nginx config backups.

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

Create a snapshot script (/etc/cron.daily/nginx-backup):

#!/bin/sh
rsnapshot daily /etc/nginx /var/log/nginx
Enter fullscreen mode Exit fullscreen mode

Make it executable and ensure rsnapshot is configured with a retention policy that matches your RPO.


Quick Checklist

  • [ ] TLS 1.3 enabled, weak ciphers disabled
  • [ ] Firewall only allows 80/443 (and custom SSH)
  • [ ] Fail2Ban active for Nginx auth failures
  • [ ] Security headers added to every response
  • [ ] Request size capped, rate limiting in place
  • [ ] Systemd hardening flags applied
  • [ ] Automatic security patches and daily config backups

Conclusion

Hardening Nginx on Ubuntu is a series of low‑effort, high‑impact steps. By tightening TLS, locking down the host firewall, adding Fail2Ban, sprinkling security headers, and sandboxing the service with systemd, you dramatically reduce the attack surface while keeping latency low. For deeper dives into Ubuntu server hardening, consider checking out resources like the official Ubuntu Security Guide, and if you need a managed partner to audit or host your hardened stack, https://lacidaweb.com offers practical assistance without the sales push.

Top comments (0)