# PegaProx nginx reverse proxy config
# NS: Mar 2026
#
# Usage:
#   1. Enable "Behind Reverse Proxy" in PegaProx Settings > Server
#      (this disables built-in SSL and binds to 127.0.0.1 only)
#   2. Copy this file to /etc/nginx/sites-available/pegaprox
#   3. Edit server_name and ssl_certificate/ssl_certificate_key
#   4. ln -s /etc/nginx/sites-available/pegaprox /etc/nginx/sites-enabled/
#   5. nginx -t && systemctl reload nginx
#
# MK: If PegaProx runs on a different host, change 127.0.0.1 to the actual IP
#     and add that IP to "Trusted Proxies" in PegaProx settings.
#
# Ports: VNC = main_port + 1, SSH = main_port + 2
# Default: 5000 (main), 5001 (VNC console), 5002 (SSH console)
# If you changed the main port, adjust VNC/SSH ports accordingly.

# required for websocket upgrade — must be in http context, before server block
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream pegaprox_app {
    server 127.0.0.1:5000;
}

upstream pegaprox_vnc {
    server 127.0.0.1:5001;  # main_port + 1
}

upstream pegaprox_ssh {
    server 127.0.0.1:5002;  # main_port + 2
}

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

server {
    listen 443 ssl;
    http2 on;
    server_name pegaprox.example.com;

    ssl_certificate     /etc/ssl/certs/pegaprox.pem;
    ssl_certificate_key /etc/ssl/private/pegaprox.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    # LW: must match PEGAPROX_MAX_UPLOAD_SIZE (default 100GB for ISO uploads)
    client_max_body_size 100g;

    # timeouts - some PVE operations take a while
    proxy_connect_timeout 10;
    proxy_read_timeout    3600;
    proxy_send_timeout    3600;

    # gzip - PegaProx has flask-compress but nginx is faster
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;
    gzip_min_length 1000;

    # main app (API + UI + flask-sock websockets)
    location / {
        proxy_pass http://pegaprox_app;

        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-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;

        # websocket upgrade for flask-sock routes (/api/ws/*, /api/clusters/*/vncwebsocket, etc.)
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

    # SSE endpoint - buffering MUST be off or live updates won't work
    location /api/sse/ {
        proxy_pass http://pegaprox_app;

        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-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_buffering off;
        proxy_cache off;
        proxy_read_timeout 86400;  # keep SSE alive for 24h
        chunked_transfer_encoding off;
    }

    # VNC console websocket (separate asyncio server on port+1)
    # NS: regex matches actual API path, not /vnc/ prefix
    location ~ ^/api/clusters/.*/vncwebsocket {
        proxy_pass http://pegaprox_vnc;

        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $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_read_timeout 3600;
    }

    # SSH console websocket (separate asyncio server on port+2)
    location ~ ^/api/clusters/.*/shellws {
        proxy_pass http://pegaprox_ssh;

        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $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_read_timeout 3600;
    }
}
