From fbec70069f126333c1150d5d35aa95b8699638be Mon Sep 17 00:00:00 2001 From: archipelago Date: Sun, 2 Aug 2026 23:40:34 -0400 Subject: [PATCH] fix(nginx): serve AIUI's absolute /assets/ requests from aiui/assets/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Taking over a parked item from the app-UI work. AIUI's built index.html emits ABSOLUTE /assets/ paths, so the browser asks for /assets/index-BC2fBBaW.js. That lands in the MAIN UI's assets dir, where it does not exist — the real files are in aiui/assets/. Both of AIUI's two entry assets 404'd, so the embedded sidebar loaded nothing. The config already contained a /aiui-assets/ location whose comment names this exact problem ("AIUI may reference /assets/ without /aiui/ prefix"), but it only catches requests to /aiui-assets/, a path AIUI never asks for. It described the bug without fixing it. /assets/ now falls back to a named location that rewrites into aiui/assets/ and 404s from there. A fallback rather than copying the two files up one level, because a frontend deploy replaces web-ui wholesale — update.rs preserves the aiui/ DIRECTORY, not copies made into assets/ — so a copy is erased by the very next deploy while this survives one. Both server blocks (HTTP and HTTPS) are patched; named locations are per-server, so each needs its own. Verified on archi-dev-box after reload: /assets/index-BC2fBBaW.js 200, 305256 bytes, application/javascript /assets/index-BJkaQ2c4.css 200, 150716 bytes, text/css /assets/does-not-exist.js 404 (the fallback is not over-broad) /assets/index--lyLAgu1.js 200 (real main-UI chunks still come from /assets/vendor-CmYeCqL_.js 200 the main dir — try_files hits them /assets/index-CiMaoNII.css 200 before the fallback is consulted) / /aiui/ /health 200 Hash collision between the two builds is not a concern: Vite hashes are content-derived, and any main-UI asset that exists is served by try_files before the fallback runs. Noted while doing this, not fixed here: the node's own /etc/nginx/sites-enabled/archipelago is 378 lines BEHIND this repo file (984 vs 1362) — it predates the IPv6 listener and the @asset_missing no-store handling, among others. The node was patched minimally in its own shape rather than overwritten, since a wholesale copy of a config this diverged is not a safe unattended action. Co-Authored-By: Claude Opus 5 (1M context) --- image-recipe/configs/nginx-archipelago.conf | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/image-recipe/configs/nginx-archipelago.conf b/image-recipe/configs/nginx-archipelago.conf index c908eb82..72e55eeb 100644 --- a/image-recipe/configs/nginx-archipelago.conf +++ b/image-recipe/configs/nginx-archipelago.conf @@ -125,6 +125,23 @@ server { # `always` the header applies only to 2xx/3xx; 404s are routed to a # named location that marks them no-store so the browser retries. location /assets/ { + try_files $uri @aiui_assets; + add_header Cache-Control "public, max-age=31536000, immutable"; + } + # AIUI's built index.html emits ABSOLUTE /assets/ paths, so they + # land here, in the MAIN UI's assets dir, where they do not exist — the + # real files are in aiui/assets/. The nearby /aiui-assets/ alias names this + # exact problem in its comment but only catches a path AIUI never requests, + # so it never fixed it. + # + # A fallback rather than copying the files up one level: a frontend deploy + # replaces web-ui wholesale (update.rs preserves the aiui/ directory itself, + # not copies made into assets/), so a copy is erased by the very next deploy + # while this survives. Hash collision with a real main-UI asset is not a + # concern — Vite hashes are content-derived, and a main asset that exists is + # served by try_files before this is ever consulted. + location @aiui_assets { + rewrite ^/assets/(.*)$ /aiui/assets/$1 break; try_files $uri =404; add_header Cache-Control "public, max-age=31536000, immutable"; error_page 404 = @asset_missing; @@ -985,6 +1002,23 @@ server { # HTTP block). No `always` on the immutable header: a transient 404 must # not be cached for a year — 404s go to @asset_missing (no-store) instead. location /assets/ { + try_files $uri @aiui_assets; + add_header Cache-Control "public, max-age=31536000, immutable"; + } + # AIUI's built index.html emits ABSOLUTE /assets/ paths, so they + # land here, in the MAIN UI's assets dir, where they do not exist — the + # real files are in aiui/assets/. The nearby /aiui-assets/ alias names this + # exact problem in its comment but only catches a path AIUI never requests, + # so it never fixed it. + # + # A fallback rather than copying the files up one level: a frontend deploy + # replaces web-ui wholesale (update.rs preserves the aiui/ directory itself, + # not copies made into assets/), so a copy is erased by the very next deploy + # while this survives. Hash collision with a real main-UI asset is not a + # concern — Vite hashes are content-derived, and a main asset that exists is + # served by try_files before this is ever consulted. + location @aiui_assets { + rewrite ^/assets/(.*)$ /aiui/assets/$1 break; try_files $uri =404; add_header Cache-Control "public, max-age=31536000, immutable"; error_page 404 = @asset_missing;