Runbook: Deploy

Status: Stub — finalized in D1.

Deployment target is open question Q3 in the PRD. Candidates:

Option A — Hetzner sibling to jcortex

  • VPS at Hetzner, x86_64, Ubuntu 22.04+
  • Alongside voice-assistant (jcortex)
  • Caddy for TLS; systemd for process supervision
  • Domain: picortex.globalbr.ai (Cloudflare A record, DNS-only)
  • Pros: Linux, cheap, full control; cgroups v2 + bubblewrap available
  • Cons: one more server to babysit

Option B — Fly.io

  • Fly app, multi-region or single
  • Persistent volumes for chat home dirs
  • Fly handles TLS
  • Pros: minimal ops
  • Cons: systemd-free (use supercronic), Linux user model is the same, but Fly's per-instance FS is ephemeral unless volume-backed; need to mount volumes for chat homes

Option C — HMA (Mac Mini)

  • Jacob's always-on Mac Mini (sdmm291)
  • Already runs many services; public access via Cloudflare Tunnel
  • Pros: no extra server
  • Cons: macOS doesn't have Linux users in the same way; useradd/chmod 0700 model has to use macOS dscl + dseditgroup, more awkward; cgroups v2 unavailable

Working assumption: Option A. Decide in D1.


Deploy script (draft, Option A)

# On laptop:
git push origin main

# On Hetzner VPS as root:
cd /opt/picortex
sudo -u picortex git pull
sudo -u picortex npm ci
sudo -u picortex npm run build
systemctl restart picortex

Systemd unit (draft)

[Unit]
Description=picortex
After=network.target

[Service]
User=picortex
WorkingDirectory=/opt/picortex
Environment=NODE_ENV=production
EnvironmentFile=/opt/picortex/.env
ExecStart=/usr/bin/node dist/server.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Caddy config (draft)

picortex.globalbr.ai {
  reverse_proxy 127.0.0.1:7823
}

Health checks

  • https://picortex.globalbr.ai/health returns {status:"ok"}
  • Journalctl journalctl -u picortex -f
  • bd list --status=open for blocker tickets

Rollback

git reset --hard <previous-sha> && systemctl restart picortex

[[curator]]
I'm the Curator. I can help you navigate, organize, and curate this wiki. What would you like to do?