justice-bac adds Fly.io deployment with an 855-line interactive deploy script

justice-bac/mike ships two-stage Dockerfiles for backend and frontend, `fly.toml` configs, and a substantial deploy script that handles multi-source secret resolution, builder retry logic, and automatic `NEXT_PUBLIC_*` build-arg injection. The Dockerfiles and the lazy-init Supabase pattern are straightforward to borrow; the script is opinionated around a `backend/.env` + `frontend/.env.local` workflow but structurally reusable.

infrastructureintegration

The Dockerfiles (node:20-bookworm-slim, two-stage builds) are the most portable piece. The backend runtime stage installs LibreOffice for document conversion; strip that layer if you don't use tabular conversion and you'll save several hundred MB. The frontend uses Next.js standalone output and includes sharp. Both have sensible .dockerignore files and health-check routes (/health, /api/health).

deploy-fly.sh (855 lines, commit aa97c8ef) does more than wrap fly deploy. It resolves secrets from environment variables, backend/.env, frontend/.env.local, and interactive prompts in that order. It generates DOWNLOAD_SIGNING_SECRET and USER_API_KEYS_ENCRYPTION_SECRET when they're absent, derives FRONTEND_URL and NEXT_PUBLIC_API_BASE_URL from the app names automatically, and writes temporary fly.toml files so changing your app name or region doesn't touch the committed config. On remote-builder failures it retries with --recreate-builder then falls back to Depot. The GitHub Actions workflow (deploy-fly.yml) drives the same script with workflow_dispatch, accepting prefix, region, and org inputs, and lists all required secrets by name in the env block.

Two bugs caught during real deploy attempts are worth noting. The frontend Supabase client was initialized at module level, which broke the Next.js build because NEXT_PUBLIC_SUPABASE_* aren't available at build time in Docker. The fix (6921ae2c) wraps the client in a Proxy that calls createClient on first browser access - a pattern you'd need regardless of deployment target if you build the frontend as a Docker image. The companion fix (680ca30e) adds ARG/ENV declarations for the four NEXT_PUBLIC_* vars to the frontend Dockerfile and injects them into [build.args] in the temp toml. This is correct for NEXT_PUBLIC_* values (they're public by design), but don't extend the [build.args] pattern to server-side secrets; they'd end up in image history.

The ensure_fly_auth helper (308988bd) bridges FLY_API_TOKEN and FLY_ACCESS_TOKEN, which Fly has used interchangeably. The original flyctl auth whoami check silently failed in CI even with a valid token.

So what Worth a look if you're targeting Fly.io for a mike deployment. The Dockerfiles and the lazy Supabase init pattern are near-drop-in. The deploy script assumes a specific local env-file layout and prompts interactively, so you'd likely adapt the secret-resolution logic rather than use it as-is in a clean CI environment. Skip the LibreOffice layer in the backend Dockerfile unless you need document conversion.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

8 commits from justice-bac/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
0ec5fd61 fly.io deployment modifications Jules Kuehn 2026-05-13 ↗ GitHub
d24f6dab Merge pull request #1 from justice-bac/jus-setup Jules Kuehn 2026-05-14 ↗ GitHub
ops: jus devcontainer setup; fly.io deploy
aa97c8ef deploy to fly.io Jules Kuehn 2026-05-14 ↗ GitHub
308988bd update deployment script Jules Kuehn 2026-05-14 ↗ GitHub
7daca8f0 fix dockerfile Jules Kuehn 2026-05-14 ↗ GitHub
ec481035 fix dockerfile Jules Kuehn 2026-05-14 ↗ GitHub
6921ae2c lazy init supabase module (for build fix) Jules Kuehn 2026-05-14 ↗ GitHub
680ca30e fix deployment Jules Kuehn 2026-05-15 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-401.md from inside the repo you want the changes in.

⬇ Download capture-thread-401.md