fix(nginx): serve /serverkit-vendor/*.mjs shims as text/javascript

Stock nginx (1.18-1.24 on Debian/Ubuntu) has no `.mjs` entry in mime.types,
so the runtime-extension vendor shims the import map points at came back as
application/octet-stream. Browsers refuse to execute an ES module with that
type, so every runtime-loaded extension (WordPress, Git, Mail, Fail2ban, ...)
failed on fresh installs with "Failed to fetch dynamically imported module:
blob:..." (Chrome) or "'application/octet-stream' is not a valid JavaScript
MIME type" (Safari).

Add a location block to the shipped vhosts (and the container frontend
config) that forces text/javascript for /serverkit-vendor/*.mjs. The regex is
anchored to that folder: a bare `\.mjs$` would also capture the
/api/v1/plugins/<slug>/assets/dist/index.mjs route and 404 every bundle.
update.sh already re-copies these vhosts, so existing installs pick it up on
their next update.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWc84WDsWR7M55Mn7qtpie
This commit is contained in:
Juan DenisandClaude Fable 5.1 committed 2026-09-08 00:25:25 -04:00
1 parent 1ace946ab9
commit bbce447e85
4 files changed
+58

No files matched your search

+5
View File
@@ -24,6 +24,11 @@ Changes after 1.9.28 on the development branch.
### Fixed
- Serve the runtime-extension vendor shims (`/serverkit-vendor/*.mjs`) as
`text/javascript` from the shipped nginx vhosts. Stock nginx has no `.mjs`
MIME entry and returned `application/octet-stream`, so every runtime-loaded
extension (WordPress, Git, Mail, Fail2ban, ...) failed with "Failed to fetch
dynamically imported module: blob:..." on fresh installs.
- Evaluate fleet alert thresholds every minute and send opened/resolved alerts
to administrators through the notification bus.
- Preserve memory, disk and network measurements from agent heartbeats through
+15
View File
@@ -57,6 +57,21 @@ server {
proxy_read_timeout 7d;
}
# Runtime-extension vendor shims (/serverkit-vendor/*.mjs). nginx builds
# without an `.mjs` MIME entry serve application/octet-stream, which the
# browser refuses to import as an ES module and every runtime-loaded
# extension fails with "Failed to fetch dynamically imported module".
# Force the type; the shims are not hashed, so they must revalidate.
# Anchored to the shim folder: a bare `\.mjs$` regex would also capture
# /api/v1/plugins/<slug>/assets/dist/index.mjs (regex locations beat the
# /api prefix block) and 404 every extension bundle instead.
location ~* ^/serverkit-vendor/.+\.mjs$ {
types { }
default_type text/javascript;
try_files $uri =404;
expires -1;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
@@ -43,6 +43,25 @@ server {
add_header Cache-Control "public, immutable";
}
# Runtime-extension vendor shims (/serverkit-vendor/*.mjs). The import map in
# index.html resolves react / react-dom / react-router-dom / i18next /
# serverkit-sdk to these, and the browser refuses to run an ES module served
# with a non-JavaScript MIME type. Stock nginx (1.18-1.24, Debian/Ubuntu
# mime.types) has no `.mjs` entry and falls back to application/octet-stream,
# which surfaces as "Failed to fetch dynamically imported module: blob:..."
# (Chrome) or "'application/octet-stream' is not a valid JavaScript MIME
# type" (Safari) on EVERY runtime-loaded extension. Force the type here
# instead of editing the system mime.types. Not hashed, so revalidate.
# Anchored to the shim folder: a bare `\.mjs$` regex would also capture
# /api/v1/plugins/<slug>/assets/dist/index.mjs (regex locations beat the
# /api prefix block) and 404 every extension bundle instead.
location ~* ^/serverkit-vendor/.+\.mjs$ {
types { }
default_type text/javascript;
try_files $uri =404;
expires -1;
}
location / {
# expires -1 → Cache-Control: no-cache — the entrypoint must
# revalidate every load or a cached index.html references hashed
+19
View File
@@ -123,6 +123,25 @@ server {
add_header Cache-Control "public, immutable";
}
# Runtime-extension vendor shims (/serverkit-vendor/*.mjs). The import map in
# index.html resolves react / react-dom / react-router-dom / i18next /
# serverkit-sdk to these, and the browser refuses to run an ES module served
# with a non-JavaScript MIME type. Stock nginx (1.18-1.24, Debian/Ubuntu
# mime.types) has no `.mjs` entry and falls back to application/octet-stream,
# which surfaces as "Failed to fetch dynamically imported module: blob:..."
# (Chrome) or "'application/octet-stream' is not a valid JavaScript MIME
# type" (Safari) on EVERY runtime-loaded extension. Force the type here
# instead of editing the system mime.types. Not hashed, so revalidate.
# Anchored to the shim folder: a bare `\.mjs$` regex would also capture
# /api/v1/plugins/<slug>/assets/dist/index.mjs (regex locations beat the
# /api prefix block) and 404 every extension bundle instead.
location ~* ^/serverkit-vendor/.+\.mjs$ {
types { }
default_type text/javascript;
try_files $uri =404;
expires -1;
}
location / {
# expires -1 (not add_header): emits Cache-Control: no-cache without
# discarding the server-level security headers, and forces every load