Nginx powers over 30% of all websites, and its popularity makes it a frequent target for automated attacks, brute force logins, and DDoS attempts. Securing Nginx on your VPS isn’t optional — it’s the minimum baseline for running any production workload. This guide walks through the three most impactful security layers: firewall rules, SSL/TLS hardening, and rate limiting configurations.
We assume you have root access to a Linux VPS running Nginx. If you haven’t picked a provider yet, compare options on our VPS comparison table.
1. Firewall: Lock Down Everything Except Ports 80 and 443
Start with a default-deny firewall policy. UFW (Uncomplicated Firewall) is the simplest option on Ubuntu:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
This allows SSH management and web traffic only. If your application needs additional ports (e.g., 8080 for a Node.js app, 3306 for MySQL from a specific IP), add them individually rather than opening wide ranges.
For tighter control, restrict SSH to your office or home IP:
sudo ufw allow from 203.0.113.50 to any port 22
Advanced: Nginx-Specific iptables Rules
For high-traffic servers, bypass UFW and write direct iptables rules. Limit connection rates to prevent SYN floods:
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 --connlimit-mask 32 -j DROP
iptables -A INPUT -p tcp --syn --dport 443 -m connlimit --connlimit-above 100 --connlimit-mask 32 -j DROP
These rules drop connections from any single IP that exceeds 100 concurrent connections to ports 80 or 443. Adjust the threshold based on your traffic profile.
2. SSL/TLS: Move Beyond Default Certificates
Let’s Encrypt provides free, automated certificates, but the default configuration leaves security on the table. Hardening your TLS setup blocks downgrade attacks and ensures modern clients connect with strong ciphers.
Generate a Strong DH Parameter
Diffie-Hellman key exchange strength depends on the parameter size. Generate a 4096-bit DH group (this takes a few minutes on a VPS):
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Hardened Nginx SSL Configuration
Replace your server block SSL settings with these:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_ecdh_curve secp384r1;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
This configuration: enforces TLS 1.2 and 1.3 only, uses AEAD ciphers (GCM mode), disables session tickets (prevents ticket-based decryption attacks), and sets a secure ECDH curve. Test your setup at SSL Labs — aim for an A+ rating.
Enable HSTS and Security Headers
Add these headers to your Nginx config to prevent downgrade attacks and content injection:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
HSTS tells browsers to always connect via HTTPS for the next two years. Submit your domain to the HSTS preload list for baked-in protection in Chrome, Firefox, and Safari.
3. Rate Limiting: Stop Brute Force and DDoS at the Nginx Layer
Nginx has a built-in rate limiting module that tracks requests by IP and throttles clients exceeding a threshold. This stops brute force login attempts, XML-RPC attacks on WordPress, and resource-exhaustion DDoS.
Basic Rate Limiting for All Requests
In your http block, define a limit zone:
limit_req_zone $binary_remote_addr zone=basic:10m rate=30r/s;
Then apply it in your server or location blocks:
limit_req zone=basic burst=50 nodelay;
This allows 30 requests per second per IP, with a burst capacity of 50 before queuing or dropping. Adjust the rate based on your site’s typical traffic patterns.
Login Page Hardening
Apply stricter limits to login endpoints. For WordPress, target wp-login.php and xmlrpc.php:
location /wp-login.php {
limit_req zone=login:10m rate=3r/m;
limit_conn login_conn 5;
# ... rest of config
}
location /xmlrpc.php {
deny all;
}
This limits login attempts to 3 per minute per IP and blocks the notoriously insecure XML-RPC endpoint entirely (unless you specifically need it for the Jetpack app or mobile clients).
Connection Limiting
Complement rate limiting with connection limits per IP:
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
limit_conn addr 10;
}
This limits each IP to 10 concurrent connections. Combined with rate limiting, it effectively mitigates most layer 7 DDoS attacks targeting your VPS.
Putting It All Together
A complete Nginx security configuration combines all three layers. Start with the firewall to control access at the network level, then harden SSL/TLS to protect data in transit, and finish with rate limiting to defend the application layer. Test every change in a staging environment before applying to production.
For a managed VPS that includes pre-configured security, consider Cloudways ($14/month) with built-in firewall and automated SSL. Budget-conscious users can start with InterServer ($3/month) and apply these hardening steps manually. Browse all providers on our VPS comparison table.




Leave a Reply
You must be logged in to post a comment.