# Access log in the platform logging contract (same shape as the backend # template's pino-http lines), so Fluent Bit turns every key into a Kibana # field. $app_name / $git_sha come from conf.d/service-vars.conf, written at # container start by docker-entrypoint.d/10-config.sh. map $status $log_level { ~^5 error; default info; } # Echo X-Request-Id if the caller sent one, else nginx's own id. map $http_x_request_id $req_id { "" $request_id; default $http_x_request_id; } # $request_time is seconds ("0.002"); the contract's responseTime is integer ms. map $request_time $response_ms { "~^0\.0*(?\d+)$" $ms; "~^(?[1-9]\d*)\.(?\d{3})$" $s$ms; default 0; } log_format contract escape=json '{"level":"$log_level","time":"$time_iso8601","service":"$app_name",' '"version":"$git_sha","req":{"id":"$req_id","method":"$request_method",' '"url":"$request_uri"},"res":{"statusCode":$status},' '"responseTime":$response_ms,"msg":"request completed"}'; server { listen 8080; server_name _; root /usr/share/nginx/html; access_log /dev/stdout contract; # Liveness/readiness for k8s probes. location = /healthz { access_log off; default_type text/plain; return 200 "ok\n"; } # Runtime config, written at container start; never cache. location = /config.js { add_header Cache-Control "no-store" always; } # Hashed build assets: cache forever; a missing asset is a real 404. location /assets/ { add_header Cache-Control "public, max-age=31536000, immutable" always; try_files $uri =404; } location = /index.html { add_header Cache-Control "no-cache" always; } # SPA fallback: unknown paths get index.html; the router handles them. location / { try_files $uri /index.html; } }