# Production vhost for ui-dashboard.gnerim.ru.
# Symlink into /etc/nginx/sites-enabled/ and reload nginx.
# TLS certs assumed to exist via certbot (separate process).
#
# Cache zone `flights_api` is declared in /etc/nginx/conf.d/flights-api-cache.conf
# (proxy_cache_path lives at http context, can't be in server {}).

server {
    listen 80;
    server_name ui-dashboard.gnerim.ru;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name ui-dashboard.gnerim.ru;

    ssl_certificate     /etc/letsencrypt/live/ui-dashboard.gnerim.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ui-dashboard.gnerim.ru/privkey.pem;

    auth_basic           "ui-dashboard";
    auth_basic_user_file /etc/nginx/htpasswd/ui-dashboard;

    # SSR app on loopback (container bound to 127.0.0.1:3002)
    location / {
        proxy_pass http://127.0.0.1:3002;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;

        # Long-poll friendliness for any future SignalR / SSE
        proxy_read_timeout 300s;
        proxy_buffering    off;
    }

    # API proxy — bypass basic auth (gates HTML, not API).
    # Routed via the flights-tim-tunnel.service systemd unit (see
    # deployment/systemd/flights-tim-tunnel.service): 127.0.0.1:8443 is an
    # ssh -L tunnel to webzavod which exits via ppp0 with a corp-VPN source IP
    # the upstream WAF whitelists. SNI/Host are set explicitly because the
    # TCP target is loopback rather than the real hostname.
    #
    # Cached to absorb e2e bursts that would otherwise trip the upstream
    # WAF rate limit. Only GET/HEAD are cached (default proxy_cache_methods).
    #
    # Dictionary endpoints (cities, airports, countries, world_regions) are
    # essentially static — pre-warmed by CI and held for 6h. Other /api/*
    # paths are dynamic queries; 1m is a reasonable freshness budget.
    location /api/dictionary/ {
        auth_basic off;
        proxy_pass         https://127.0.0.1:8443;
        proxy_set_header   Host flights.test.aeroflot.ru;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_ssl_server_name on;
        proxy_ssl_name        flights.test.aeroflot.ru;

        proxy_cache            flights_api;
        proxy_cache_key        "$scheme$host$request_uri";
        proxy_cache_valid      200 6h;
        proxy_cache_valid      404 5m;
        proxy_cache_lock       on;
        proxy_cache_use_stale  error timeout updating http_403 http_500 http_502 http_503 http_504;
        # Allow CI to force a re-fetch when the cache is suspected stale
        # (Cache-Control: no-cache from client → bypass on this hit, then
        # store the fresh response). Already enabled below for /api/.
        proxy_cache_bypass     $http_cache_control;
        # Refuse to cache the WAF block page (text/html). $no_cache_html
        # is set in conf.d/flights-api-cache.conf based on upstream's
        # Content-Type. Without this, a single rate-limited fetch
        # poisoned the cache for 6h.
        proxy_no_cache         $no_cache_html;
        add_header             X-Cache-Status $upstream_cache_status always;
    }

    location /api/ {
        auth_basic off;
        proxy_pass         https://127.0.0.1:8443;
        proxy_set_header   Host flights.test.aeroflot.ru;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_ssl_server_name on;
        proxy_ssl_name        flights.test.aeroflot.ru;

        proxy_cache            flights_api;
        proxy_cache_key        "$scheme$host$request_uri";
        proxy_cache_valid      200 1m;
        proxy_cache_valid      404 30s;
        proxy_cache_lock       on;
        proxy_cache_use_stale  error timeout updating http_403 http_500 http_502 http_503 http_504;
        proxy_cache_bypass     $http_cache_control;
        # Same rationale as /api/dictionary/ — refuse to cache the WAF
        # block page (text/html). Prevents `proxy_cache_use_stale` from
        # later serving that HTML as a stale 200 when the WAF returns 403
        # on a fresh fetch.
        proxy_no_cache         $no_cache_html;
        add_header             X-Cache-Status $upstream_cache_status always;
    }

    # Map tiles — heavily cacheable (tile data rarely changes for an area).
    # Longer TTL than /api/ since these are essentially static.
    location /map/api/ {
        auth_basic off;
        proxy_pass         https://127.0.0.1:8443;
        proxy_set_header   Host flights.test.aeroflot.ru;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_ssl_server_name on;
        proxy_ssl_name        flights.test.aeroflot.ru;

        proxy_cache            flights_api;
        proxy_cache_key        "$scheme$host$request_uri";
        proxy_cache_valid      200 24h;
        proxy_cache_valid      404 5m;
        proxy_cache_lock       on;
        proxy_cache_use_stale  error timeout updating http_403 http_500 http_502 http_503 http_504;
        add_header             X-Cache-Status $upstream_cache_status always;
    }
}
