This commit completes Phase 0 of Approach C: the CCP template/env/static
files now produce output structurally byte-identical to canonical
docker-compose.prod.yml + .env.example. Verified by rendering against
marcelle, linda, and pia and diffing against their actual files — all
three show only the 30-line CCP-tenant header comment differing,
zero service/env-var structural differences.
Changes:
- templates/docker-compose.yml.hbs: reverted {{imageTag}} substitutions
back to ${IMAGE_TAG:-latest} so the compose template is now byte-
equivalent to docker-compose.prod.yml (modulo header). CCP controls
per-instance image tag selection via the rendered .env's IMAGE_TAG,
which compose-up picks up at runtime. This single-source-of-truth
via env-substitution matches install.sh tenants exactly.
- templates/env.hbs: rewritten as a near-mirror of .env.example. Adds
27 missing keys (IMAGE_TAG, GITEA_REGISTRY, COMPOSE_PROFILES,
ENABLE_CCP_AGENT, GITEA_ADMIN_*, ENABLE_HLS_TRANSCODE, TZ, etc.)
plus 15 CCP-specific extras (embed ports, dev-mode helpers, etc.).
All 145 compose-template env-var references are now covered.
- templates/nginx/nginx.conf: synced from canonical. Includes recent
security additions: redacted access-log format for token/secret
query params, rate-limit zones (api_global, api_auth, upload),
conditional HSTS via X-Forwarded-Proto map.
- api/scripts/render-for-instance.ts (new): one-off CLI that loads
an Instance row, decrypts secrets if present (or uses empty object
for isRegistered=true tenants), and calls renderAllTemplates() to
a scratch dir. Used in Phase 0.4 to verify the template-vs-prod
contract per tenant.
Usage:
docker compose exec ccp-api npx tsx scripts/render-for-instance.ts \
--slug changemakerlite
Phase 0 acceptance gate met:
- marcelle (release v2.10.2 install): 30-line diff, header-only
- linda (release v2.9.14 install): 30-line diff, header-only
- pia (release v2.9.10 install): 30-line diff, header-only
- env.hbs key coverage: 0 missing vs marcelle's .env
Next phases unblocked:
- Phase 1: add Instance.imageTag column (Prisma migration)
- Phase 2: pre-flight diff endpoint
- Phase 3: startReleaseUpgrade runner
- Phase 4: routes + schemas
- Phase 5: CCP UI "Upgrade to Release" button
- Phase 6: E2E test on marcelle (v2.10.2 -> v2.10.3)
Bunker Admin
Drop the custom Dockerfile.code-server that bundled Claude Code CLI,
Python/MkDocs tooling, and build-essential on top of codercom base.
Switch to the already-mirrored linuxserver/code-server image instead.
- Both compose files: use code-server:latest, LinuxServer env vars
(PUID/PGID/DEFAULT_WORKSPACE), port 8443, /config mount layout
- Nginx configs + templates: proxy to :8443 instead of :8080
- API env default: CODE_SERVER_URL updated to :8443
- build-and-push.sh: remove --include-code-server flag
- upgrade.sh: remove code-server conditional rebuild + registry fallback
- install.sh: add --ignore-pull-failures for optional missing images
- .env.example, CCP templates, bunker-ops template: updated
Bunker Admin
All 13 nginx embed proxy ports (8881-8895) are now driven by environment
variables instead of being hardcoded. This prevents port conflicts when
running multiple Changemaker instances on the same host.
Chain: .env → docker-compose port mappings → nginx container env →
entrypoint.sh envsubst → services.conf.template listen directives →
API /services/config endpoint → frontend buildServiceUrl().
Existing deployments are unaffected (all vars default to current values).
Bunker Admin
Closes 12 template drift gaps between the Control Panel templates and
production configs. New instances now provision with full monitoring
(alerts fire properly), correct Gitea DB type (postgres not mysql),
social sharing previews (OG meta bot routes), Excalidraw subdomain
routing, docker-socket-proxy for Homepage, and complete Grafana/
Alertmanager/Prometheus config copying.
Key changes:
- Rewrite Prometheus template: add alerting, rule_files, 5 scrape jobs
- Add cAdvisor, node-exporter, redis-exporter, gotify, docker-socket-proxy
- Fix Gitea env from mysql to postgres to match docker-compose
- Add OG bot detection + rewrite routes for campaigns/pages/gallery
- Add Excalidraw nginx server block + Pangolin draw subdomain
- Add embed port to discovery portConfig + emailTestMode to registration
- Copy alerts.yml, alertmanager.yml, Grafana dashboards to templates
- Add Listmonk proxy port and upgrade volume to API service
Bunker Admin
New instances provisioned via CCP were missing env vars for video analytics,
geocoding config, Listmonk SMTP, Gitea comments, Overpass/area import,
monitoring ports, Bunker Ops, and other features added since the template
was last updated.
Bunker Admin