# ============================================================================
# Nginx Static Site Configuration
# Optimized for serving static files (HTML, CSS, JS, images)
# Perfect for: SPAs (React, Vue, Angular), static site generators, documentation
# Standards: 2025 Best Practices with Aggressive Caching
# ============================================================================

# Rate Limiting Zones (optional for static sites, but good for DDoS protection)
# Place in http block of /etc/nginx/nginx.conf if not already present
limit_req_zone $binary_remote_addr zone=static:10m rate=50r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;

# ============================================================================
# HTTP to HTTPS Redirect
# ============================================================================

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # Let's Encrypt challenge
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    # Redirect all HTTP to HTTPS
    location / {
        return 301 https://$server_name$request_uri;
    }
}

# ============================================================================
# HTTPS Static Site Server Block
# ============================================================================

server {
    # Listen on port 443 with HTTP/2 support
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # Server name - CUSTOMIZE THIS
    server_name example.com www.example.com;

    # Root directory - CUSTOMIZE THIS
    root /var/www/html;

    # Default index files
    index index.html index.htm;

    # ========================================================================
    # SSL/TLS Configuration (2025 Standards)
    # ========================================================================

    # Certificate paths - CUSTOMIZE THESE
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;

    # Modern protocols only (TLS 1.2 and 1.3)
    ssl_protocols TLSv1.2 TLSv1.3;

    # Session settings
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    # Let client choose cipher (recommended for TLS 1.3)
    ssl_prefer_server_ciphers off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/certs/ca-bundle.crt;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # ========================================================================
    # Security Headers
    # ========================================================================

    # Hide Nginx version
    server_tokens off;

    # HSTS (1 year with includeSubDomains and preload)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Prevent clickjacking
    add_header X-Frame-Options "SAMEORIGIN" always;

    # Prevent MIME sniffing
    add_header X-Content-Type-Options "nosniff" always;

    # XSS protection
    add_header X-XSS-Protection "1; mode=block" always;

    # Content Security Policy (adjust for your site's needs)
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self';" always;

    # Referrer Policy
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Permissions Policy
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

    # ========================================================================
    # Performance Optimizations
    # ========================================================================

    # Gzip compression for text-based files
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript
               application/json application/javascript application/xml+rss
               application/rss+xml application/atom+xml image/svg+xml
               text/x-component text/x-cross-domain-policy;
    gzip_disable "msie6";

    # File handle caching (improves performance significantly)
    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # Client settings
    client_body_buffer_size 128k;
    client_max_body_size 5m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    # Timeouts
    client_body_timeout 12;
    client_header_timeout 12;
    keepalive_timeout 65;
    send_timeout 10;

    # TCP optimization
    tcp_nopush on;
    tcp_nodelay on;

    # ========================================================================
    # Logging
    # ========================================================================

    # Access log with caching status
    log_format static '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" rt=$request_time';

    access_log /var/log/nginx/example.com.access.log static;
    error_log /var/log/nginx/example.com.error.log warn;

    # ========================================================================
    # Static File Caching Strategy
    # ========================================================================

    # Immutable assets (fingerprinted files: app.abc123.js)
    # These never change, so cache aggressively
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|otf)$ {
        # Rate limiting (lighter for static assets)
        limit_req zone=static burst=100 nodelay;

        # Cache for 1 year
        expires 1y;
        add_header Cache-Control "public, immutable";

        # ETag support for cache validation
        etag on;

        # Disable logging for static assets (reduces I/O)
        access_log off;

        # CORS headers if serving assets to other domains
        # add_header Access-Control-Allow-Origin "*";

        # Gzip static files
        gzip_static on;
    }

    # Versioned assets (with hash in filename)
    location ~* \.[0-9a-f]{8,}\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
        gzip_static on;
    }

    # Media files (videos, audio)
    location ~* \.(mp4|webm|ogg|mp3|wav|flac|aac|mov|avi|wmv)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;

        # Enable range requests for video streaming
        add_header Accept-Ranges bytes;
    }

    # PDF and document files
    location ~* \.(pdf|doc|docx|ppt|pptx|xls|xlsx)$ {
        expires 7d;
        add_header Cache-Control "public";
        access_log off;
    }

    # ========================================================================
    # SPA (Single Page Application) Support
    # ========================================================================

    # Main location block for HTML files and SPA routing
    location / {
        # Light rate limiting
        limit_req zone=static burst=50 nodelay;
        limit_conn addr 20;

        # Try to serve file directly, fallback to index.html for SPA routing
        # This handles client-side routing (React Router, Vue Router, etc.)
        try_files $uri $uri/ /index.html;

        # Don't cache HTML files (they may change on deployment)
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires "0";

        # ETag for cache validation
        etag on;
    }

    # Explicitly handle index.html (main SPA entry point)
    location = /index.html {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires "0";
        etag on;
    }

    # ========================================================================
    # API Proxying (Optional - if your SPA calls an API)
    # ========================================================================

    # Proxy API requests to backend
    # location /api/ {
    #     proxy_pass http://localhost:3000;
    #     proxy_http_version 1.1;
    #     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;
    #
    #     # Don't cache API responses
    #     add_header Cache-Control "no-store";
    # }

    # ========================================================================
    # Security and Access Control
    # ========================================================================

    # Deny access to hidden files (except .well-known)
    location ~ /\.(?!well-known) {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Deny access to backup and config files
    location ~* \.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Disable directory listing
    autoindex off;

    # ========================================================================
    # Custom Error Pages
    # ========================================================================

    # Custom error pages (create these files in your root directory)
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    location = /404.html {
        internal;
        add_header Cache-Control "no-cache";
    }

    location = /50x.html {
        root /usr/share/nginx/html;
        internal;
    }

    # ========================================================================
    # Robots and SEO
    # ========================================================================

    # robots.txt
    location = /robots.txt {
        access_log off;
        log_not_found off;
    }

    # sitemap.xml
    location = /sitemap.xml {
        access_log off;
        log_not_found off;
    }

    # favicon.ico
    location = /favicon.ico {
        access_log off;
        log_not_found off;
        expires 1y;
    }

    # ========================================================================
    # Health Check
    # ========================================================================

    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}

