Skip to content

fix: repair the one-command self-host stack#115

Merged
AKogut merged 1 commit into
mainfrom
fix/self-host-stack
Jul 21, 2026
Merged

fix: repair the one-command self-host stack#115
AKogut merged 1 commit into
mainfrom
fix/self-host-stack

Conversation

@AKogut

@AKogut AKogut commented Jul 21, 2026

Copy link
Copy Markdown
Owner

The problem

docker compose up — the promise on the front page of the README — was broken. Replacing the placeholder web app with Next.js in #113 left the container wiring pointing at the old app, and I verified that work locally with next start instead of verifying the stack. That was the wrong check.

What was broken

  • The web Docker target ran node apps/web/dist/index.js, a file deleted in feat: add dashboard with github auth, onboarding and runs list #113. Next builds to .next, so the container exited immediately.
  • The web healthcheck probed /health, a route the Next app never had.
  • The web service had no auth environment, so even a running container could not sign anyone in.
  • The seed produced 24 runs, 1 org and 0 memberships — the demo data belonged to nobody and was unreachable after signing in.
  • The worker was passed HEARTBEAT_INTERVAL_MS, left over from the placeholder; the real worker reads POLL_INTERVAL_MS.

Fixes

  • web now builds with Next's standalone output and runs server.js; the Dockerfile copies only the standalone bundle and static assets.
  • Added a real /health route.
  • Compose passes AUTH_SECRET (required, with a message telling you how to generate one), the GitHub OAuth pair, AUTH_URL and AUTH_TRUST_HOST.
  • First-account bootstrap: the first account created on a fresh instance adopts orgs that have no members, so seeded demo data is reachable instead of orphaned. Orgs that already have a member are never touched, so this can never hand an existing team's data to a later signup.
  • README quickstart now generates AUTH_SECRET and explains the OAuth app and the bootstrap behaviour.

Found only because the stack was actually started this time

  • The API healthcheck was broken too, and had been all along. wget localhost inside Alpine resolves ::1 first while the servers bind IPv4, so both services reported unhealthy forever. It went unnoticed because nothing depends on the API's health condition. Both healthchecks now use 127.0.0.1.
  • A flaky build. web#typecheck ran concurrently with its own build, but the app's tsconfig includes the .next/types that build generates — so typecheck intermittently failed on a missing generated module. Reproduced in one run out of two. Fixed with a package-level turbo config making typecheck depend on build; verified with four consecutive clean runs after deleting .next each time.
  • Turbo cached nothing for the web build — the root config declared outputs: ["dist/**"] while Next writes .next.
  • Four more tracked build artifacts left behind by the deleted placeholder app.

Verification

Brought the whole stack up on a clean volume: every service reports healthy, and the containerized dashboard renders the seeded runs and the flaky board (scores 0.86 / 0.75 / 0.58). Four tests cover the adoption rule, including that it refuses an org someone already owns.

42/42 turbo tasks, 132 tests.

@AKogut AKogut self-assigned this Jul 21, 2026
@AKogut
AKogut merged commit 8609ac3 into main Jul 21, 2026
2 checks passed
@AKogut
AKogut deleted the fix/self-host-stack branch July 21, 2026 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant