Skip to content

Install phlix-server via Docker โ€‹

TL;DR โ€‹

phlix-server is a PHP 8.3+ media server with HLS streaming, WebSocket real-time sync, DLNA, and a Smarty web portal. This guide deploys it via Docker in roughly 10 minutes using the official detain/phlix-server image and docker-compose.

Minimum requirements: Docker 20.10+, docker-compose v2, 2 CPU / 4 GB RAM.

Quick one-liner:

bash
curl -sSL https://raw.githubusercontent.com/detain/phlix-server/master/docker/examples/server-only/docker-compose.yml | \
  PHLIX_DB_PASSWORD=$(openssl rand -hex 16) \
  PHLIX_SECRET_KEY=$(openssl rand -hex 32) \
  docker-compose -f - up -d

Image variants:

Image tagUse caseHardware
detain/phlix-server:latestGeneric x86_64, no HWaccelAny 64-bit
detain/phlix-server:nvidiaNVIDIA GPU transcodingNVIDIA GPU with driver 525+
detain/phlix-server:intelIntel Quick Sync VideoIntel CPUs with Quicksync (Gen 8+)

Screenshots TBD

This guide is text-first. Screenshots will be added in a follow-up.


1. Supported Docker variants โ€‹

Image tagUse caseHardware
detain/phlix-server:latestGeneric x86_64, no HWaccelAny 64-bit
detain/phlix-server:nvidiaNVIDIA GPU transcodingNVIDIA GPU with driver 525+
detain/phlix-server:intelIntel Quick Sync VideoIntel CPUs with Quicksync (Gen 8+)

Registry path & mutable tags

These images live on ghcr.io/detain/phlix-server (pull with the full ghcr.io/ prefix โ€” e.g. ghcr.io/detain/phlix-server:nvidia). The bare :latest / :nvidia / :intel tags above are mutable convenience tags that move with every build to master, so a docker pull of one may give you a different image than the last time, or a stale one. For a reproducible pull, pin the immutable <full-sha>-<variant> tag the Docker Build & Push workflow publishes on every push (<variant> โˆˆ latest|intel|nvidia). The registry has no v1.2.3-style semver tags and no nightly-* tags. Find the current immutable shas with an anonymous read (no login required):

bash
TOKEN=$(curl -s "https://ghcr.io/token?scope=repository:detain/phlix-server:pull" | jq -r .token)
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://ghcr.io/v2/detain/phlix-server/tags/list" \
  | jq -r '.tags[]' | grep -E '^[0-9a-f]{40}-(latest|intel|nvidia)$' | sort | tail

The companion relay image ghcr.io/detain/phlix-hub uses <sha12> immutable short-sha tags (same recipe, swapping repository:detain/phlix-hub:pull); its own Helm chart documents the published :latest as frozen/stale, so pin a <sha12>. This doc-truth marker S483DOCTRUTHX9P2 records that the tag guidance on this page was re-derived from the live ghcr.io tags on 2026-09-11.


2. Prerequisites โ€‹

Install Docker Engine (Ubuntu/Debian) โ€‹

bash
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker $USER
newgrp docker

Install docker-compose v2 (standalone) โ€‹

bash
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-$(uname -s)-$(uname -m)" \
  -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

3. Quick-start (server-only) โ€‹

bash
mkdir -p ~/phlix && cd ~/phlix
curl -O https://raw.githubusercontent.com/detain/phlix-server/master/docker/examples/server-only/docker-compose.yml
cp .env.example .env  # copy and edit
# Edit .env: set PHLIX_DB_PASSWORD, PHLIX_SECRET_KEY, TZ, PLEX_UID, PLEX_GID
docker-compose up -d

.env configuration reference โ€‹

bash
# Required
PHLIX_DB_PASSWORD=change_me_generate_with_openssl    # openssl rand -hex 16
PHLIX_SECRET_KEY=change_me_generate_with_openssl       # openssl rand -hex 32

# Optional โ€” defaults shown
TZ=UTC
PLEX_UID=1000
PLEX_GID=1000
PHLIX_LOG_LEVEL=info

There is no PHLIX_PORT (or PHLIX_HTTP_PORT) variable โ€” earlier revisions of this page listed one, but no such variable is read anywhere in phlix-server. The published port is set by the ports: mapping in docker-compose.yml; see Port reference below.


4. Volume mounts โ€‹

Host pathContainer pathPurpose
phlix_config (named volume)/var/phlix/configApplication config
phlix_data (named volume)/var/phlix/dataMedia database, caches
phlix_backups (named volume)/var/phlix/backupsAutomatic backups
phlix_logs (named volume)/var/phlix/logsLog files
/path/to/media/media:roRead-only media library mount

To bind-mount a host media directory, replace the volume entry in docker-compose.yml:

yaml
volumes:
  - /mnt/mediavault/movies:/media:ro

5. Hardware transcoding โ€‹

NVIDIA GPU (nvidia image tag) โ€‹

Install NVIDIA Docker runtime first:

bash
distribution=$(. /etc/os-release && echo "$ID$VERSION_ID")
curl -sL https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -sL https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt update && sudo apt install -y nvidia-container-toolkit
sudo systemctl restart docker

Use the nvidia image and add runtime to compose (pin the immutable <full-sha>-nvidia tag โ€” recipe in ยง1 โ€” so the pull is reproducible; the bare :nvidia is a mutable convenience tag that may be stale):

