Create Deployment wiki page for fractafrag
parent
c640f13e15
commit
972797dcfc
1 changed files with 200 additions and 0 deletions
200
Deployment.md
Normal file
200
Deployment.md
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
./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
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 15s
|
||||||
|
```
|
||||||
|
|
||||||
|
### PostgreSQL Health
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U fracta -d fractafrag"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
### Redis Health
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
## Renderer Configuration
|
||||||
|
|
||||||
|
The renderer service requires special Docker configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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)
|
||||||
Loading…
Add table
Reference in a new issue