1 Deployment
xpltd_admin edited this page 2026-04-03 22:52:34 -06:00

Deployment

Meta Value
Repo xpltdco/fractafrag
Page Deployment
Audience developers, agents, newcomers
Last Updated 2026-04-04
Status current

Docker Compose Stack

Fractafrag runs as 8 Docker containers orchestrated by docker-compose.yml.

Services

Service Image Port Health Check
nginx nginx:alpine 80
frontend node:20-alpine (custom) 5173
api python:3.12-slim (custom) 8000 curl -f http://localhost:8000/health (10s interval)
mcp python:3.12-slim (custom) 3200
renderer node:20-slim + Chromium (custom) 3100
worker reuses api image
postgres pgvector/pgvector:pg16 5432 pg_isready -U fracta (5s interval)
redis redis:7-alpine 6379 redis-cli ping (5s interval)

Startup Dependencies

postgres (healthy) ─┐
                    ├─→ api (healthy) ─┬─→ nginx
redis (healthy) ────┘                  ├─→ mcp
                                       └─→ frontend ─→ nginx
postgres (healthy) ─┐
                    ├─→ worker
redis (healthy) ────┘

Volume Mounts

Volume Container Path Purpose Backup Priority
pgdata (named) /var/lib/postgresql/data PostgreSQL data Critical — all application state
redisdata (named) /data Redis AOF persistence Low — regeneratable cache
renders (named) /renders Shader thumbnails/previews Medium — regeneratable but slow

Init Script Mount

./db/init.sql:/docker-entrypoint-initdb.d/01-init.sql:ro

This SQL file runs on first PostgreSQL startup only. It creates all tables, indexes, extensions, and the system user account.

Port Mappings

Port Service Protocol Purpose
80 nginx HTTP Main entry point (proxy to all services)
8000 api HTTP FastAPI backend (dev direct access)
5173 frontend HTTP Vite dev server (dev direct access)
3200 mcp HTTP+SSE MCP server (dev direct access)
3100 renderer HTTP Headless renderer (internal)
5432 postgres TCP PostgreSQL (dev direct access)
6379 redis TCP Redis (dev direct access)

In production, only port 80 (nginx) should be exposed externally. Other ports are exposed in docker-compose.override.yml for development only.

Nginx Routing

Config file: services/nginx/conf/default.conf

Location Target Timeout Notes
/ frontend:5173 WebSocket upgrade for Vite HMR
/api/* api:8000/api/ 120s 10M body limit
/mcp/* mcp:3200/ 600s SSE support, no buffering
/renders/* /renders/ (volume alias) 30-day cache, immutable
/health direct 200 Logging disabled

xpltd Infrastructure Deployment

On the xpltd infrastructure:

Traffic Flow

Client → Cloudflare (DNS: fractafrag.xpltd.co)
  → nginx01:443 (TLS termination)
  → ub01:80 (fractafrag nginx container)
  → internal service routing

DNS

Layer Record Value
Cloudflare fractafrag.xpltd.co CNAME dyndns.xpltd.co
AdGuard Home *.xpltd.co rewrite 10.0.0.9 (nginx01)

Health Checks

API Health

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 15s

PostgreSQL Health

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U fracta -d fractafrag"]
  interval: 5s
  timeout: 5s
  retries: 5

Redis Health

healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 5s
  timeout: 5s
  retries: 5

Renderer Configuration

The renderer service requires special Docker configuration:

renderer:
  shm_size: '512mb'  # Required for Chromium shared memory
  environment:
    - MAX_RENDER_DURATION=8
    - OUTPUT_DIR=/renders

Chromium runs in headless mode with software rendering (SwiftShader). No GPU passthrough required.

Redis Configuration

command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
  • AOF persistence enabled (append-only file)
  • 256MB max memory with LRU eviction
  • Increase --maxmemory if running many concurrent Celery tasks

Logging

All services write to stdout/stderr (captured by Docker logging driver).

# All services
make logs
# or: docker compose logs -f

# Specific service
docker compose logs -f api
docker compose logs -f worker
docker compose logs -f renderer

Backup Considerations

What to Back Up

Data Location Strategy
PostgreSQL pgdata volume pg_dump for logical backup
Render output renders volume Optional — can be regenerated
Redis redisdata volume Optional — ephemeral cache

PostgreSQL Backup

# Logical backup (recommended)
docker compose exec postgres pg_dump -U fracta fractafrag > backup.sql

# Restore
docker compose exec -T postgres psql -U fracta fractafrag < backup.sql

Recovery

  1. docker compose down
  2. Remove volumes if doing a clean restore: docker volume rm fractafrag_pgdata
  3. docker compose up -d postgres (waits for healthy)
  4. Restore: docker compose exec -T postgres psql -U fracta fractafrag < backup.sql
  5. docker compose up -d (start remaining services)