Commit Graph

9 Commits

Author SHA1 Message Date
JP
f0c745c50c Remove Google and GitHub sign-in
Both providers were registered but never usable: all four client
env vars are empty in production and no Account row has ever been
created. Email and password is the only path that has ever worked.

This also simplifies the invite gating that follows. With OAuth there
were two redemption paths, an invite token that had to survive the
provider round trip in a SameSite=Lax cookie, and an
OAuthAccountNotLinked dead end for anyone who signed up with a password
and later clicked a provider button. Now there is one path.

Account, Session and VerificationToken stay in the schema. They are
Auth.js's tables and dropping them would be a destructive migration for
no benefit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 20:42:40 +00:00
JP
87f951bf94 Run natively under systemd; Docker was unworkable in this LXC
Docker in this unprivileged Proxmox LXC was broken two independent ways:
AppArmor could not load the docker-default profile, so the daemon could
not start any new container, and runc could not set the
net.ipv4.ip_unprivileged_port_start sysctl, which is why every service
needed network_mode: host. `docker build` was impossible outright since
Docker 29 removed the classic builder. The stack only survived because
the containers predated the breakage - a reboot would have left the app
down, and nothing could be redeployed.

Postgres, MinIO and the app now run natively under systemd. Deploys
build out-of-place into releases/<sha> and swap a symlink, so the build
happens while the old release keeps serving and downtime is the ~3s
restart rather than the ~3min build. Rollback is the same swap in
reverse with no rebuild.

Dockerfile and docker-compose.prod.yml are unchanged and still work on
a normal host; the compose app service gains `build: .` so it can come
up on a VPS that cannot reach the LAN-only Gitea registry.

Documents three traps found during the migration: rewrites() in
next.config.mjs is evaluated at build time so MINIO_ENDPOINT changes
silently do nothing, prisma migrate deploy would fail because
production has no _prisma_migrations table, and the image proxy relies
on the bucket's anonymous-download policy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 17:58:34 +00:00
JP
a0e1619072 Route all AI features through the Switchboard gateway
Replace the direct Anthropic and OpenAI integrations with a single
provider that talks to Switchboard, an OpenAI-compatible gateway that
routes each request to the best available model. The app no longer pins
a model id anywhere: it sends switchboard/auto and lets the gateway
choose, then logs which model answered and what it cost.

Routing levers are set per feature in src/lib/ai/routing.ts. Three of
those choices came from measuring against the live gateway:

- category and prefer_free are set explicitly on every request. An API
  key carries its own routing defaults, and anything left unset inherits
  them - drink prompts were being sent to a free coding model.
- Token budgets are generous because the router may pick a reasoning
  model, and reasoning tokens come out of the same max_tokens budget as
  the answer. At 512 tokens a request returned null content; at 4096 the
  same request returned correct JSON.
- No tier lever on text features. tier "cheap" pinned a slow reasoning
  model (42-180s, two timeouts and one truncated response in five
  trials) and tier "frontier" escalated as far as Opus at $0.02 a call,
  while unconstrained routing answered in about a second. Vision keeps
  "frontier", where the accuracy is worth a few tenths of a cent.

Gateway failures are mapped to actionable messages rather than passed
through: a 401 relayed as 401 would read as an expired session and
bounce the user to login, and a 429 would collide with the app's own
rate limiter.

Also collapses the key lookup that was duplicated across ten call sites
into getUserProvider(), which fixes a latent bug where a bare findFirst
with no ordering let different features pick different providers.

Existing claude/openai key rows are ignored at runtime and offered for
removal in Settings, so no migration is needed before deploying.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 16:41:00 +00:00
JP Scott
247a21b6a7 Add AUTH_TRUST_HOST for reverse proxy deployments
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:16:00 -07:00
JP Scott
4ed53d0fd7 Switch to host networking for Proxmox LXC compatibility
network_mode: host avoids Docker creating separate network namespaces
which trigger sysctl writes blocked in LXC containers. All service
references updated from container names to localhost.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:37:14 -07:00
JP Scott
491f8f2c7b Switch to pre-built Docker Hub image for production
- Push app image to jpscott84/drinktracker on Docker Hub
- docker-compose.prod.yml uses image instead of build
- install.sh pulls image instead of building from source
- Much faster deploys (no npm ci/build on target server)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:38:44 -07:00
JP Scott
9212fd4acd Fix compose env var interpolation with --env-file flag
Docker Compose reads ${VAR} interpolation from .env by default,
not from the env_file directive (which only sets container vars).
Added --env-file .env.production to all docker compose commands
so POSTGRES_USER, POSTGRES_PASSWORD, etc. are available for
compose file interpolation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:32:25 -07:00
JP Scott
44c70e7825 Add auto-install for Docker and dependencies in install script
- Automatically installs Docker via get.docker.com if not found
- Installs Docker Compose plugin if missing
- Installs OpenSSL and curl if missing
- Detects package manager (apt, dnf, yum, apk)
- Handles docker group permissions for current user
- Falls back to sudo for docker commands when needed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:28:01 -07:00
JP Scott
1d454d84b2 Add production install script and migrate service
- install.sh: Interactive setup script for Linux VPS/LXC deployment
  - Checks prerequisites (Docker, Docker Compose, OpenSSL)
  - Auto-generates all secrets (Postgres, MinIO, NextAuth, encryption)
  - Creates .env.production with proper Docker service hostnames
  - Builds and starts all services via docker-compose.prod.yml
  - Health check loop with status reporting
  - Idempotent (safe to re-run)

- docker-compose.prod.yml: Add migrate service
  - One-shot container that runs prisma db push before app starts
  - App depends on migrate completing successfully
  - Override DATABASE_URL and MINIO_ENDPOINT for Docker networking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:40:48 -07:00