# Infrastructure — Accessible Video Processing Platform

<!-- SCOPE: Declarative inventory of what is deployed and where — servers, services, ports, external dependencies. No procedures (see runbook.md). -->
<!-- DOC_KIND: explanation -->
<!-- DOC_ROLE: canonical -->
<!-- READ_WHEN: Read when you need to know what runs where, which ports are exposed, or which external services are used. -->
<!-- SKIP_WHEN: Skip when you need deployment steps → runbook.md; API contracts → api_spec.md. -->
<!-- PRIMARY_SOURCES: docker-compose.yml, backend/app/core/config.py -->

**Generated:** 2026-05-01

---

## Quick Navigation

- [Docs Hub](../README.md)
- [Runbook](runbook.md)
- [Architecture](architecture.md)
- [Tech Stack](tech_stack.md)

## Agent Entry

| Signal | Value |
|--------|-------|
| Purpose | Inventory of servers, Docker services, ports, and external dependencies |
| Read When | You need to know what runs where, port mappings, or external service dependencies |
| Skip When | You need how-to deploy → runbook.md; API contracts → api_spec.md |
| Canonical | Yes |
| Next Docs | [Runbook](runbook.md), [Architecture](architecture.md) |
| Primary Sources | `docker-compose.yml`, `.env.example` |

---

## Server Inventory

| Server | Role | Environment |
|--------|------|-------------|
| `optical-web-1` | Production host — runs all Docker services | Production |
| Local machine | Developer workstation — Docker Compose local stack | Development |

**Production URL:** `https://optical-dev.oliver.solutions/video-accessibility`
**Production API URL:** `https://optical-dev.oliver.solutions/video-accessibility-back`

---

## Docker Services

All services are defined in `docker-compose.yml` and share the `accessible-video-network` bridge network.

| Service | Image / Build | Container Name | Purpose |
|---------|--------------|----------------|---------|
| `mongodb` | `mongo:7.0` | `accessible-video-mongodb` | Primary database |
| `redis` | `redis:7-alpine` | `accessible-video-redis` | Celery broker + result backend |
| `api` | `./backend` (target: `api`) | `accessible-video-api` | FastAPI REST + WebSocket |
| `worker` | `./backend` (target: `worker`) | `accessible-video-worker` | Celery: default, ingest, notify, render queues |
| `tts-worker` | `./backend` (target: `worker`) | `accessible-video-tts-worker` | Celery: tts queue |
| `ffmpeg-worker` | `./backend` (target: `worker`) | `accessible-video-ffmpeg-worker` | Celery: ffmpeg queue |
| `whisper-worker` | `./backend` (target: `whisper-worker`) | `accessible-video-whisper-worker` | Celery: whisper queue |

---

## Port Allocation

| Service | Internal Port | External Port | Notes |
|---------|--------------|---------------|-------|
| `api` | 8000 | **8012** | Exposed to host |
| `mongodb` | 27017 | — | Internal only |
| `redis` | 6379 | — | Internal only |
| Workers | — | — | No HTTP port |

Production: nginx reverse-proxies `optical-web-1:8012` → `https://optical-dev.oliver.solutions/video-accessibility-back`.

---

## Worker Configuration

| Worker | Celery Queues | Concurrency | Memory Limit | Notes |
|--------|--------------|-------------|--------------|-------|
| `worker` | `default, ingest, notify, render` | `${WORKER_CONCURRENCY:-8}` | — | General pipeline |
| `tts-worker` | `tts` | `${TTS_WORKER_CONCURRENCY:-2}` | — | Configurable via env |
| `ffmpeg-worker` | `ffmpeg` | `${FFMPEG_WORKER_CONCURRENCY:-1}` | — | CPU-bound; 1 local, higher in Cloud Run mode |
| `whisper-worker` | `whisper` | `${WHISPER_WORKER_CONCURRENCY:-1}` | **8 GB** (4 GB reserved) | RAM-bound; Whisper large-v3 needs ~4–6 GB |

