companion/@deployments/quinn.ai/README.md

4.9 KiB

quinn.ai Deployment

Domain: ai.transquinnftw.com Host: vps-0 (89.127.233.145) — 1984 Hosting, Debian 12 Auth: nginx basic auth (/etc/quinn-ai/htpasswd)


Services

Service Location Port
companion-api vps-0, systemd unit quinn-ai-companion-api :3850
companion-web (PWA) vps-0, nginx static /var/www/quinn.ai/dist/
PostgreSQL vps-0, Docker companion-postgres :26407
Redis vps-0, Docker companion-redis :26406
model-boss apricot, via wg1 10.9.0.2:8210
chatterbox-tts apricot, via wg1 10.9.0.2:8000

WireGuard Tunnel (wg1 — direct apricot ↔ vps-0)

A direct peer-to-peer WireGuard tunnel (wg1, separate from the hub-based wg0) connects vps-0 to apricot for AI service access.

Host wg1 IP Role
vps-0 10.9.0.1/24 Server (listens :51820)
apricot 10.9.0.2/32 Client

Config files:

  • vps-0: /etc/wireguard/wg1.conf — interface + apricot peer
  • apricot: /etc/wireguard/wg1.conf — interface + vps-0 peer
  • Both enabled via systemctl enable wg-quick@wg1

UFW rule on vps-0 (already applied):

ufw allow 51820/udp comment "WireGuard - apricot companion tunnel"

Firewalld on apricot (already applied):

firewall-cmd --zone=trusted --add-interface=wg1 --permanent

Apricot-Side Bindings

Services verified via ss -tlnp on apricot, and connectivity confirmed from vps-0:

Service Bind Reachable from vps-0 Notes
model-boss coordinator 0.0.0.0:8210 http://10.9.0.2:8210/v1/models → 200 claude:* models available
chatterbox-tts 0.0.0.0:8000 http://10.9.0.2:8000/health → healthy Port is 8000, NOT 41222 — app.manifest.yaml has stale port; actual CHATTERBOX_PORT=8000
ai-core NOT RUNNING N/A Bypassed — chat uses claude:* via model-boss subprocess

SPEECH_SYNTHESIS_URL in env must be http://10.9.0.2:8000 (not 41222).


One-Time Setup (vps-0)

# 1. Create directories
mkdir -p /etc/quinn-ai /var/www/quinn.ai/api /var/www/quinn.ai/dist

# 2. Create htpasswd
htpasswd -c /etc/quinn-ai/htpasswd quinn

# 3. Create companion-api env from example
cp env/vps-0.env.example /etc/quinn-ai/companion-api.env
# Edit /etc/quinn-ai/companion-api.env — fill DATABASE_URL, REDIS_URL, VAPID keys, PUSH_FIRE_TOKEN

# 4. Generate VAPID keys
npx web-push generate-vapid-keys
# Paste output into /etc/quinn-ai/companion-api.env

# 5. Start Docker services (postgres + redis)
cd /path/to/companion/@deployments && docker compose up -d
# Or start from the companion @deployments docker-compose.yml

# 6. Obtain TLS cert (first time only)
certbot certonly --webroot -w /var/www/certbot -d ai.transquinnftw.com
# Ensure /var/www/certbot exists and nginx serves it for ACME challenges

# 7. Create certbot webroot dir
mkdir -p /var/www/certbot

Deploy

bash deploy.sh              # full deploy
bash deploy.sh --rollback   # restore previous companion-api
bash deploy.sh --skip-build # skip local build (CI)

Push Fire Restriction

/api/push/fire is restricted at nginx level to 10.9.0.2 only (apricot wg1 IP). The coworker-agent on apricot calls this endpoint to trigger Web Push notifications. This rule prevents the public internet from firing push notifications.


Coworker Nag → Push Wiring (apricot one-time setup)

The coworker-agent cron loop fires push-nag.sh after every Miku TTS synthesis to deliver a matching native iOS push. Set this up once on apricot:

# 1. Create config dir
mkdir -p ~/.config/coworker-agent

# 2. Copy env example
cp /var/home/lilith/Code/@projects/@lilith/lilith-platform.live/users/transquinnftw/agents/coworker-agent/scripts/push.env.example \
   ~/.config/coworker-agent/push.env

# 3. Lock down permissions
chmod 600 ~/.config/coworker-agent/push.env

# 4. Generate a push fire token (same value goes into companion-api env on vps-0)
openssl rand -hex 32
# Paste the output into:
#   ~/.config/coworker-agent/push.env  →  PUSH_FIRE_TOKEN=<value>
#   /etc/quinn-ai/companion-api.env    →  PUSH_FIRE_TOKEN=<value>

# 5. Test the script directly
bash /var/home/lilith/Code/@projects/@lilith/lilith-platform.live/users/transquinnftw/agents/coworker-agent/scripts/push-nag.sh "Test push from apricot"
# Expected: "[push-nag] push sent" (or non-fatal failure if no subscriptions yet)

Token synchronisation: PUSH_FIRE_TOKEN must be identical in:

  • ~/.config/coworker-agent/push.env on apricot (loaded by push-nag.sh)
  • /etc/quinn-ai/companion-api.env on vps-0 (validated by PushFireGuard)

Fallback: if push.env is missing or PUSH_FIRE_TOKEN is unset, push-nag.sh exits 0 silently — the nag loop continues uninterrupted.


Logs

# On vps-0:
journalctl -u quinn-ai-companion-api -n 100 -f
tail -f /var/log/nginx/quinn.ai.access.log
tail -f /var/log/nginx/quinn.ai.error.log