nginx
Installation
SKILL.md
Nginx
Overview
Nginx is a high-performance web server, reverse proxy, and load balancer. This skill provides workflows for common nginx tasks including site configuration, SSL setup, reverse proxying, and security hardening.
Quick Commands
Test Configuration
Always test before reloading:
nginx -t
Reload Nginx
Apply changes without dropping connections:
systemctl reload nginx
# or
nginx -s reload
Check Status
systemctl status nginx
nginx -v
Site Configuration
Default Paths
- Main config:
/etc/nginx/nginx.conf - Sites available:
/etc/nginx/sites-available/ - Sites enabled:
/etc/nginx/sites-enabled/ - HTML root:
/var/www/html/or/usr/share/nginx/html/
Create a New Site
- Create configuration in
sites-available/:
nano /etc/nginx/sites-available/example.com
- Basic static site template:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
- Enable the site:
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Reverse Proxy
Basic Reverse Proxy
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
WebSocket Support
location /ws {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
SSL/TLS with Let's Encrypt
Using Certbot
# Install certbot
apt install certbot python3-certbot-nginx
# Obtain and configure certificate
certbot --nginx -d example.com -d www.example.com
# Auto-renewal test
certbot renew --dry-run
Manual SSL Configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# SSL optimization
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
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;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
Load Balancing
Upstream Configuration
upstream backend {
least_conn; # or ip_hash, least_time
server 192.168.1.10:3000 weight=5;
server 192.168.1.11:3000 weight=5;
server 192.168.1.12:3000 backup;
keepalive 32;
}
server {
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Load Balancing Methods
- round_robin (default): Requests distributed evenly
- least_conn: Sends to server with fewest active connections
- ip_hash: Client IP determines server (session persistence)
- least_time: Sends to server with lowest response time (NGINX Plus)
Security Hardening
Hide Nginx Version
# In http block of nginx.conf
server_tokens off;
Rate Limiting
# In http block
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
# In server/location block
limit_req zone=one burst=5 nodelay;
limit_conn addr 10;
Block Bad User Agents
if ($http_user_agent ~* (bot|crawler|spider|scraper)) {
return 403;
}
Restrict Access
location /admin {
allow 192.168.1.0/24;
deny all;
# or
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
Performance Optimization
Gzip Compression
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/rss+xml application/atom+xml image/svg+xml;
Static File Caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
Buffer Settings
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
Troubleshooting
Check Configuration Syntax
nginx -t
nginx -T # Full config dump
View Error Logs
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/access.log
Common Issues
"nginx: [emerg] bind() to 0.0.0.0:80 failed" Port 80 already in use:
ss -tlnp | grep :80
systemctl stop apache2 # If Apache running
Permission Denied on Static Files
chmod -R 755 /var/www/site
chown -R www-data:www-data /var/www/site
502 Bad Gateway
- Check upstream service is running
- Verify firewall allows connection
- Check SELinux/AppArmor policies
Scripts
Use bundled scripts for common operations:
# Create new site configuration
scripts/create-site.sh example.com /var/www/example.com
# Enable/disable sites
scripts/site-enable.sh example.com
scripts/site-disable.sh example.com
# Test and reload with backup check
scripts/safe-reload.sh
Resources
- Full configuration reference: See references/nginx-directives.md
- Common snippets: See references/snippets.md for copy-paste templates