# Deployment Notes Two active environments share one Convex deployment (`dev:befitting-dalmatian-161`). Each runs its own web server, Flue agents process, and `.env` file. ## Environments | | Local Mac Dev | Cheaptricks Staging | | --- | --- | --- | | SSH alias | (local) | `cheaptricks` | | Repo path | `/Users/puter/Workspace/zopu/code` | `/workspace/code` | | Tailscale IPv4 | `100.101.157.28` | `100.122.185.111` | | Web URL | `http://100.101.157.28:5173` | `https://zopu.cheaptricks.puter.wtf` | | Flue URL (internal) | `http://100.101.157.28:3585` | `http://127.0.0.1:3585` | | Flue URL (browser-facing) | `http://100.101.157.28:3585` | `https://zopu.cheaptricks.puter.wtf/api` | | Caddy | none (direct Tailscale) | `zopu.cheaptricks.puter.wtf` HTTPS termination | | Bun | installed directly | symlink at `/workspace/.bun` | | Process manager | manual `bun run dev:tailscale:*` | `nohup` into `/tmp/zopu-*.log` | ## Shared Convex deployment Deployment name: `dev:befitting-dalmatian-161` Convex URL: `https://befitting-dalmatian-161.convex.cloud` Convex Site URL: `https://befitting-dalmatian-161.convex.site` Convex env vars are deployment-scoped, not per-machine. Authenticate from any machine with `npx convex dev` inside `packages/backend`. Key Convex env var: ``` SITE_URL = ``` This controls `trustedOrigins` in the Better Auth config (`packages/backend/convex/auth.ts`). It must match the URL the browser actually visits, or sign-in fails silently with a CORS rejection. When switching between environments: ```bash cd packages/backend # For local Mac testing: npx convex env set SITE_URL 'http://100.101.157.28:5173' # For Cheaptricks staging: npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf' ``` ### OAuth consequence `SITE_URL` drives both Better Auth's public callback origin and the single GitHub OAuth App callback. When switching the shared deployment between the local and staging origins, also update the GitHub OAuth App's **Authorization callback URL** to `/api/auth/callback/github` before attempting a GitHub connection. GitHub OAuth Apps allow one callback URL; use distinct Convex deployments and OAuth Apps if both environments must operate concurrently. ## Local Mac Dev `.env` ```env CONVEX_DEPLOYMENT=dev:befitting-dalmatian-161 CONVEX_URL=https://befitting-dalmatian-161.convex.cloud CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site SITE_URL=http://100.101.157.28:5173 NATIVE_APP_URL=code:// VITE_CONVEX_URL=https://befitting-dalmatian-161.convex.cloud VITE_CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site VITE_FLUE_URL=http://100.101.157.28:3585 DAEMON_ID=local-macbook DAEMON_NAME=Local MacBook DAEMON_VERSION=0.0.0 DAEMON_HEARTBEAT_MS=15000 DAEMON_COMMAND_LEASE_MS=60000 FLUE_DB_TOKEN= AGENT_MODEL_PROVIDER=xiaomi AGENT_MODEL_NAME=mimo-v2.5 AGENT_MODEL_API=openai-completions AGENT_MODEL_BASE_URL= AGENT_MODEL_API_KEY= AGENT_MODEL_CONTEXT_WINDOW=1048576 AGENT_MODEL_MAX_TOKENS=131072 GITEA_URL=https://git.openputer.com GITEA_TOKEN= ``` ### Start local dev ```bash bun run dev:tailscale:agents -- --port 3585 & bun run dev:tailscale:web & ``` Both bind `0.0.0.0` so they are reachable over Tailscale from a phone. Before testing locally, flip the Convex `SITE_URL`: ```bash cd packages/backend && npx convex env set SITE_URL 'http://100.101.157.28:5173' ``` ## Cheaptricks Staging `.env` Located at `/workspace/code/.env` on the `cheaptricks` host. ```env CONVEX_DEPLOYMENT=dev:befitting-dalmatian-161 CONVEX_URL=https://befitting-dalmatian-161.convex.cloud CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site SITE_URL=https://zopu.cheaptricks.puter.wtf NATIVE_APP_URL=code:// VITE_CONVEX_URL=https://befitting-dalmatian-161.convex.cloud VITE_CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site VITE_FLUE_URL=https://zopu.cheaptricks.puter.wtf/api VITE_ZOPU_SERVER_URL=https://zopu.cheaptricks.puter.wtf/api PORT=3590 DAEMON_ID=local-macbook DAEMON_NAME=Local MacBook DAEMON_VERSION=0.0.0 DAEMON_HEARTBEAT_MS=15000 DAEMON_COMMAND_LEASE_MS=60000 FLUE_DB_TOKEN= AGENT_MODEL_PROVIDER=xiaomi AGENT_MODEL_NAME=mimo-v2.5 AGENT_MODEL_API=openai-completions AGENT_MODEL_BASE_URL=https://ai.cheaptricks.puter.wtf/v1 AGENT_MODEL_API_KEY= AGENT_MODEL_CONTEXT_WINDOW=1048576 AGENT_MODEL_MAX_TOKENS=131072 GITEA_URL=https://git.openputer.com GITEA_TOKEN= ``` ### Caddy config File: `/etc/caddy/Caddyfile` on `cheaptricks` ``` zopu.cheaptricks.puter.wtf { bind 135.181.82.179 2a01:4f9:c013:4a64::1 encode zstd gzip # Must precede the generic /api route: preserves /api/auth/* and cookies. handle /api/auth/* { reverse_proxy https://befitting-dalmatian-161.convex.site { header_up Host befitting-dalmatian-161.convex.site } } handle_path /api/* { reverse_proxy 127.0.0.1:3585 } handle { reverse_proxy 127.0.0.1:5173 } } ``` `/api/auth/*` is the same-origin Better Auth proxy to Convex. The generic `/api/*` route serves Flue at port `3585`; it must be evaluated only after the authentication route. Reload after changes: ```bash sudo systemctl reload caddy ``` ### Vite allowedHosts `apps/web/vite.config.ts` must include `server: { allowedHosts: true }` or Vite rejects requests arriving through the Caddy domain. ### Start staging dev ```bash ssh cheaptricks export PATH=$PATH:/workspace/.bun/bin cd /workspace/code # Pull latest git pull origin feat/web-integrarion bun install # Start both processes with nohup so they survive SSH disconnect nohup bun run dev:tailscale:agents -- --port 3585 > /tmp/zopu-agents.log 2>&1 & nohup bun run dev:tailscale:web > /tmp/zopu-web.log 2>&1 & ``` Before testing on staging, flip the Convex `SITE_URL`: ```bash cd packages/backend && npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf' ``` ### Verify staging ```bash curl -sS -o /dev/null -w '%{http_code}\n' https://zopu.cheaptricks.puter.wtf/ # expect: 200 curl -sS -D - -o /dev/null \ 'https://befitting-dalmatian-161.convex.site/api/auth/get-session' \ -H 'Origin: https://zopu.cheaptricks.puter.wtf' | grep access-control-allow-origin # expect: access-control-allow-origin: https://zopu.cheaptricks.puter.wtf ``` ## Model configuration Both environments use the same model via the Cheaptricks AI gateway: - Provider identity: `xiaomi` (Flue catalog maps this to MiMo multimodal metadata) - Model: `mimo-v2.5` - API protocol: `openai-completions` - Context window: `1048576` - Max output tokens: `131072` - Multimodal: text + image input The `AGENT_MODEL_BASE_URL` differs: - Local Mac: uses the external gateway URL - Cheaptricks: uses `https://ai.cheaptricks.puter.wtf/v1` (local to the box) ## Known gotchas 1. **Convex `SITE_URL` is single-valued and is the OAuth callback origin.** Switch it together with the GitHub OAuth App's single callback URL when moving between local and staging. Running both origins concurrently requires separate Convex deployments and OAuth Apps. 2. **Vite blocks unknown hosts by default.** Caddy domain must be allowed via `server.allowedHosts` in `apps/web/vite.config.ts`. 3. **Flue port changed from 3583 to 3585.** The old Caddy config pointed at 3583/13100. Current ports are 3585 (Flue) and 5173 (web). 4. **`.env` is gitignored.** Each machine maintains its own copy. The repo ships `.env.example` as the template. 5. **Convex CLI auth is per-machine.** Run `npx convex dev` once inside `packages/backend` on each new machine to authenticate the CLI.