Skip to content

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.

  1. Terminal window
    git clone https://gitlab.com/digitalhub_com_ar/vision-media-server.git
    cd vision-media-server
  2. Terminal window
    cp .env.example .env

    Edit .env — at minimum STREAMHUB_DOMAIN, ACME_EMAIL, and the generated secrets (LIVEKIT_API_KEY/_SECRET, STREAMHUB_JWT_SECRET, ADMIN_PASS, STREAMHUB_API_TOKEN). Full reference in Configuration.

  3. Terminal window
    docker compose up -d --build
    docker compose ps # redis, livekit, ingress, egress, core, caddy → healthy
  4. 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)"
  5. Terminal window
    curl http://127.0.0.1:3020/api/v1/health

    Then open https://<your-domain>/ (dashboard) and https://<your-domain>/api/v1/docs (Swagger UI).

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.

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.

Terminal window
docker compose ps # status
docker compose logs -f core # tail core logs
docker compose restart core # after editing .env
docker compose down # stop (keeps data + volumes)
git pull && docker compose up -d --build # update to a newer release