From 9b7fd15ca108156173545e50b9a12cf695df7131 Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 8 May 2026 16:23:11 +0200 Subject: [PATCH] =?UTF-8?q?Drop=20nested=20location=20blocks=20from=20ngin?= =?UTF-8?q?x=20vhost=20overrides=20=E2=80=94=20they=20404=20assets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first version of vhost.d/_location nested four `location { … }` blocks (for /_astro/, images, /sw.js, /llms.txt) inside the proxy's generated `location / { … }` to set Cache-Control. nginx accepts the syntax, but a nested location with no `proxy_pass` directive falls through to filesystem root and 404s the asset — which is why CSS / JS / images were missing on the live site even though the HTML loaded fine. Astro already emits sensible Cache-Control on hashed _astro bundles, so we don't need the proxy to set them. Removed all four nested blocks; the vhost.d files now only carry proxy headers, gzip, and security headers, all of which are valid inside a location {} block without proxy_pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../vhost.d/nibiru-framework.com_location | 50 +++++-------------- .../vhost.d/www.nibiru-framework.com_location | 34 +++---------- 2 files changed, 19 insertions(+), 65 deletions(-) diff --git a/docs/nginx/vhost.d/nibiru-framework.com_location b/docs/nginx/vhost.d/nibiru-framework.com_location index 9def230..30b885c 100644 --- a/docs/nginx/vhost.d/nibiru-framework.com_location +++ b/docs/nginx/vhost.d/nibiru-framework.com_location @@ -1,20 +1,21 @@ # ============================================================================= # nginx vhost-location override for nibiru-framework.com (apex) # -# Picked up by jwilder/nginx-proxy when this file is mounted into the proxy -# container at /etc/nginx/vhost.d/_location. +# Picked up by jwilder/nginx-proxy when this file lives in the proxy's +# /etc/nginx/vhost.d/ at _location. The contents are inlined inside +# the generated `location / { … }` block. # -# Pattern: -# -v /srv/nginx-proxy/vhost.d:/etc/nginx/vhost.d:ro -# on the proxy, then `cp docs/nginx/vhost.d/* /srv/nginx-proxy/vhost.d/` -# on the host (or symlink). -# -# Each rule is scoped to the location { } block of the generated server, -# so we DON'T re-declare server, listen, server_name, ssl_*, etc. +# IMPORTANT: do NOT add nested `location { … }` blocks here. nginx allows +# the syntax, but a nested location with no `proxy_pass` falls through to +# filesystem root and 404s the asset. Earlier versions of this file did +# exactly that for /_astro/ + images + /sw.js, which is why CSS/JS/images +# weren't loading on the live site. Cache-Control for hashed bundles is +# already set by Astro itself; the proxy doesn't need to second-guess it. # ============================================================================= # Trust the X-Forwarded-* headers nginx-proxy already sets, so the upstream -# Astro server sees the real client IP and scheme. +# Astro server sees the real client IP and scheme. (nginx-proxy sets these +# in its default config too — restating here is belt-and-braces.) proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; @@ -31,8 +32,7 @@ proxy_send_timeout 300s; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; -# Body size — large enough for the LoRA corpus uploads (cap is generous; -# tighten if abuse becomes a concern). +# Body size — generous; tighten if abuse becomes a concern. client_max_body_size 25m; # Compression — Astro emits text-heavy assets that gzip well. @@ -61,29 +61,3 @@ add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; - -# Cache hashed Astro/Starlight assets aggressively (1 year, immutable). -# The dev server hashes filenames via Vite, so cache-busting is automatic. -location ~* ^/_astro/ { - expires 1y; - add_header Cache-Control "public, immutable, max-age=31536000"; -} - -# Static images / fonts / pwa manifest — long cache, mutable so a deploy -# can invalidate by changing the file. -location ~* \.(png|jpg|jpeg|gif|webp|avif|ico|svg|woff|woff2|ttf|otf)$ { - expires 30d; - add_header Cache-Control "public, max-age=2592000"; -} - -# Service worker MUST NOT be cached — needed for PWA updates to land. -location = /sw.js { - expires off; - add_header Cache-Control "no-store, no-cache, must-revalidate"; -} - -# llms.txt is small; let it cache for a day so AI crawlers don't hammer it. -location = /llms.txt { - expires 1d; - add_header Cache-Control "public, max-age=86400"; -} diff --git a/docs/nginx/vhost.d/www.nibiru-framework.com_location b/docs/nginx/vhost.d/www.nibiru-framework.com_location index d84430d..390cc52 100644 --- a/docs/nginx/vhost.d/www.nibiru-framework.com_location +++ b/docs/nginx/vhost.d/www.nibiru-framework.com_location @@ -1,9 +1,13 @@ # ============================================================================= # nginx vhost-location override for www.nibiru-framework.com # -# Same hardening + caching rules as the apex (nibiru-framework.com_location). -# Kept as a separate file so the proxy applies them per-vhost — the www and -# apex containers each get their own server block in the generated config. +# Same hardening + headers as the apex (nibiru-framework.com_location). +# Kept as a separate file so the proxy applies them per-vhost. +# +# IMPORTANT: do NOT add nested `location { … }` blocks here. nginx allows +# the syntax, but a nested location with no `proxy_pass` falls through to +# filesystem root and 404s the asset. Astro already sets sane +# Cache-Control on hashed bundles; the proxy doesn't need to second-guess. # # If you ever decide to redirect www → apex (SEO canonical-URL pattern) # instead of serving from a second container, replace this file's contents @@ -57,27 +61,3 @@ add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; - -# Hashed Astro/Starlight assets — 1 year, immutable. -location ~* ^/_astro/ { - expires 1y; - add_header Cache-Control "public, immutable, max-age=31536000"; -} - -# Static images / fonts — 30 days. -location ~* \.(png|jpg|jpeg|gif|webp|avif|ico|svg|woff|woff2|ttf|otf)$ { - expires 30d; - add_header Cache-Control "public, max-age=2592000"; -} - -# Service worker — never cache. -location = /sw.js { - expires off; - add_header Cache-Control "no-store, no-cache, must-revalidate"; -} - -# llms.txt — short cache for AI crawlers. -location = /llms.txt { - expires 1d; - add_header Cache-Control "public, max-age=86400"; -}