3 Deployment
jlightner edited this page 2026-04-04 10:31:50 -05:00

Deployment

Quick Reference

# SSH to ub01
ssh ub01
cd /vmPool/r/repos/xpltdco/chrysopedia

# Standard deploy
git pull
docker compose build && docker compose up -d

# Run migrations (if Alembic is configured)
docker exec chrysopedia-api alembic upgrade head

# View logs
docker logs -f chrysopedia-api
docker logs -f chrysopedia-worker
docker logs -f chrysopedia-watcher
docker logs -f chrysopedia-lightrag

# Check status
docker ps --filter name=chrysopedia

File Layout on ub01

/vmPool/r/
├── repos/xpltdco/chrysopedia/          # Git repo (source code)
├── compose/xpltd_chrysopedia/          # Symlink to repo's docker-compose.yml
├── services/
│   ├── chrysopedia_postgres_data/      # PostgreSQL data
│   ├── chrysopedia_qdrant_data/        # Qdrant vector data
│   ├── chrysopedia_ollama_data/        # Ollama model cache
│   ├── chrysopedia_lightrag/           # LightRAG data + tiktoken cache
│   └── chrysopedia_watch/             # Watcher input directory
│       ├── processed/                  # Successfully ingested transcripts
│       └── failed/                     # Failed transcripts + .error sidecars

Docker Compose Configuration

  • Project name: xpltd_chrysopedia
  • Network: chrysopedia-net (172.32.0.0/24)
  • Compose file: /vmPool/r/repos/xpltdco/chrysopedia/docker-compose.yml

Config Files

File Purpose
.env Core environment variables (DB credentials, API keys, APP_SECRET_KEY)
.env.lightrag LightRAG-specific config (LLM/embedding model, Qdrant connection, working dir)

Build Args / Environment

Frontend build-time constants are injected via Docker build args:

build:
  args:
    VITE_APP_VERSION: ${APP_VERSION:-0.1.0}
    VITE_GIT_COMMIT: ${GIT_COMMIT:-unknown}

Important: ARGENVRUN npm run build ordering matters in the Dockerfile. The ENV line must appear before the build step.

Service Dependencies

chrysopedia-web-8096 → chrysopedia-api → chrysopedia-db, chrysopedia-redis
chrysopedia-worker → chrysopedia-db, chrysopedia-redis, chrysopedia-qdrant, chrysopedia-ollama
chrysopedia-watcher → chrysopedia-api
chrysopedia-lightrag → chrysopedia-qdrant, chrysopedia-ollama

Healthchecks

Service Healthcheck Notes
PostgreSQL pg_isready Built-in
Redis redis-cli ping Built-in
Qdrant bash -c 'echo > /dev/tcp/localhost/6333' No curl available
Ollama ollama list Built-in CLI
API curl -f http://localhost:8000/health
Worker celery -A worker inspect ping Not HTTP
Watcher python -c "import os; os.kill(1, 0)" Slim image, no pgrep
LightRAG python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:9621/health')" Python urllib (no curl in image)

nginx Reverse Proxy

On nuc01 (10.0.0.9):

  • Server block proxies chrysopedia.com → ub01:8096
  • SSL via Certbot (Let's Encrypt)
  • SPA fallback: all paths return index.html

Stale DNS after rebuild: If API container is rebuilt, restart nginx container to pick up new internal IP:

docker compose restart chrysopedia-web-8096

Rebuilding After Code Changes

# Full rebuild (backend + frontend)
cd /vmPool/r/repos/xpltdco/chrysopedia
git pull
docker compose build && docker compose up -d

# Frontend only
docker compose build chrysopedia-web-8096 && docker compose up -d chrysopedia-web-8096

# Backend only (API + Worker share same image)
docker compose build chrysopedia-api && docker compose up -d chrysopedia-api chrysopedia-worker

# Restart without rebuild
docker compose restart chrysopedia-api chrysopedia-worker

Email Digest Scheduling (M025/S01)

The Celery worker runs with the --beat flag to enable periodic task scheduling:

command: celery -A worker worker --loglevel=info --beat

Celery Beat schedule:

  • send-digest-emails: Runs daily at 09:00 UTC via crontab(hour=9, minute=0)
  • Collocated with worker.py celery_app config (no separate beat container needed)

LLM Fallback Configuration (M025/S08)

Add to the API service environment in docker-compose.yml:

environment:
  LLM_FALLBACK_URL: http://chrysopedia-ollama:11434/v1
  LLM_FALLBACK_MODEL: qwen2.5:7b

The fallback endpoint is the local Ollama instance running on the same Docker network. No external dependency -- fallback works even when the primary DGX endpoint is unreachable.

Port Mapping

Service Container Port Host Port Binding
PostgreSQL 5432 5433 0.0.0.0
Web (nginx) 80 8096 0.0.0.0
LightRAG 9621 9621 127.0.0.1
SSH (Forgejo) 22 2222 0.0.0.0

All other services (Redis, Qdrant, Ollama, API, Worker) are internal-only.

Monitoring


See also: Architecture, Development-Guide