Skip to content

Docker Installation

The recommended way to run OmniLux. This guide covers every service, volume, environment variable, and optional sidecar.

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.

yaml
services:
  omnilux:
    build:
      context: .
      dockerfile: Dockerfile.server
    image: omnilux:latest
    container_name: omnilux
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    ports:
      - "4000:4000"          # Web UI + API
      - "6881:6881/tcp"      # BitTorrent
      - "6881:6881/udp"      # BitTorrent
      - "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
      OMNILUX_NATIVE_PORT: 6881
      OMNILUX_TORRENT_ROUTE_BASE_URL: http://omnilux-torrent-route:4100
      OMNILUX_VPN_SCOPE: split
      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: 3

Ports

PortProtocolPurpose
4000TCPWeb UI and REST API
6881TCP/UDPBitTorrent peer connections
1900UDPDLNA/SSDP device discovery

Volumes

Container pathPurpose
/app/dataSQLite database, downloads, logs, config
/dataMedia library root (movies, TV, music, etc.)

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.

Capabilities

NET_ADMIN is required for WireGuard VPN tunnel mode. The src_valid_mark sysctl enables split-tunneling. If you don't use VPN features, you can remove both.

GPU passthrough for hardware transcoding

NVIDIA

Install the NVIDIA Container Toolkit, then add to your compose service:

yaml
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)

yaml
omnilux:
  devices:
    - /dev/dri:/dev/dri

AMD (VA-API)

yaml
omnilux:
  devices:
    - /dev/dri:/dev/dri
  environment:
    LIBVA_DRIVER_NAME: radeonsi

ClamAV sidecar

OmniLux integrates with ClamAV for virus scanning on import. The ClamAV daemon runs inside the main container and is managed by the entrypoint script. Virus definitions are stored in /app/data/clamav and persist across restarts.

The entrypoint script:

  1. Checks for virus definitions in /app/data/clamav, runs freshclam if missing or stale (>24h)
  2. Starts clamd in the background and waits for the Unix socket to become ready
  3. Starts the Node.js application

No additional container is needed — ClamAV runs inside the main OmniLux container.

Torrent route sidecar

The torrent route sidecar is a native WebTorrent engine running in an isolated container with its own VPN kill-switch. Enable it with the torrent-route profile:

bash
docker compose --profile torrent-route up -d
yaml
omnilux-torrent-route:
  profiles: ["torrent-route"]
  build:
    context: .
    dockerfile: Dockerfile.server
  container_name: omnilux-torrent-route
  restart: unless-stopped
  user: root
  cap_add:
    - NET_ADMIN
  devices:
    - /dev/net/tun:/dev/net/tun
  ports:
    - "6881:6881/tcp"
    - "6881:6881/udp"
  environment:
    NODE_ENV: production
    PORT: 4100
    CLAWTORRENT_PORT: 4100
    CLAWTORRENT_TORRENT_PORT: 6881
    OMNILUX_DB_PATH: /app/data/omnilux.db
    OMNILUX_DOWNLOAD_PATH: /app/data/downloads
  command: ["node", "apps/server/dist/clawtorrent/sidecar.js"]
  volumes:
    - /path/to/omnilux/data:/app/data
    - /path/to/media:/data

The main OmniLux container communicates with the torrent route sidecar over HTTP on port 4100. Set OMNILUX_TORRENT_ROUTE_BASE_URL to http://omnilux-torrent-route:4100 in the main service.

Gaming agent container (optional)

For game streaming (RetroArch, Steam, etc.), run the gaming agent on a machine with a dedicated GPU:

yaml
omnilux-gaming:
  build:
    context: .
    dockerfile: Dockerfile.gaming
  container_name: omnilux-gaming
  restart: unless-stopped
  runtime: nvidia
  environment:
    NVIDIA_VISIBLE_DEVICES: all
    NVIDIA_DRIVER_CAPABILITIES: all
    OMNILUX_SERVER_URL: http://omnilux:4000
  ports:
    - "4200:4200"   # Gaming agent API
    - "6080:6080"   # noVNC (debug)
  volumes:
    - /path/to/games:/games

See Game Streaming for setup details.

Networking

Bridge mode (default)

Uses Docker's default bridge network. Ports are mapped with -p. Services communicate via Docker DNS (e.g., http://omnilux-torrent-route:4100).

Host mode

For DLNA discovery and HDHomeRun emulation, host networking works better:

yaml
omnilux:
  network_mode: host

With host networking, remove the ports section — all ports bind directly to the host.

Storage

Bind mounts vs named volumes

Bind mounts (recommended) — map host directories directly. Easier to back up and inspect:

yaml
volumes:
  - /srv/omnilux/data:/app/data
  - /srv/media:/data

Named volumes — managed by Docker. Data lives in /var/lib/docker/volumes/:

yaml
volumes:
  - omnilux-data:/app/data
  - media:/data

volumes:
  omnilux-data:
  media:
    driver: local
    driver_opts:
      type: none
      device: /srv/media
      o: bind

Multiple media directories

Mount additional media paths under /data:

yaml
volumes:
  - /mnt/movies:/data/movies
  - /mnt/tv:/data/tv
  - /mnt/music:/data/music
  - /mnt/games:/data/games

Then add each as a separate library root in the OmniLux UI.

Logging

yaml
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 in the repository.

Use OmniLux, run your own server, or build on the platform.