Files
gogo-telefon/docs/DEPLOY.md
Senad Uka fd45ff84dc M6 + M0: hardening, deploy docs, PoC scripts
- Pipeline-down fallback: dialplan plays gogo-fallback after a failed
  AudioSocket (§15) + script to synthesize the Bosnian prompt via TTS
- Voice heartbeat file → /health/voice endpoint + live status in admin panel
- Retention job also purges stale call registrations; chat sessions metered;
  100%-usage super-admin alert email (GOGO_ADMIN_ALERT_EMAIL)
- .env.example, docs/DEPLOY.md (compose stack, GPU node, backups pg_dump,
  update procedure, security notes)
- §16 Definition of Done as an automated test: softphone-style call → fake
  partner availability → request pushed → webhook confirm → console SMS
- M0 PoC scripts: STT accuracy harness (CER/WER + spoken-digit check; dry-run
  verified with espeak-ng samples + faster-whisper small on CPU — phone number
  extracted exactly), TTS bake-off (Azure vs ElevenLabs, latency+cost), and
  end-to-end latency smoke test speaking real AudioSocket to the live pipeline

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 11:27:05 +02:00

3.5 KiB
Raw Blame History

Deploy — founder's DC (Docker Compose, §3/§16 M6)

Layout

Service What Where
db PostgreSQL 16 any node
app FastAPI backend (dashboard, admin, widget, webhooks, action links) any node
voice AudioSocket server + Whisper STT GPU node
asterisk SIP server (softphones, GSM gateway) host networking, reachable by the gateway

First install

git clone <repo> && cd gogotelefon
cp .env.example .env            # fill everything in; strong GOGO_SECRET_KEY!
docker compose build
docker compose up -d db app     # app runs alembic upgrade head on start
docker compose --profile voice up -d voice

# Asterisk config comes from the DB:
docker compose exec app python -m gogo.telephony.asterisk --out ./asterisk/conf \
    --backend http://app:8000 --voice voice:9092
python scripts/generate_fallback_audio.py ./asterisk/sounds   # needs a TTS key
docker compose --profile voice up -d asterisk

# seed the first admin (or python -m gogo.seed for a full demo tenant):
docker compose exec app python - <<'EOF'
import asyncio
from gogo.auth import hash_password
from gogo.db import get_sessionmaker
from gogo.models import Admin
async def main():
    async with get_sessionmaker()() as s:
        s.add(Admin(email="you@gogotelefon.ba", password_hash=hash_password("CHANGE-ME")))
        await s.commit()
asyncio.run(main())
EOF

Put a TLS reverse proxy (caddy/nginx) in front of app:8000 for GOGO_BASE_URL — action links and the widget are public.

GPU node for Whisper

Dockerfile.voice installs CPU wheels by default. On the GPU node use the NVIDIA runtime and set GOGO_WHISPER_DEVICE=cuda, GOGO_WHISPER_MODEL=large-v3 (one RTX 4090/L4 handles 1015 concurrent calls, §3). Scale by adding voice containers and pointing different tenants' Asterisk GOGO_VOICE at them.

Operational jobs (built-in, APScheduler in app)

  • proposal expiry + owner reminders — every 5 min
  • partner polling fallback — every 5 min
  • retention: delete call audio older than GOGO_AUDIO_RETENTION_DAYS (transcripts kept, §5.4), purge stale call registrations — daily 04:00

Monitoring

  • GET /health (app), GET /health/db, GET /health/voice (heartbeat age)
  • admin panel → Sistem: DB, LLM key, email/SMS mode, voice heartbeat, delivery errors from sms_log/email_log
  • per-call latency breakdown: calls.trace.turns[].{stt_ms,llm_ms}

Backups

# nightly dump (cron on the DB node) — keep 14 days
docker compose exec -T db pg_dump -U gogo gogo | gzip > /backup/gogo-$(date +%F).sql.gz
find /backup -name 'gogo-*.sql.gz' -mtime +14 -delete

Recordings volume: rsync /data/recordings if call audio must survive node loss (transcripts are in the DB either way; audio expires after 90 days).

Restore: gunzip -c dump.sql.gz | docker compose exec -T db psql -U gogo gogo.

Update procedure

git pull
docker compose build app voice
docker compose up -d app voice        # alembic migrates on app start
# if workers/tenants changed the SIP layout:
docker compose exec app python -m gogo.telephony.asterisk --out ./asterisk/conf ...
docker compose exec asterisk asterisk -rx 'core reload'

Security notes

  • OAuth tokens + partner API keys are encrypted at rest (Fernet from GOGO_SECRET_KEY) — changing the key orphans them (reconnect/re-enter).
  • /internal/* must not be exposed publicly (compose keeps it on the internal network; the reverse proxy should only forward what's needed).
  • Action links are signed + single-use; widget is rate-limited per IP.