Cloud Run offload: when `FFMPEG_SERVICE_URL` or `WHISPER_SERVICE_URL` are set, the respective workers delegate to Cloud Run HTTP endpoints instead of running locally.

---

## Volumes

| Volume Name | Mounted In | Purpose |
|-------------|-----------|---------|
| `accessible-video-mongodb-data` | mongodb `/data/db` | MongoDB data |
| `accessible-video-mongodb-config` | mongodb `/data/configdb` | MongoDB config |
| `accessible-video-redis-data` | redis `/data` | Redis AOF persistence |
| `accessible-video-api-logs` | api `/app/logs` | API log files |
| `accessible-video-worker-logs` | worker `/app/logs` | Worker log files |
| `accessible-video-tts-worker-logs` | tts-worker `/app/logs` | TTS worker logs |
| `accessible-video-ffmpeg-worker-logs` | ffmpeg-worker `/app/logs` | FFmpeg worker logs |
| `accessible-video-whisper-worker-logs` | whisper-worker `/app/logs` | Whisper worker logs |
| `accessible-video-shared-tmp` | worker, tts/ffmpeg/whisper workers `/shared-tmp` | Shared temp dir for FFmpeg operations |
| `./secrets` (bind mount) | all services `/secrets:ro` | GCP credentials JSON |

---

## External Dependencies

| Service | Purpose | Config Key |
|---------|---------|------------|
| Google Cloud Storage | Video files, VTT, MP3, rendered video | `GCS_BUCKET`, `GOOGLE_APPLICATION_CREDENTIALS` |
| MongoDB Atlas | Production database (can also run local container) | `MONGODB_URI`, `MONGODB_DB` |
| Gemini 2.5 Pro | VTT generation, translation | `GEMINI_API_KEY` |
| Google Cloud Translate | Language translation | `TRANSLATE_API_KEY` |
| Google Cloud TTS | Audio description synthesis | `GOOGLE_TTS_CREDENTIALS` |
| ElevenLabs | Premium TTS synthesis | `ELEVENLABS_API_KEY` |
| SendGrid | Transactional email (notifications, delivery) | `SENDGRID_API_KEY` |
| Azure AD / Microsoft MSAL | SSO authentication | `AZURE_CLIENT_ID`, `AZURE_AUTHORITY`, `AZURE_REDIRECT_URI` |
| Sentry | Error tracking and alerting | `SENTRY_DSN` |
| OpenTelemetry / OTLP | Distributed tracing | `OTEL_EXPORTER_OTLP_ENDPOINT` |
| AI Cost Tracker | Cross-project AI cost tracking (optical-dev) | `COST_TRACKER_BASE_URL`, `COST_TRACKER_API_KEY` |
| Google Cloud Run (optional) | Offload FFmpeg and Whisper workloads | `FFMPEG_SERVICE_URL`, `WHISPER_SERVICE_URL` |

---

## Health Checks

| Service | Check | Interval |
|---------|-------|---------|
| `mongodb` | TCP port 27017 check | 60s (10s timeout, 3 retries) |
| `redis` | `redis-cli ping` | 30s (10s timeout, 3 retries) |
| `api` | Depends on mongodb + redis healthy | — |
| Workers | Depend on mongodb + redis healthy | — |

Admin health endpoint: `GET /api/v1/admin/health/detailed` (requires admin Bearer token).

---

## Redis Configuration

```text
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly yes
```

---

## Log Rotation

All services use Docker `json-file` logging:

```text
max-size: 10m
max-file: 3
```

---

## Maintenance

**Last Updated:** 2026-05-01

**Update Triggers:**
- New service added to `docker-compose.yml`
- Port mapping changes
- New external dependency added
- Worker queue or concurrency configuration changes

**Verification:**
- [ ] All services in `docker-compose.yml` listed
- [ ] Port table matches `ports:` sections in compose file
- [ ] External dependencies match env vars in `.env.example`
- [ ] Volume names match `volumes:` section in compose file
