# This is the main Nginx configuration file for the AliasVault reverse-proxy container.
# which exposes all AliasVault services via both 80 (HTTP)
# and 443 (HTTPS) with either a self-signed or Let's Encrypt certificate.
events {
    worker_connections 1024;
}

http {
    client_max_body_size 25M;

    upstream client {
        server client:3000 max_fails=1 fail_timeout=5s;
    }

    upstream api {
        server api:3001 max_fails=1 fail_timeout=5s;
    }

    upstream admin {
        server admin:3002 max_fails=1 fail_timeout=5s;
    }

    # Preserve any existing X-Forwarded-* headers, this is relevant if AliasVault
    # is running behind another reverse proxy.
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;
    set_real_ip_from 192.168.0.0/16;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Enable gzip compression, which reduces the amount of data that needs to be transferred
    # to speed up WASM load times.
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    server {
        listen 80;
        listen 443 ssl;
        server_name _;

        # Include the appropriate SSL certificate configuration generated
        # by the entrypoint script (only applies to 443).
        include /etc/nginx/ssl.conf;

        # Security headers
        add_header Referrer-Policy "strict-origin-when-cross-origin" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header Cross-Origin-Resource-Policy "same-origin" always;
        add_header Content-Security-Policy "frame-ancestors 'self'" always;

        # Root for static files
        root /usr/share/nginx/html;

        # Handle ACME challenge for Let's Encrypt certificate validation
        location /.well-known/acme-challenge/ {
            allow all;
            root /var/www/certbot;
            try_files $uri =404;
            default_type "text/plain";
            add_header Cache-Control "no-cache";
            break;
        }

        # Error page handler location (internal use only)
        location = /status.html {
            internal;
            try_files /status.html =404;
            add_header Cache-Control "no-cache, no-store, must-revalidate";
            add_header Pragma "no-cache";
            add_header Expires "0";
        }

        # Admin interface
        location /admin {
            proxy_pass http://admin;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Prefix /admin/;

            # Add WebSocket support for Blazor server
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;

            # Show status page if admin is down
            proxy_intercept_errors on;
            error_page 502 503 504 =503 /status.html;
        }

        # API endpoints
        location /api {
            proxy_pass http://api;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # Show status page if api is down
            proxy_intercept_errors on;
            error_page 502 503 504 =503 /status.html;
        }

        # Client app (root path)
        location / {
            proxy_pass http://client;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # Show status page if client is down
            proxy_intercept_errors on;
            error_page 502 503 504 =503 /status.html;
        }
    }
}
