nginx

SKILL.md

Nginx

Web server configuration, reverse proxy, and SSL/TLS.

Basic Server Block

# /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/myapp;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

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;
    }
}

# Multiple backends
upstream backend {
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
    server 127.0.0.1:3003;
}

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://backend;
    }
}

SSL/TLS (HTTPS)

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    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 hardening
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    location / {
        proxy_pass http://localhost:3000;
    }
}
# Get SSL cert with Certbot
sudo certbot --nginx -d example.com -d www.example.com

# Renew certs
sudo certbot renew --dry-run

Location Blocks

# Exact match
location = /health {
    return 200 "OK";
    add_header Content-Type text/plain;
}

# Prefix match
location /api/ {
    proxy_pass http://localhost:3000/;
}

# Regex match (case-sensitive)
location ~ \.php$ {
    fastcgi_pass unix:/var/run/php-fpm.sock;
}

# Regex match (case-insensitive)
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}

# Priority order:
# 1. = exact
# 2. ^~ prefix (stops regex search)
# 3. ~ or ~* regex
# 4. prefix (longest match)

Caching & Performance

# Static file caching
location /static/ {
    alias /var/www/static/;
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

server {
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        proxy_pass http://localhost:3000;
    }
}

# Connection limiting
limit_conn_zone $binary_remote_addr zone=addr:10m;

location /download/ {
    limit_conn addr 5;
}

SPA (Single Page Application)

server {
    listen 80;
    server_name app.example.com;

    root /var/www/app/dist;
    index index.html;

    # All routes fall back to index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Don't cache index.html
    location = /index.html {
        add_header Cache-Control "no-cache";
    }
}

Common Commands

# Test configuration
sudo nginx -t

# Reload (no downtime)
sudo nginx -s reload

# Start/stop
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx

# View logs
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

# Enable site
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo nginx -s reload

Security Headers

# Add to server block
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;
add_header Content-Security-Policy "default-src 'self'" always;

Reference

For HTTPS setup and security hardening: references/ssl.md

Weekly Installs
3
GitHub Stars
2
First Seen
Feb 21, 2026
Installed on
opencode3
gemini-cli3
claude-code3
github-copilot3
codex3
amp3