← back to Watches

nginx/omega-watches.conf

173 lines

# Nginx Configuration for Omega Watch Price History
# This file should be copied to /etc/nginx/sites-available/
# and symlinked to /etc/nginx/sites-enabled/

upstream omega_watches_backend {
    # Load balancing strategy
    least_conn;

    # Backend server(s)
    server 127.0.0.1:7600 max_fails=3 fail_timeout=30s;

    # Add more servers here for horizontal scaling
    # server 127.0.0.1:7601 max_fails=3 fail_timeout=30s;

    # Keep-alive connections
    keepalive 32;
}

# Rate limiting zones
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/m;
limit_req_zone $binary_remote_addr zone=general_limit:10m rate=200r/m;

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

server {
    listen 80;
    server_name 45.61.58.125 omega-watches.local;

    # 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 "no-referrer-when-downgrade" always;

    # Logging
    access_log /var/log/nginx/omega-watches-access.log combined;
    error_log /var/log/nginx/omega-watches-error.log warn;

    # Root directory for static files
    root /root/Projects/watches/dist;
    index index.html;

    # Client max body size
    client_max_body_size 10M;

    # Timeouts
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;

    # Static file caching
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
        try_files $uri $uri/ =404;
    }

    # API endpoints with rate limiting
    location /api/ {
        # Rate limiting
        limit_req zone=api_limit burst=20 nodelay;
        limit_conn conn_limit 10;

        # Proxy settings
        proxy_pass http://omega_watches_backend;
        proxy_http_version 1.1;

        # Headers
        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_set_header Connection "";

        # Buffering
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;

        # Cache API responses (optional)
        # proxy_cache api_cache;
        # proxy_cache_valid 200 5m;
        # proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    }

    # WebSocket support
    location /ws {
        proxy_pass http://omega_watches_backend;
        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;

        # WebSocket timeouts
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    # Health check endpoint (no rate limiting)
    location /api/health {
        limit_req zone=general_limit burst=5 nodelay;
        proxy_pass http://omega_watches_backend;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        access_log off;
    }

    # Monitoring endpoints (restrict to localhost)
    location /api/admin/ {
        allow 127.0.0.1;
        allow 45.61.58.125;
        deny all;

        proxy_pass http://omega_watches_backend;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # SPA fallback - serve index.html for all other routes
    location / {
        limit_req zone=general_limit burst=50 nodelay;
        try_files $uri $uri/ /index.html;
    }

    # Deny access to hidden files
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Deny access to backup files
    location ~* \.(bak|backup|old|save|swp|swo)$ {
        deny all;
        access_log off;
    }
}

# HTTPS configuration (uncomment and configure SSL certificates)
# server {
#     listen 443 ssl http2;
#     server_name 45.61.58.125 omega-watches.local;
#
#     # SSL certificates (Let's Encrypt)
#     ssl_certificate /etc/letsencrypt/live/omega-watches.local/fullchain.pem;
#     ssl_certificate_key /etc/letsencrypt/live/omega-watches.local/privkey.pem;
#
#     # SSL configuration
#     ssl_protocols TLSv1.2 TLSv1.3;
#     ssl_ciphers HIGH:!aNULL:!MD5;
#     ssl_prefer_server_ciphers on;
#     ssl_session_cache shared:SSL:10m;
#     ssl_session_timeout 10m;
#
#     # HSTS
#     add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
#
#     # Include all location blocks from above
#     # ...
# }

# Redirect HTTP to HTTPS (uncomment when SSL is configured)
# server {
#     listen 80;
#     server_name 45.61.58.125 omega-watches.local;
#     return 301 https://$server_name$request_uri;
# }