# ============================================================================
# Deployment Instructions
# ============================================================================
# 1. Customize the following:
#    - server_name (line 44)
#    - root directory (line 47)
#    - ssl_certificate paths (lines 58-59)
#
# 2. Create root directory and copy your static files:
#    sudo mkdir -p /var/www/html
#    sudo cp -r /path/to/your/build/* /var/www/html/
#
# 3. Set proper permissions:
#    sudo chown -R www-data:www-data /var/www/html
#    sudo chmod -R 755 /var/www/html
#
# 4. Test configuration:
#    sudo nginx -t
#
# 5. Copy to sites-available:
#    sudo cp static-site.conf /etc/nginx/sites-available/example.com.conf
#
# 6. Create symbolic link:
#    sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/
#
# 7. Reload Nginx:
#    sudo systemctl reload nginx
#
# 8. Verify caching is working:
#    curl -I https://example.com/assets/app.js
#    # Look for "Cache-Control: public, immutable" header
#
# ============================================================================
# SPA Deployment Notes
# ============================================================================
# For React/Vue/Angular apps:
#   1. Build your app: npm run build
#   2. Copy build output to /var/www/html
#   3. The try_files directive handles client-side routing
#   4. HTML files are not cached (allows instant updates)
#   5. Assets (JS/CSS) are cached aggressively (use hash in filenames)
#
# Asset Fingerprinting:
#   - Use build tools to add content hash to filenames
#   - Example: app.abc123.js instead of app.js
#   - This allows aggressive caching with instant cache invalidation
#
# ============================================================================
# Cache Headers Explained
# ============================================================================
# Static Assets (JS/CSS/Images):
#   - Cache-Control: "public, immutable"
#   - expires 1y
#   - Files are cached for 1 year
#   - "immutable" tells browser file will never change
#
# HTML Files:
#   - Cache-Control: "no-cache, no-store, must-revalidate"
#   - Browser always checks server for updates
#   - Ensures users get latest version after deployment
#
# ETag:
#   - Enables conditional requests (If-None-Match)
#   - Returns 304 Not Modified if file unchanged
#   - Reduces bandwidth while ensuring freshness
#
# ============================================================================
# Performance Tips
# ============================================================================
# 1. Use CDN for global distribution
# 2. Enable Brotli compression (if available)
# 3. Optimize images (WebP format, proper sizing)
# 4. Use HTTP/2 Server Push for critical resources (if needed)
# 5. Implement preload/prefetch for better loading
# 6. Minify and bundle assets
# 7. Use lazy loading for images and components
# 8. Monitor with tools like Lighthouse, WebPageTest
#
# ============================================================================
# Troubleshooting
# ============================================================================
# SPA 404 on refresh:
#   - Check try_files directive is present
#   - Ensure /index.html exists in root directory
#
# Assets not loading:
#   - Check file permissions (should be readable by www-data)
#   - Verify paths in HTML match actual file locations
#   - Check browser console for 404 errors
#
# Cache not working:
#   - Clear browser cache and test
#   - Check response headers with curl -I
#   - Verify expires and Cache-Control headers
# ============================================================================
