Vigil
← All news

v1.1.0 — single-origin prod + HTTP Basic auth (Cloudflare quick-tunnel ready)

- **Single-origin prod mode.** When `WEB_STATIC_DIR` env var is set, FastAPI serves the React `web/dist/` build at `/` via `StaticFiles(html=True)`. Mounted after every `@app.get`…

Added — deployment infrastructure (post-1.0 backlog item 2, partial)

  • Single-origin prod mode. When WEB_STATIC_DIR env var is set, FastAPI serves the React web/dist/ build at / via StaticFiles(html=True). Mounted after every @app.get so the API routes stay intact. In dev (WEB_STATIC_DIR unset) the Vite dev server keeps doing what it does, no behavior change.
  • HTTP Basic auth middleware in api/main.py, gated on AUTH_USERNAME + AUTH_PASSWORD env vars being non-empty. Both unset → middleware is a no-op (dev + test behavior preserved). /healthz always bypasses auth for monitoring probes. secrets.compare_digest for the credential check.
  • api/config.py grew three settings: web_static_dir, auth_username, auth_password. Pydantic-settings handles .env and process env identically.
  • scripts/run_prod.ps1 — PowerShell runner: confirms web/dist/ exists (auto-builds if not), sets WEB_STATIC_DIR, warns if AUTH_* env unset, starts uvicorn on :8000, opens a Cloudflare quick tunnel (cloudflared tunnel --url) and prints the *.trycloudflare.com URL. Ctrl-C cleans up both processes.
  • 8 new auth-middleware tests (tests/test_auth_middleware.py): /healthz bypass / missing-auth 401 / wrong password / wrong username / correct creds pass / malformed header / invalid base64 / disabled-when-unset. 295 tests passing (287 → 295).

Why these choices

  • HTTP Basic over Cloudflare Access — Access requires a domain on Cloudflare DNS, which we don't have yet. Once a named tunnel + domain land (post-quick-tunnel), unset AUTH_* and Access fronts auth instead — no code change.
  • Single-origin — one tunnel target, no CORS in prod, no separate CDN for the React bundle. The CORS middleware stays in place for the dev-server scenario (Vite on :5173 hitting FastAPI on :8000).
  • PowerShell runner — dev box is Windows. A cron equivalent would be Task Scheduler, but the user chose manual Poll-now over scheduled polling so no cron is wired in.

Operator steps to actually ship a URL

  1. Add to .env: WEB_STATIC_DIR=d:\Misc\Vigil\web\dist, AUTH_USERNAME=<pick>, AUTH_PASSWORD=<long random>.
  2. npm run build in web/ once (or let the script do it).
  3. .\scripts\run_prod.ps1 from project root. Bookmark the *.trycloudflare.com URL printed in the cloudflared output.
  4. Stable URL needed → file an is-a.dev PR (~24-48h merge) or buy a $10/yr domain; then upgrade to a named tunnel + Cloudflare Access (and unset AUTH_*).