Files
zopu-code/docs/deployment.md

6.7 KiB

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 = <the origin Better Auth should trust>

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:

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'

Local Mac Dev .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=<from secrets manager>

AGENT_MODEL_PROVIDER=xiaomi
AGENT_MODEL_NAME=mimo-v2.5
AGENT_MODEL_API=openai-completions
AGENT_MODEL_BASE_URL=<cheaptricks gateway base url>
AGENT_MODEL_API_KEY=<cheaptricks api key>
AGENT_MODEL_CONTEXT_WINDOW=1048576
AGENT_MODEL_MAX_TOKENS=131072

GITEA_URL=https://git.openputer.com
GITEA_TOKEN=<gitea personal access token>

Start local dev

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:

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.

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=<from secrets manager>

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=<cheaptricks api key>
AGENT_MODEL_CONTEXT_WINDOW=1048576
AGENT_MODEL_MAX_TOKENS=131072

GITEA_URL=https://git.openputer.com
GITEA_TOKEN=<gitea personal access 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

    handle_path /api/* {
        reverse_proxy 127.0.0.1:3585
    }

    reverse_proxy 127.0.0.1:5173
}

/api/* routes to the Flue agents process (port 3585). Everything else routes to the web dev server (port 5173).

Reload after changes:

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

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:

cd packages/backend && npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf'

Verify staging

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. Only one origin can be trusted at a time. Switch it when moving between local and staging, or sign-in breaks silently with a CORS error in the browser console.

  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.