yaml
# <full-sha> = the 40-char commit sha, e.g. from the ยง1 tags/list recipe
image: ghcr.io/detain/phlix-server:<full-sha>-nvidia
# mutable alternative (moves with every build, may be stale):
#   image: ghcr.io/detain/phlix-server:nvidia
# docker-compose.yml must include:
deploy:
  resources:
    reservations:
      devices:
        - driver: nvidia
          count: 1
          capabilities: [gpu, video]

Intel Quick Sync (intel image tag) โ€‹

Pin the immutable <full-sha>-intel tag (recipe in ยง1) for a reproducible pull:

yaml
# <full-sha> = the 40-char commit sha, e.g. from the ยง1 tags/list recipe
image: ghcr.io/detain/phlix-server:<full-sha>-intel
# mutable alternative (moves with every build, may be stale):
#   image: ghcr.io/detain/phlix-server:intel

No special runtime needed; the container automatically detects Quicksync devices via /dev/dri.


6. Port reference โ€‹

Host portContainer portProtocolService
324008096TCPHTTP web interface (REST, the /app SPA, static assets, WebSocket upgrade)
80978097TCPSyncPlay WebSocket
19001900UDPDLNA discovery

8096 inside, 32400 outside

phlix-server always listens on 8096 โ€” that is server.port in config/server.php and it is not settable from the environment. The example compose files in docker/examples/ publish it on host port 32400 (ports: - "32400:8096"), which is why the URLs on this page use :32400 while the Linux/macOS/Windows install pages use :8096. Change the left side of that mapping to publish it somewhere else; the right side must stay 8096.

bash
# Verify ports are free before starting
sudo ss -tlnp | grep -E '32400|8097|1900'

7. Example stacks โ€‹

Tip: All example stacks below are also available in docker/examples/ in the repository. Copy the directory that matches your use case and edit .env.

7a. Server-only (minimal) โ€‹

Single phlix-server + MySQL container, local access only. See docker/examples/server-only/docker-compose.yml:

bash
curl -O https://raw.githubusercontent.com/detain/phlix-server/master/docker/examples/server-only/docker-compose.yml

7b. Server + Hub (remote access) โ€‹

Adds phlix-hub relay service for remote access behind NAT. See docker/examples/server-hub/docker-compose.yml.

7c. Full-stack with Traefik (production) โ€‹

Traefik reverse proxy handling HTTPS, WebSocket relay, and Let's Encrypt certificates:

bash
mkdir -p ~/phlix/full-stack/traefik
curl -O https://raw.githubusercontent.com/detain/phlix-server/master/docker/examples/full-stack/docker-compose.yml
curl -O https://raw.githubusercontent.com/detain/phlix-server/master/docker/examples/full-stack/traefik/traefik.yml
curl -O https://raw.githubusercontent.com/detain/phlix-server/master/docker/examples/full-stack/traefik/dynamic.yml

8. Verify the install โ€‹

bash
# Check container is running
docker ps | grep phlix-server

# Check logs
docker-compose logs -f phlix-server

# Test HTTP endpoint
curl -I http://localhost:32400
# Expected: HTTP 200

# Access web UI
open http://localhost:32400

What can go wrong โ€‹

Docker not installed or wrong version โ€‹

  • Symptom: docker: command not found, or docker-compose: command not found
  • Fix (no Docker): Follow step 2 above to install Docker Engine + docker-compose plugin
  • Fix (docker-compose standalone): Install docker-compose binary separately as shown above
  • Verify: docker --version (min 20.10) and docker-compose --version (min v2.0) or docker compose version

Volume permission errors โ€‹

  • Symptom: Permission denied accessing /var/phlix/config or media files, or "cannot create file" errors in logs
  • Cause: UID/GID mismatch between host user and container's www-data (UID 33 typically)
  • Fix: Set PLEX_UID and PLEX_GID in .env to match the host user that owns the media directories:
    bash
    PLEX_UID=$(id -u)
    PLEX_GID=$(id -g)
  • Verify: docker-compose exec phlix-server id shows correct UID/GID

Port already in use โ€‹

  • Symptom: bind(): Address already in use on 0.0.0.0:32400 or 1900
  • Fix: Find and stop the conflicting process: sudo ss -tlnp | grep 32400, then sudo kill <PID> Or change the mapped port in docker-compose.yml:
    yaml
    ports:
      - "32401:8096"   # publish on host port 32401 instead of 32400
    Only the host (left) side may change โ€” 8096 is the port inside the container.
  • For DLNA port 1900/UDP: set PHLIX_DLNA_PORT=0 to disable DLNA if another service uses it

NVIDIA runtime not configured โ€‹

  • Symptom: Transcoding falls back to software encoding despite NVIDIA GPU present; logs show GPU not available
  • Cause: nvidia-container-toolkit not installed, or nvidia runtime not enabled in Docker
  • Fix: Install nvidia-container-toolkit and add "default-runtime": "nvidia" to /etc/docker/daemon.json:
    json
    {
      "default-runtime": "nvidia",
      "runtimes": {
        "nvidia": {
          "path": "nvidia-container-runtime",
          "runtimeArgs": []
        }
      }
    }
    Then sudo systemctl restart docker
  • Verify: docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi โ€” should print GPU info

Next steps โ€‹

  • First-run wizard โ€” complete the browser-based setup at http://your-server:32400
  • Hardware transcoding โ€” configure NVENC/VAAPI/Quicksync for better transcoding performance
  • Linux install โ€” alternative install method without containers

BSD-3-Clause