# Managed by Ansible (roles/web-static). Do not edit by hand. # Access logs: JSON to stdout for Alloy → Loki (see dta_webapp/deploy/nginx-logging.conf). log_format observability escape=json '{' '"timestamp":"$time_iso8601",' '"level":"INFO",' '"service":"$obs_app",' '"app":"$obs_app",' '"env":"$obs_env",' '"message":"$request",' '"method":"$request_method",' '"status":$status,' '"bytes":$body_bytes_sent,' '"request_time":$request_time,' '"uri":"$request_uri",' '"remote_addr":"$remote_addr",' '"user_agent":"$http_user_agent"' '}'; {% for a in _static_apps %} server { listen {{ a.port }}; server_name _; set $obs_app "{{ a.name }}"; set $obs_env "{{ a.env }}"; access_log /dev/stdout observability; error_log /dev/stderr warn; root {{ (app_catalog[a.name].webroot_pattern | default(web_static_root ~ '/{env}_' ~ a.name)) | replace('{env}', a.env) }}; index index.html; {%- set api_backend_name = app_catalog[a.name].api_backend | default('') %} {%- if api_backend_name %} {%- set api_proxy_prefix = app_catalog[a.name].api_proxy_prefix | default('/api/') %} {%- set api_match = namespace(port=0, ok=false) %} {%- for item in host_apps | default([]) %} {%- if item.name == api_backend_name and item.env == a.env and (item.enabled | default(true)) %} {%- set api_match.port = item.port %} {%- set api_match.ok = true %} {%- endif %} {%- endfor %} {%- if api_match.ok %} {%- set api_host = (app_catalog[api_backend_name].public_hosts | default({}))[a.env] | default('') %} # Finance webhooks (Stripe) arrive on the public product host. The SPA # try_files fallback is a static file and returns 405 for POST. location {{ api_proxy_prefix }} { proxy_pass http://host.docker.internal:{{ api_match.port }}; proxy_http_version 1.1; proxy_set_header Host {{ api_host if api_host else '$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 60s; client_max_body_size 2m; } {%- endif %} {%- endif %} {% if a.name == 'chat_web_app' and a.env == 'prod' %} # HeyCatch short links. # f Facebook, h Threads, i Instagram, l LinkedIn, r Reddit, x X, y YouTube. # Relative Location: this vhost listens on the container port. An absolute # redirect would publish that port (hesychia.ai:8082). location ~ ^/([a-z0-9])/?$ { absolute_redirect off; return 302 /?utm_source=heycatch&utm_campaign=$1; } {% endif %} {% if app_catalog[a.name].error_page_404 | default('') %} error_page 404 {{ app_catalog[a.name].error_page_404 }}; location / { try_files $uri $uri/ =404; } {% else %} location / { try_files $uri $uri/ /index.html; } {% endif %} location ~* \.(?:js|css|woff2?|png|jpg|jpeg|gif|svg|ico)$ { expires 7d; add_header Cache-Control "public"; } } {% endfor %}