Docker Installation
The recommended way to run OmniLux. This guide covers every service, volume, environment variable, and optional sidecar.
Who this is for
Use this guide if you want the default self-hosted path with the least friction. If you only need a server running quickly, start with Self-Hosted Quick Start and come back here when you want to tune the deployment.
What this guide covers
- The main OmniLux container
- Storage and permission mapping
- GPU passthrough for transcoding
- Networking and update-safe storage patterns
Prerequisites
- Docker 24+ with Docker Compose v2
- 2 GB RAM minimum (4 GB+ recommended for transcoding)
- Storage for your media library and application data
Core service
The main OmniLux container runs the backend API, web frontend, and all background workers.
services:
omnilux:
build:
context: .
dockerfile: Dockerfile.server
image: omnilux:latest
container_name: omnilux
restart: unless-stopped
ports:
- "4000:4000" # Web UI + API
- "1900:1900/udp" # DLNA/SSDP discovery
environment:
NODE_ENV: production
PORT: 4000
OMNILUX_LIBRARY_ROOT: /data
OMNILUX_DB_PATH: /app/data/omnilux.db
OMNILUX_DOWNLOAD_PATH: /app/data/downloads
TMDB_API_KEY: ${TMDB_API_KEY:-}
volumes:
- /path/to/omnilux/data:/app/data
- /path/to/media:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4000/api/health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3Ports
| Port | Protocol | Purpose |
|---|---|---|
4000 | TCP | Web UI and REST API |
1900 | UDP | DLNA/SSDP device discovery |
Volumes
| Container path | Purpose |
|---|---|
/app/data | SQLite database, downloads, logs, config |
/data | Media library root (movies, TV, music, etc.) |
Minimum viable setup
If you want the smallest possible starting point, focus on these three edits before first boot:
- Change
/path/to/omnilux/datato a persistent host directory. - Change
/path/to/mediato the root of your mounted media library. - Keep the first boot simple and add GPU settings later only if you need transcoding help.
Permissions
The container runs as UID 1000 by default. Make sure your host directories are readable and writable by UID 1000, or set user: "your-uid:your-gid" in the compose file.
GPU passthrough for hardware transcoding
NVIDIA
Install the NVIDIA Container Toolkit, then add to your compose service:
omnilux:
runtime: nvidia
environment:
NVIDIA_VISIBLE_DEVICES: all
NVIDIA_DRIVER_CAPABILITIES: compute,video,utility
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu, video, compute]OmniLux will automatically detect NVENC and use hardware-accelerated transcoding for live TV and on-the-fly streaming. An RTX 3060 supports up to 8 simultaneous NVENC encode sessions.
Intel Quick Sync (VA-API)
omnilux:
devices:
- /dev/dri:/dev/driAMD (VA-API)
omnilux:
devices:
- /dev/dri:/dev/dri
environment:
LIBVA_DRIVER_NAME: radeonsiNetworking
Bridge mode (default)
Uses Docker's default bridge network. Ports are mapped with -p and the server stays isolated from the host except for the ports you publish.
Host mode
For DLNA discovery and HDHomeRun emulation, host networking works better:
omnilux:
network_mode: hostWith host networking, remove the ports section — all ports bind directly to the host.
Recommended production shape
For most operators, the cleanest production setup is:
- Run OmniLux in bridge mode.
- Mount persistent bind paths for
/app/dataand/data. - Put HTTPS and your public hostname in front of it with Reverse Proxy.
- Add GPU passthrough only after the base install is stable.
Storage
Bind mounts vs named volumes
Bind mounts (recommended) — map host directories directly. Easier to back up and inspect:
volumes:
- /srv/omnilux/data:/app/data
- /srv/media:/dataNamed volumes — managed by Docker. Data lives in /var/lib/docker/volumes/:
volumes:
- omnilux-data:/app/data
- media:/data
volumes:
omnilux-data:
media:
driver: local
driver_opts:
type: none
device: /srv/media
o: bindMultiple media directories
Mount additional media paths under /data:
volumes:
- /mnt/movies:/data/movies
- /mnt/tv:/data/tv
- /mnt/music:/data/music
- /mnt/games:/data/gamesThen add each as a separate library root in the OmniLux UI.
Logging
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"Application logs are also written inside the data volume at /app/data/logs/.
Full example
See the complete docker-compose.example.yml mirrored on the docs site.