Manual install (Docker Compose)
Use this if you’d rather manage the .env and the clone yourself instead of running the hosted
installer. Same result, more manual steps. Requirements are the same as the one-liner: a Linux
host with a public IP, Docker, and the Compose v2 plugin — see
Requirements.
-
Terminal window git clone https://gitlab.com/digitalhub_com_ar/vision-media-server.gitcd vision-media-server -
Configure
Section titled “Configure”Terminal window cp .env.example .envEdit
.env— at minimumSTREAMHUB_DOMAIN,ACME_EMAIL, and the generated secrets (LIVEKIT_API_KEY/_SECRET,STREAMHUB_JWT_SECRET,ADMIN_PASS,STREAMHUB_API_TOKEN). Full reference in Configuration. -
Build & start
Section titled “Build & start”Terminal window docker compose up -d --builddocker compose ps # redis, livekit, ingress, egress, core, caddy → healthy -
Seed the global API token
Section titled “Seed the global API token”Core needs one bootstrap
sk_token in its database before the API will authenticate anyone:Terminal window docker compose exec -T core node deploy/seed-token.js \"$(grep '^STREAMHUB_API_TOKEN=' .env | cut -d= -f2)" -
Verify
Section titled “Verify”Terminal window curl http://127.0.0.1:3020/api/v1/healthThen open
https://<your-domain>/(dashboard) andhttps://<your-domain>/api/v1/docs(Swagger UI).
Linux-only (host networking)
Section titled “Linux-only (host networking)”redis, livekit, ingress, egress, core, and caddy all run with network_mode: host in
docker-compose.yml. Every service reaches the others over 127.0.0.1, and LiveKit/ingress/
egress push real-time media over UDP/RTMP and rely on STUN external-IP detection — running them
on the host network is the reliable, LiveKit-recommended setup that also mirrors the bare-metal
deployment. network_mode: host is Linux-only, so this targets a Linux VM/server, not Docker
Desktop on macOS.
Compose services
Section titled “Compose services”| Service | Image | Role |
|---|---|---|
redis |
redis:7-alpine |
Coordinates LiveKit ingress/egress and backs BullMQ job queues. |
livekit |
livekit/livekit-server:v1.8.4 |
The SFU — signaling :7880, TCP fallback :7881, media :7882/udp. |
ingress |
livekit/ingress:latest |
RTMP push (:1935) and WHIP (:8080) ingest. |
egress |
livekit/egress:latest |
Room-composite recording (headless Chrome) → MP4/HLS on disk. |
core |
built from deploy/Dockerfile |
The API + SPA + HLS + SDK host, :3020 (loopback only). |
caddy |
caddy:2-alpine |
Terminates TLS on :80/:443; routes /rtc* → LiveKit, everything else → core. |
Persistent data: STREAMHUB_HOST_DATA_DIR (host, default ./data) is bind-mounted to
DATA_DIR (/data) in both core and egress — see
Directory structure for what lives there.
Day-2 operations
Section titled “Day-2 operations”docker compose ps # statusdocker compose logs -f core # tail core logsdocker compose restart core # after editing .envdocker compose down # stop (keeps data + volumes)git pull && docker compose up -d --build # update to a newer release