4038fe74 | docs: add self-host docker-compose spec and plan | Lef | 2026-05-04 | ↗ GitHub |
2a9edade | feat: add generate-secrets.sh for docker-compose self-host stack | Lef | 2026-05-04 | ↗ GitHub |
6fe97e23 | fix: harden generate-secrets.sh permissions, openssl guard, CRLF | Lef | 2026-05-04 | ↗ GitHub |
c027e2e6 | feat: add root .env.example for docker-compose stack | Lef | 2026-05-04 | ↗ GitHub |
93152400 | feat: add postgres init script for PostgREST roles and auth helpers | Lef | 2026-05-04 | ↗ GitHub |
ff85a408 | feat: add garage single-node config for self-host stack | Lef | 2026-05-04 | ↗ GitHub |
cd1678ae | feat: add init-db script for applying mike schema | Lef | 2026-05-04 | ↗ GitHub |
6e9c11f8 | feat: add init-garage script for bucket and key bootstrap | Lef | 2026-05-04 | ↗ GitHub |
3a37c449 | feat: add mike-backend Dockerfile with libreoffice | Lef | 2026-05-04 | ↗ GitHub |
09f6be77 | feat: add mike-frontend Dockerfile | Lef | 2026-05-04 | ↗ GitHub |
2f46947f | feat: add caddyfile ingress for self-host stack | Lef | 2026-05-04 | ↗ GitHub |
ee25d150 | feat: add docker-compose for self-host stack | Lef | 2026-05-04 | ↗ GitHub |
9613b6bd | fix: resolve first-boot smoke test failures for Task 11 | Lef | 2026-05-04 | ↗ GitHub |
commit body - scripts/generate-secrets.sh: strip inline comments from .env values
so GARAGE_RPC_SECRET (and others) are correctly detected as empty and
regenerated on first run
- docker/init-garage.Dockerfile: new multi-stage image that copies
/garage binary into alpine, replacing the shell-less scratch image
that had no /bin/sh
- docker-compose.yml: change init-garage to use alpine:3.20 directly
(garage CLI no longer needed; init script now calls HTTP admin API);
add API_EXTERNAL_URL env var required by GoTrue v2
- docker/init-garage.sh: rewrite to use Garage v2 HTTP admin API
(port 3903) instead of the RPC CLI, which required the server's node
key; fixes both first-boot and idempotent restart; corrects endpoint
names (GetKeyInfo, not GetKey; ListKeys for existence check)
|
8ff0dc8b | docs: document docker-compose self-host workflow | Lef | 2026-05-05 | ↗ GitHub |
9cc8453c | fix: route backend->gotrue through caddy with transparent host header | Lef | 2026-05-05 | ↗ GitHub |
commit body The backend's @supabase/supabase-js client constructs URLs as
${SUPABASE_URL}/auth/v1/..., so SUPABASE_URL must point at a layer
that strips /auth/v1/ before forwarding to GoTrue (which serves at
the root path). Pointing it at gotrue:9999 directly returned 404
on every auth call, causing all backend endpoints to return 401.
Two changes:
- Caddy site address relaxed from {$MIKE_HOST}:{$MIKE_PORT} to
:{$MIKE_PORT} so internal services (caddy:80) reach it without
Host-header matching games.
- reverse_proxy directives set 'header_up Host {upstream_hostport}'
so Caddy presents the upstream's address as the Host header instead
of forwarding the inbound Host through, which was causing GoTrue
to return empty 200 responses for in-cluster requests.
- mike-backend SUPABASE_URL now points at http://caddy:${MIKE_PORT}.
|
9f6dcfaf | fix: align garage virtual-hosted-style routing for AWS S3 SDK | Lef | 2026-05-05 | ↗ GitHub |
commit body The AWS S3 SDK uses virtual-hosted-style URLs by default
(<bucket>.<endpoint>), so it tries to resolve 'mike.garage:3900'
when uploading to the 'mike' bucket via http://garage:3900.
Three changes:
- docker-compose.yml: add a network alias 'mike.garage' on the
garage service so the SDK's hostname resolves.
- garage.toml: set s3_region = 'auto' to match the value Mike's
storage.ts hardcodes when constructing the S3 client (Garage
rejects requests whose AWS4 scope doesn't match its region).
- garage.toml: set root_domain = '.garage' so Garage parses the
bucket name out of the inbound Host header for virtual-hosted
requests.
Tied to R2_BUCKET_NAME=mike. If you rename the bucket, update
the alias in docker-compose.yml to match.
|
8d411844 | perf: use Next.js standalone output for frontend image | Lef | 2026-05-05 | ↗ GitHub |
commit body Drops mike-frontend image from 1.98 GB to ~465 MB (76% reduction)
by relying on Next.js's standalone output mode. Standalone bundles
only the node_modules subset the server actually requires at runtime
instead of copying the whole build-stage tree (which still contains
devDeps after npm ci).
Two changes:
- frontend/next.config.ts: add output: 'standalone'.
- docker/frontend.Dockerfile: runtime stage now copies .next/standalone
+ .next/static + public, and runs 'node server.js' instead of
'npm run start'.
The standalone server still picks up the NEXT_PUBLIC_* values that
were baked at build time, so behaviour is unchanged.
|
0549bff6 | chore: silence compose warning when only one LLM key is set | Lef | 2026-05-05 | ↗ GitHub |
commit body Adds the :- empty-default substitution to ANTHROPIC_API_KEY and
GEMINI_API_KEY so docker compose treats them as optional. The .env.example
default is the empty string but a user that wipes one of them (e.g. only
sets GEMINI_API_KEY) was getting a 'variable is not set' warning on every
compose invocation. Cosmetic, but loud enough to bury real warnings.
|
e59f59ea | chore: drop unused MIKE_HOST from caddy + remove orphaned Dockerfile | Lef | 2026-05-05 | ↗ GitHub |
commit body Two cleanups surfaced by the final code review:
- Caddy's site address was relaxed from {$MIKE_HOST}:{$MIKE_PORT} to
:{$MIKE_PORT} in 9cc8453, but the compose service kept passing
MIKE_HOST: ${MIKE_HOST} into the container env. The variable is no
longer read by the Caddyfile; replace with a comment explaining
where MIKE_HOST is actually consumed (frontend build args + GoTrue
allow-list) so future maintainers don't assume it flows here.
- docker/init-garage.Dockerfile was created as part of 9613b6b's first
bootstrap attempt; the same commit pivoted init-garage to use
alpine:3.20 + Garage's HTTP admin API and the Dockerfile became
unreferenced. Delete it to avoid misleading future edits.
|
9c7218a8 | fix: add aud claim to minted JWTs in generate-secrets.sh | Lef | 2026-05-05 | ↗ GitHub |
commit body PostgREST is configured with PGRST_JWT_AUD: authenticated. The anon
and service_role JWTs minted by generate-secrets.sh had no aud claim
at all. PostgREST currently accepts a missing aud as a soft-pass
under our config - the smoke test exercised this path and got 200 -
but that is brittle library behaviour and would change between
PostgREST major versions.
Add "aud":"authenticated" to the JWT payload so the audience check
is explicit. GoTrue-issued user JWTs already carry this claim, so
the publishable/secret JWTs now match the user-session shape.
HMAC signing is unchanged. Existing .env files keep working with
their current keys; users who want the new form run
./scripts/generate-secrets.sh --force.
|
325510e6 | Merge pull request #1 from Lef-F/lef/docker-compose | Lef Filippakis | 2026-05-05 | ↗ GitHub |
Self-hosted docker-compose stack |