Nginx Management Essentials
Essential commands for managing Nginx on Ubuntu VPS. These snippets cover installation, SSL setup, performance tuning, and troubleshooting.
1. Complete Nginx Installation & Setup
Install Nginx and enable it to start on boot:
# Install Nginx
sudo apt update && sudo apt install nginx -y
# Enable and start Nginx
sudo systemctl enable nginx
sudo systemctl start nginx
# Check status
sudo systemctl status nginx
# Test Nginx configuration
sudo nginx -t
2. SSL Certificate with Let's Encrypt
Set up free SSL certificates using Certbot:
# Install Certbot
sudo apt install certbot python3-certbot-nginx -y
# Obtain and install SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Auto-renewal test
sudo certbot renew --dry-run
# List all certificates
sudo certbot certificates
3. View Real-Time Access Logs
Monitor incoming requests in real-time:
# Tail access log with color coding
sudo tail -f /var/log/nginx/access.log
# Show only 403/404/500 errors
sudo tail -f /var/log/nginx/access.log | grep -E "403|404|500"
# Monitor specific domain
sudo tail -f /var/log/nginx/access.log | grep "yourdomain.com"
# Count requests per IP in last 1000 lines
sudo tail -1000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
Best Practices
- Always test configuration with
nginx -tbefore reloading - Keep SSL certificates updated - check
certbot renewregularly - Monitor error logs daily for security issues
- Use
nginx -s reloadinstead of restart for zero-downtime config updates - Implement rate limiting on all public endpoints
- Set up log rotation to prevent disk space issues
Enabling Gzip Compression in Nginx
Gzip compression dramatically reduces the size of text-based responses sent over the wire, improving load times and reducing bandwidth costs. Add the following block inside your http context in /etc/nginx/nginx.conf:
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json
application/javascript application/xml+rss
application/atom+xml image/svg+xml;
Run nginx -t && systemctl reload nginx after every config change. Verify compression is active with curl -H "Accept-Encoding: gzip" -I https://yourdomain.com and look for Content-Encoding: gzip in the response headers.
Browser Caching with Cache-Control Headers
Static assets — images, CSS, JavaScript — rarely change between requests. Telling browsers to cache them locally saves round-trips and speeds up repeat visits significantly.
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
Use a content-hash in filenames (e.g. app.a3f9c1.js) so browsers pick up new versions automatically when you deploy.
Rate Limiting to Prevent Abuse
Rate limiting protects your server from brute-force attacks, scrapers, and runaway clients. Define a shared memory zone and apply it to sensitive endpoints:
http {
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
}
server {
location /login {
limit_req zone=login burst=3 nodelay;
}
}
The burst parameter allows a small spike above the rate before nginx starts returning 429 Too Many Requests. Monitor hits with grep "limiting requests" /var/log/nginx/error.log.
Hardening Security Headers
Security headers are free to add and meaningfully reduce your attack surface. Place these inside your server block or a shared snippet:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Validate your headers at securityheaders.com — aim for an A or A+ rating.
Tuning Worker Processes and Connections
Nginx performance at the OS level is controlled by a few key directives in /etc/nginx/nginx.conf:
worker_processes auto; # match CPU core count
worker_rlimit_nofile 65535;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
keepalive_timeout 65;
keepalive_requests 1000;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
}
worker_processes auto automatically sets one worker per CPU core. sendfile enables zero-copy file transfers. tcp_nopush batches response headers with the first data packet, reducing small-packet overhead.
Testing Your Configuration
Always validate before reloading: nginx -t catches syntax errors without touching the live config. Use ab (Apache Bench) or wrk for load testing:
wrk -t4 -c100 -d30s https://yourdomain.com/
Check /var/log/nginx/access.log and error.log regularly. Tools like GoAccess parse nginx logs in real time and produce useful dashboards without sending data to third parties.