Stream. Manage. Control.
Self-Hosted Streaming Operations Suite
CastCore is a self-hosted streaming operations suite β a control plane for FFmpeg streams, media sources, network/cloud storage, platform metadata, multi-output streaming, monitoring, recording and linear channels.
It is not "just an FFmpeg web wrapper". CastCore manages sources, analyses media, plans streams, supervises FFmpeg processes safely, monitors outputs, explains failures in plain language and offers automatic fallbacks.
Positioning: CastCore is a self-hosted streaming-control suite for managing FFmpeg streams, media sources, network & cloud storage, platform metadata, multi-destination streaming, monitoring, recording and linear channels.
π‘ Early beta / advanced alpha. The core is built and runs on Docker; it is suitable for
self-hosted early use, not yet production-hardened. See CHANGELOG.md for
the authoritative, chronological record of what landed.
Implemented (functional): auth (JWT + rotating refresh, RBAC Admin/Operator/Viewer), 2FA
(TOTP), API tokens, session management, rate limiting on sensitive auth endpoints;
stream jobs with a shell-free FFmpeg command builder + multi-output, live logs (WebSocket/
Redis), auto-restart; monitoring + Prometheus exporter; a stream health score + diagnostics
assistant; FFmpeg version detection & safe-media mode (CVE-2026-8461 mitigation); local +
SMB/CIFS storage; media library,
playlists, channels (HLS/EPG), recording, scheduler, notifications, backup/restore; MediaMTX
ingest (status + as a source); platform OAuth (YouTube/Twitch) with metadata push and a
readiness check; a full
bilingual docs/help system; and CI for backend (ruff/mypy/pytest incl. API integration
tests), frontend (eslint/build), docs and compose, a Docker FFmpeg build smoke test (builds
all images with FFMPEG_VARIANT=copy and asserts ffmpeg/ffprobe β₯ 8.1.2), plus a manual
full-stack E2E workflow.
Known gaps / not yet:
- GPU encoding (NVENC/QSV/VAAPI) is not verified end-to-end β the bundled FFmpeg supports it, but it additionally needs host drivers + a GPU-enabled container runtime (see FFmpeg requirements).
- OAuth metadata push is implemented for YouTube/Twitch but not yet verified against the live platform APIs (CastCore-side logic is tested with mocked APIs; real push needs client credentials + a connected account).
- Storage: only local + SMB/CIFS; NFS/SFTP/WebDAV/rclone/cloud are not implemented.
- Hardening: worker runs non-root +
cap_drop; backend/process-manager still run as root (onlyno-new-privileges). A CSP header ships in report-only mode by default (toggle viaCSP_ENABLED/CSP_REPORT_ONLY); enforce mode and a report endpoint are not yet enabled. - Tests: no frontend tests and no migration tests yet. The E2E workflow is manual
(
workflow_dispatch). - Native
install.sh/update.sh/uninstall.shexist but are not fully verified.
See docs/ROADMAP.md for the milestone plan.
| Layer | Choice |
|---|---|
| Backend / API | Python 3.12 Β· FastAPI Β· SQLAlchemy 2 (async) Β· Pydantic v2 |
| Process manager | Dedicated asyncio supervisor for long-running FFmpeg processes |
| Worker | arq (Redis) for scans, ffprobe, thumbnails, backups |
| Database | PostgreSQL 16 |
| Cache / Queue / PubSub | Redis 7 |
| Frontend | React 18 Β· TypeScript Β· Vite Β· Tailwind Β· i18next Β· zustand (+ a custom data hook) |
| Reverse proxy | Caddy (automatic HTTPS) |
| Optional router | MediaMTX (RTSP/RTMP/SRT/WebRTC/HLS routing) |
See docs/ARCHITECTURE.md for the full rationale.
Verified path: Docker / Docker Compose is the recommended and tested deployment. The native install scripts exist but are experimental / not fully verified (see below).
- A Linux host (or Docker Desktop on Windows/macOS) with Docker Engine 24+ and the Docker Compose v2 plugin.
- ~2 GB RAM and a few GB of disk for the database, media and recordings.
- Outbound internet for the initial image build (pulls base images + packages).
- The bundled images run Debian 13 (trixie); by default they ship a pinned, static
FFmpeg/ffprobe β₯ 8.1.2 (
FFMPEG_VARIANT=copy, verified by a build-time version gate). Theapt(Debian package) andstatic(custom tarball + SHA256) variants are documented fallbacks. See FFmpeg requirements.
cp .env.example .envEdit .env and set at least:
SECRET_KEYβopenssl rand -hex 32ENCRYPTION_KEYβ a Fernet key:python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"POSTGRES_PASSWORDβ any strong valueDOMAINβlocalhostfor local use, or your public hostname (Caddy gets a real cert via ACME)
.env is git-ignored β never commit it. Keep the ENCRYPTION_KEY safe and backed up
separately: without it, stored secrets (stream keys, platform tokens) cannot be decrypted.
docker compose up -dThe backend auto-runs database migrations on start. Optional service profiles:
docker compose --profile mediamtx up -d # add the MediaMTX media router
docker compose --profile monitoring up -d # add Prometheus exporterOpen https://localhost (or your DOMAIN). On a fresh install the login screen offers a
first-run admin form β create the admin account, then sign in and complete the Setup
Wizard (language, system check, storage). Subsequent users are managed under Users (admin).
Data lives in the castcore_data Docker volume, mounted at /data inside the containers:
| Path | Purpose |
|---|---|
/data/media |
media library sources |
/data/recordings |
recordings/replay output |
/data/logs, /data/backups, /data/mounts, /data/thumbnails |
logs, backups, mounts, assets |
Postgres, Redis and Caddy use their own named volumes. Storage: local folders work out of the box; SMB/CIFS is supported (prefer host-side mounts; in-container mounting needs extra capabilities). NFS/SFTP/WebDAV/rclone/cloud are not implemented yet.
git pull
docker compose up -d --build # rebuilds images; migrations run automatically on startUse Backup / Restore in the UI (DB + config as gz-JSON; secrets stay encrypted). Keep the
ENCRYPTION_KEY with your backups (stored separately). See
Deployment for details.
- Can't reach
https://localhostβ checkdocker compose ps; thecaddyandbackendservices must be healthy. With a self-signed localhost cert, accept the browser warning. - Backend keeps restarting β usually a missing/invalid
SECRET_KEY/ENCRYPTION_KEYorPOSTGRES_PASSWORD; checkdocker compose logs backend. - Can't log in on a fresh install β the first-run admin form appears only while no user exists; if you created one already, sign in with it.
- FFmpeg "vulnerable" warning β should not appear with the default
copybuild (β₯ 8.1.2); it is expected only if you switched toFFMPEG_VARIANT=apt(7.1.x < 8.1.2). See FFmpeg requirements.
β οΈ The native scripts exist but are not fully verified β Docker is recommended.
sudo ./scripts/install.sh # Debian 12 / Ubuntu LTS
sudo ./scripts/update.sh
sudo ./scripts/uninstall.sh- Architecture β strategy, stack, target architecture
- Data model β entities & relationships
- API β REST + WebSocket surface
- Deployment β Docker-first & native install, backup/restore, upgrade
- Local dev & testing β run the full stack on Windows via Docker Desktop
- Security β auth, roles, secret handling, hardening
- Roadmap β milestone plan (Phase 1β4)
CastCore is fully bilingual (Deutsch / English) from day one. Language is chosen in the
Setup Wizard and per user; no UI strings are hard-coded. Translations live in
frontend/src/i18n/{de,en}.json; the backend returns translatable error codes.
GitHub Actions (.github/workflows/ci.yml) runs on every push and pull request:
- Backend β
ruff(lint),mypy(type check),pytest(unit + API integration tests against a Postgres service). - Frontend β
npm ci, ESLint, and thetsc+ Vite build. - Docs β
scripts/check_docs.py(structure, DE/EN parity, manifest, internal links). - Compose β
docker compose configvalidation.
A separate manual workflow (.github/workflows/e2e.yml, workflow_dispatch) runs a
full-stack end-to-end stream-lifecycle test; it is not part of the per-PR gate because it
boots the whole stack. Run the same checks locally; the commands are listed in
CONTRIBUTING.md.
See LICENSE. Branding assets in branding/ follow the CastCore brand guide.