Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
f70d9b50 Fixed Admin Vite crash from Ghost's own protocol-redirect middleware
no ref
The url override from the previous commit fixed the browser-facing
CSRF/origin login loop, but broke apps/admin's own vite dev server:
its bootstrap fetch (resolveGhostSiteUrl in
apps/admin/vite-backend-proxy.ts) hits GHOST_URL +
ghost/api/admin/site/ directly at http://localhost:2368, bypassing
Caddy. Once Ghost's url is HTTPS, its url-redirects middleware
(getAdminRedirectUrl) 301s any request it sees as insecure to that
HTTPS url -- real browser traffic through Caddy is fine (Caddy sets
X-Forwarded-Proto: https, so Express's req.secure is true), but vite's
direct fetch has no such header, gets redirected to the public,
GitHub-auth-gated tunnel URL, and crashes trying to parse the login
page HTML as JSON. That crash cascades: Nx tears down the whole
run-many continuous-task group when one task exits non-zero, taking
Ember/Portal/shade/etc. down with it -- confirmed via SSH (added
sshd specifically to get this kind of ground truth instead of
guessing): a live snapshot caught ember as a defunct zombie following
this exact crash trace in the frontend log.
Fixed by routing GHOST_URL through the gateway container instead
(http://ghost-dev-gateway:80/) -- confirmed via direct curl that this
returns a clean 200 with the correct site JSON. Stays on the internal
Docker network (no GitHub auth wall) while still picking up
X-Forwarded-Proto: https from Caddy, so no redirect either. 18a2a922 Changed devcontainer to use the prebuilt ghost-dev image + cached pnpm store
no ref
.github/workflows/devcontainer-build.yml has published
ghcr.io/tryghost/ghost-devcontainer:latest with GHA layer caching on
every relevant main push, but nothing consumed it -- the devcontainer's
ghost-dev service only had a build: block, so every fresh
codespace/container rebuilt the image from scratch (apt-get,
backend-only pnpm install) regardless.
Considered baking the full-workspace pnpm install into a layered image
on top of that base, but compose.devcontainer.yaml bind-mounts the
entire repo over /workspaces/Ghost, which fully shadows anything an
image bakes in at that path with the host's (node_modules-less)
checkout -- the same reason onCreateCommand/postCreateCommand have to
run pnpm install live in the first place. A per-workspace-package
volume mount could work around that but means ~19 entries to maintain
as packages come and go.
Instead: added image: pointing at the published tag (with build.cache_from
so a local rebuild, e.g. after a Dockerfile edit, still reuses those
layers instead of starting cold) and an initializeCommand to pre-pull it
into the local image cache before the container is built or pulled.
Separately, cached pnpm's content-addressable store as a named volume
at /pnpm-store (outside /workspaces/Ghost, so the bind mount can't
shadow it) via npm_config_store_dir. The live pnpm install
onCreateCommand/postCreateCommand still run every time, but against a
warm store they're linking already-fetched content instead of
re-downloading and recompiling native deps (better-sqlite3, sharp,
etc.) from scratch. 18a2a922 Changed devcontainer to use the prebuilt ghost-dev image + cached pnpm store
no ref
.github/workflows/devcontainer-build.yml has published
ghcr.io/tryghost/ghost-devcontainer:latest with GHA layer caching on
every relevant main push, but nothing consumed it -- the devcontainer's
ghost-dev service only had a build: block, so every fresh
codespace/container rebuilt the image from scratch (apt-get,
backend-only pnpm install) regardless.
Considered baking the full-workspace pnpm install into a layered image
on top of that base, but compose.devcontainer.yaml bind-mounts the
entire repo over /workspaces/Ghost, which fully shadows anything an
image bakes in at that path with the host's (node_modules-less)
checkout -- the same reason onCreateCommand/postCreateCommand have to
run pnpm install live in the first place. A per-workspace-package
volume mount could work around that but means ~19 entries to maintain
as packages come and go.
Instead: added image: pointing at the published tag (with build.cache_from
so a local rebuild, e.g. after a Dockerfile edit, still reuses those
layers instead of starting cold) and an initializeCommand to pre-pull it
into the local image cache before the container is built or pulled.
Separately, cached pnpm's content-addressable store as a named volume
at /pnpm-store (outside /workspaces/Ghost, so the bind mount can't
shadow it) via npm_config_store_dir. The live pnpm install
onCreateCommand/postCreateCommand still run every time, but against a
warm store they're linking already-fetched content instead of
re-downloading and recompiling native deps (better-sqlite3, sharp,
etc.) from scratch. 18a2a922 Changed devcontainer to use the prebuilt ghost-dev image + cached pnpm store
no ref
.github/workflows/devcontainer-build.yml has published
ghcr.io/tryghost/ghost-devcontainer:latest with GHA layer caching on
every relevant main push, but nothing consumed it -- the devcontainer's
ghost-dev service only had a build: block, so every fresh
codespace/container rebuilt the image from scratch (apt-get,
backend-only pnpm install) regardless.
Considered baking the full-workspace pnpm install into a layered image
on top of that base, but compose.devcontainer.yaml bind-mounts the
entire repo over /workspaces/Ghost, which fully shadows anything an
image bakes in at that path with the host's (node_modules-less)
checkout -- the same reason onCreateCommand/postCreateCommand have to
run pnpm install live in the first place. A per-workspace-package
volume mount could work around that but means ~19 entries to maintain
as packages come and go.
Instead: added image: pointing at the published tag (with build.cache_from
so a local rebuild, e.g. after a Dockerfile edit, still reuses those
layers instead of starting cold) and an initializeCommand to pre-pull it
into the local image cache before the container is built or pulled.
Separately, cached pnpm's content-addressable store as a named volume
at /pnpm-store (outside /workspaces/Ghost, so the bind mount can't
shadow it) via npm_config_store_dir. The live pnpm install
onCreateCommand/postCreateCommand still run every time, but against a
warm store they're linking already-fetched content instead of
re-downloading and recompiling native deps (better-sqlite3, sharp,
etc.) from scratch. f49dfd37 Removed dead public-app dev-server proxy targets from gateway
no ref
#28970 switched public apps (Portal, Comments UI, Signup Form, Sodo
Search, Announcement Bar, Admin Toolbar) from a proxied vite preview
server to Caddy serving their umd/ build output directly via
file_server, but left the now-unread *_DEV_SERVER env vars in the
gateway Dockerfile and the devcontainer's compose override, and left
their ports forwarded in devcontainer.json. Confirmed via grep that the
Caddyfile only ever reads GHOST_BACKEND, ADMIN_DEV_SERVER,
ADMIN_LIVE_RELOAD_SERVER, LEXICAL_DEV_SERVER, ANALYTICS_PROXY_TARGET,
and ACTIVITYPUB_PROXY_TARGET. Fixing at the Dockerfile (shared by host
and devcontainer builds) removes the need to keep re-declaring dead
vars in the devcontainer overlay, and stops Codespaces from showing
five phantom ports nothing ever binds.