Docker Installation
One-click Docker setup for NixStream
Docker is the fastest way to get NixStream running. install.sh pulls prebuilt images from GHCR (or builds locally with --build), wires up services, and seeds the database in one command.
Requirements
- Docker 24+ and Docker Compose v2
- 4+ CPU cores, 8 GB RAM, 100 GB SSD recommended
- Ports: 80 (web), 1935 (RTMP), 8888 (media API)
Quick start
One command (clone + install; pass -y to auto-install Docker if missing):
curl -fsSL https://raw.githubusercontent.com/Muntader/nixstream/main/nixstream/scripts/bootstrap.sh | bash -s -- -yFrom a local clone:
cd nixstream/nixstream
./install.shBy default this pulls ghcr.io/muntader/nixstream and ghcr.io/muntader/nixstream-edge (version NIXSTREAM_VERSION in .env, default 1.0.0). Use ./install.sh --build to compile images locally.
Open http://localhost (or port 8080 if 80 is already in use).
Default admin after install:
- Email:
[email protected](orADMIN_EMAILfrom.env) - Password: one-time temp password, printed once by
install.sh, not saved in.env
Save the password when the installer prints it. Change it after first login.
What install.sh does
install.sh handles:
- Checks prerequisites. Verifies Docker and Compose are available (offers to install Docker via get.docker.com if missing).
- Creates
.env. Copies from.env.docker.exampleand generates secrets likeAPP_KEYandMEDIA_SERVER_API_KEY. - Detects your host IP. Sets
MEDIA_SERVER_INGEST_IPso OBS can reach the RTMP server. - Builds images. Compiles the PHP app image with FFmpeg, Whisper, Shaka Packager, and encoding binaries.
- Starts containers. Brings up all seven services (see diagram below).
- Runs migrations. Creates database tables and seeds the default admin user.
- Prints access info. Shows the URL, port, and default credentials.
If port 80 is busy, install falls back to 8080.
Container layout
| Container | Role |
|---|---|
nixstream_app | Laravel (PHP-FPM) |
nixstream_nginx | Web server |
nixstream_db | MySQL 8 |
nixstream_redis | Cache, sessions, queues |
nixstream_queue | 2 queue workers (encoding + transcripts) |
nixstream_scheduler | Laravel scheduler (recordings:watch) |
nixstream_live | RTMP ingest + live streaming API |
Development mode
./install.sh --devThis adds source bind mounts and starts a Vite dev server on port 5173 with hot module replacement. PHP and config changes on the host show up without rebuilding the image.
Environment variables
Key Docker-specific settings in .env.docker.example:
| Variable | Purpose |
|---|---|
DB_HOST=db | MySQL service name |
REDIS_HOST=redis | Redis service name |
MEDIA_SERVER_HOST | Internal URL to live server |
MEDIA_SERVER_API_KEY | Auto-generated by install.sh |
MEDIA_SERVER_INGEST_IP | Host IP for OBS/RTMP (auto-detected) |
WHISPER_CLI_PATH | Built into image at /opt/whisper/whisper-cli |
BROADCAST_CONNECTION=log | Broadcasting disabled (Reverb not required) |
Useful commands
# View queue logs
docker compose logs -f queue
# Check queue workers
docker compose exec queue supervisorctl status
# Scale encoding workers
docker compose up -d --scale queue=3
# Stop everything
./install.sh --down
# Reset (deletes database + volumes)
./install.sh --resetVerify the install
cd nixstream/nixstream
./scripts/verify.shThis checks container health, database connectivity, and basic endpoints.
Backup
./scripts/backup.shSSL
For production, put a reverse proxy in front of the stack, or use the built-in Caddy installer:
# DNS: A records for stream.example.com and edge.stream.example.com to this host
./install.sh --ssl stream.example.comThis starts Caddy with automatic Let's Encrypt certificates, sets APP_URL / EDGE_BASE_URL to HTTPS, and enables secure cookies. See SSL setup.
For an external reverse proxy (Caddy, Traefik, or host Nginx) in front of port 80, see SSL setup.
Architecture notes
- Whisper: FFmpeg extracts audio, then
whisper-clitranscribes to VTT - No Reverb: Real-time broadcasting uses polling, not WebSockets
- Scheduler: Runs in its own container, so you don't need host crontab
- Live server: Started by default with Redis and API key authentication
GPU encoding
The default Docker install does not include CUDA, NVIDIA drivers, or GPU-enabled FFmpeg. Out of the box, video encoding and Whisper transcription run on CPU only.
NixStream's encoding settings support NVIDIA hardware acceleration (h264_nvenc, hevc_nvenc) and the dashboard can read GPU stats via nvidia-smi when it's present. That path isn't wired up by ./install.sh. The default image ships Debian FFmpeg (CPU encoders only), Whisper built without -DGGML_CUDA=1, no CUDA runtime, and no Compose GPU passthrough.
- Install NVIDIA Container Toolkit on the host.
- Expose the GPU to the
queueservice (and live server if you transcode live with NVENC) indocker-compose.yml. - Replace the stock
apt install ffmpegstep with an NVENC-capable FFmpeg build (for example a CUDA-based image or a known NVENC-enabled FFmpeg package). - Optionally rebuild Whisper with
-DGGML_CUDA=1for GPU transcription.
On a manual install without Docker, install NVIDIA drivers and an NVENC-capable FFmpeg on the host, then enable GPU acceleration in Settings > Encoding. Use CPU encoding profiles when running the default Docker stack.
Troubleshooting
See the troubleshooting guide for encoding stuck jobs, Whisper failures, live stream issues, and database errors.