# ==============================================================================
# docker/nginx/default.conf — Production Nginx Configuration for SMM Panel
# ==============================================================================
# Security hardening:
#  - Server tokens hidden
#  - Only necessary methods allowed (GET, POST, HEAD, OPTIONS)
#  - Large request body rejection (prevents memory exhaustion)
#  - X-Forwarded-For trusted only from known proxy IPs
#  - Rate limiting zones
#  - HTTPS redirect (when SSL is terminated at load balancer, use X-Forwarded-Proto)
#  - Static file caching
#  - Gzip compression
#  - PHP-FPM with Unix socket (faster than TCP socket)
# ==============================================================================

# Rate limiting zones
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=webhook:10m rate=60r/m;
limit_req_zone $binary_remote_addr zone=general:10m rate=60r/s;

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

server {
    listen 80;
    server_name _;

    root /var/www/html/public;
    index index.php;

    # ── Security ────────────────────────────────────────────────────────────
    server_tokens off;

    # Limit request methods
    if ($request_method !~ ^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS)$) {
        return 405;
    }

    # Maximum request body size (adjust for file uploads)
    client_max_body_size 10M;
    client_body_timeout 15s;
    client_header_timeout 15s;

    # Prevent slow loris attacks
    keepalive_timeout 65s;
    send_timeout 15s;

    # Connection limit per IP
    limit_conn addr 20;

    # ── Compression ─────────────────────────────────────────────────────────
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        image/svg+xml;

    # ── Static Asset Caching ─────────────────────────────────────────────────
    # Vite-compiled assets have content-hashed filenames — safe to cache forever
    location ~* /build/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
        try_files $uri =404;
    }

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

    # ── Sensitive File Protection ────────────────────────────────────────────
    # Block access to .env, .git, and other sensitive paths
    location ~ /\. {
        deny all;
        return 404;
    }

    location ~ \.(env|log|md|gitignore|lock)$ {
        deny all;
        return 404;
    }

    # Block access to storage (only symlinked public/ should be accessible)
    location ^~ /storage/ {
        deny all;
        return 404;
    }

    # ── Webhook Routes (higher rate limit) ──────────────────────────────────
    location ~* ^/webhooks/ {
        limit_req zone=webhook burst=20 nodelay;
        try_files $uri $uri/ /index.php?$query_string;

        fastcgi_pass php_fpm;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_read_timeout 30s;
    }

    # ── Login/Register Routes (strict rate limit) ────────────────────────────
    location ~* ^/(login|register|password) {
        limit_req zone=login burst=5 nodelay;
        try_files $uri $uri/ /index.php?$query_string;

        fastcgi_pass php_fpm;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # ── Main Application ─────────────────────────────────────────────────────
    location / {
        limit_req zone=general burst=30 nodelay;
        try_files $uri $uri/ /index.php?$query_string;
    }

    # ── PHP-FPM ──────────────────────────────────────────────────────────────
    location ~ \.php$ {
        # SECURITY: Prevent execution of uploaded PHP files
        # Only execute PHP from the document root
        try_files $uri =404;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php_fpm;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param PHP_VALUE "upload_max_filesize=10M \n post_max_size=10M";
        include fastcgi_params;

        # Timeouts
        fastcgi_connect_timeout 10s;
        fastcgi_send_timeout 30s;
        fastcgi_read_timeout 60s;

        # Buffering (tune for your server RAM)
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
    }

    # ── Health Check ─────────────────────────────────────────────────────────
    # Used by Docker healthcheck and load balancer probes
    location = /up {
        access_log off;
        try_files $uri /index.php?$query_string;
        fastcgi_pass php_fpm;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # ── Logs ─────────────────────────────────────────────────────────────────
    access_log /var/log/nginx/access.log combined buffer=512k flush=5m;
    error_log  /var/log/nginx/error.log warn;
}

# PHP-FPM upstream (Unix socket is faster than TCP for same-host communication)
upstream php_fpm {
    server unix:/run/php/php8.2-fpm.sock;
    # OR for Docker:
    # server 127.0.0.1:9000;
}
