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.envon apricot (loaded bypush-nag.sh)/etc/quinn-ai/companion-api.envon vps-0 (validated byPushFireGuard)
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