diff --git a/fly/nginx.conf b/fly/nginx.conf index db02a21..ca4eb11 100644 --- a/fly/nginx.conf +++ b/fly/nginx.conf @@ -46,18 +46,32 @@ http { proxy_cache_path /tmp/cache levels=1:2 keys_zone=services:10m max_size=200m inactive=24h; - # MagicDNS resolver — using a variable in proxy_pass defers upstream DNS - # resolution to request time (not config time). Results are cached for - # 30s per worker to avoid per-request DNS lookups. + # WebSocket-aware Connection header. Only send "upgrade" when the client + # actually requests a protocol switch; otherwise empty string to preserve + # upstream keepalive connections. + map $http_upgrade $connection_upgrade { + default ""; + websocket upgrade; + } + + # --- Upstream pools with keepalive --- + # DNS is resolved once at config load via MagicDNS. If Tailscale Ingress + # pods get new IPs (restart, reschedule), run `mise run fly-reload` to + # re-resolve. A Grafana alert fires when upstreams are unreachable. resolver 100.100.100.100 valid=30s; resolver_timeout 5s; - # WebSocket-aware Connection header. Only send "upgrade" when the client - # actually requests a protocol switch; otherwise "close" (the HTTP/1.1 - # default when keepalive pooling is not available). - map $http_upgrade $connection_upgrade { - default close; - websocket upgrade; + upstream forge_backend { + server forge.tail8d86e.ts.net:443; + keepalive 8; + } + upstream docs_backend { + server docs.tail8d86e.ts.net:443; + keepalive 4; + } + upstream cv_backend { + server cv.tail8d86e.ts.net:443; + keepalive 4; } # --- docs.eblu.me (static site) --- @@ -76,12 +90,14 @@ http { internal; } location / { - set $upstream_docs https://docs.tail8d86e.ts.net; - proxy_pass $upstream_docs$request_uri; + proxy_pass https://docs_backend$request_uri; proxy_ssl_verify off; proxy_ssl_server_name on; proxy_intercept_errors on; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + # Cache aggressively — static site only. # Do NOT use these settings for dynamic services. proxy_cache services; @@ -116,12 +132,14 @@ http { } location / { - set $upstream_cv https://cv.tail8d86e.ts.net; - proxy_pass $upstream_cv$request_uri; + proxy_pass https://cv_backend$request_uri; proxy_ssl_verify off; proxy_ssl_server_name on; proxy_intercept_errors on; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_cache services; proxy_cache_valid 200 1d; proxy_cache_valid 404 1m; @@ -187,8 +205,7 @@ http { location ~ ^/user/(login|sign_up|forgot_password) { limit_req zone=forge_auth burst=5 nodelay; - set $upstream_forge https://forge.tail8d86e.ts.net; - proxy_pass $upstream_forge$request_uri; + proxy_pass https://forge_backend$request_uri; proxy_ssl_verify off; proxy_ssl_server_name on; proxy_intercept_errors on; @@ -206,11 +223,13 @@ http { # Cache release artifact downloads — immutable files keyed by tag+filename. # Avoids hammering Forgejo when crawlers or users re-download the same asset. location ~ ^/[^/]+/[^/]+/releases/download/ { - set $upstream_forge_releases https://forge.tail8d86e.ts.net; - proxy_pass $upstream_forge_releases$request_uri; + proxy_pass https://forge_backend$request_uri; proxy_ssl_verify off; proxy_ssl_server_name on; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_cache services; proxy_cache_valid 200 7d; proxy_cache_key $host$uri; @@ -226,11 +245,13 @@ http { # Selectively cache static assets only location ~* \.(css|js|png|jpg|svg|woff2?)$ { - set $upstream_forge_static https://forge.tail8d86e.ts.net; - proxy_pass $upstream_forge_static$request_uri; + proxy_pass https://forge_backend$request_uri; proxy_ssl_verify off; proxy_ssl_server_name on; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_cache services; proxy_cache_valid 200 7d; proxy_cache_key $host$uri; @@ -240,8 +261,7 @@ http { } location / { - set $upstream_forge https://forge.tail8d86e.ts.net; - proxy_pass $upstream_forge$request_uri; + proxy_pass https://forge_backend$request_uri; proxy_ssl_verify off; proxy_ssl_server_name on; proxy_intercept_errors on; diff --git a/mise-tasks/fly-reload b/mise-tasks/fly-reload new file mode 100755 index 0000000..34806c5 --- /dev/null +++ b/mise-tasks/fly-reload @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +#MISE description="Reload Fly.io proxy nginx config (re-resolves upstream DNS)" + +set -euo pipefail + +export FLY_API_TOKEN +FLY_API_TOKEN="$(op read 'op://blumeops/fly.io admin/add more/deploy-token')" + +# SSH into the Fly machine and send nginx a reload signal. +# This re-resolves upstream DNS without a full redeploy. +APP="blumeops-proxy" +MACHINE_ID=$(fly machines list -a "$APP" --json | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['id'])") + +echo "Reloading nginx on machine $MACHINE_ID..." +fly ssh console -a "$APP" -C "nginx -s reload" +echo "Done. Upstream DNS re-resolved."