Skip to content

Plex Media Server

Overview

Plex organizes your video, music, and photo collections and streams them to all your devices. This guide covers HomelabARR CE setup with Traefik v3.5.0 and modern best practices.

Container Information

Image

  • Registry: lscr.io/linuxserver/plex
  • Current Version: 1.41.3
  • Legacy Image: plexinc/pms-docker (deprecated)

Ports

  • 32400/tcp: Web UI and primary access port
  • 1900/udp: DLNA discovery
  • 3005/tcp: Plex Companion
  • 5353/udp: Bonjour/Avahi discovery
  • 8324/tcp: Roku companion
  • 32410/udp: GDM network discovery
  • 32412-32414/udp: GDM network discovery
  • 32469/tcp: Plex DLNA server

Environment Variables

environment:
  - PUID=1000
  - PGID=1000
  - TZ=${TZ}
  - VERSION=docker  # or specific version like 1.41.3.9314-a0bfb8370
  - PLEX_CLAIM=${PLEX_CLAIM}  # Optional: claim token from https://plex.tv/claim

Volume Mounts

volumes:
  - ${APPDATA_PATH}/plex:/config
  - ${MEDIA_PATH}/movies:/movies
  - ${MEDIA_PATH}/tv:/tv
  - ${MEDIA_PATH}/music:/music
  - ${MEDIA_PATH}/photos:/photos
  - /dev/shm:/transcode  # RAM disk for transcoding (optional but recommended)

Docker Compose Configuration

Modern HomelabARR Configuration (Traefik v3.5.0)

services:
  plex:
    image: lscr.io/linuxserver/plex:1.41.3
    container_name: plex
    network_mode: host  # Required for DLNA and discovery
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=${TZ}
      - VERSION=docker
      - PLEX_CLAIM=${PLEX_CLAIM}
    volumes:
      - ${APPDATA_PATH}/plex:/config
      - ${MEDIA_PATH}:/media
      - /dev/shm:/transcode
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:32400/identity"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"

      # HTTP Router
      - "traefik.http.routers.plex.entrypoints=websecure"
      - "traefik.http.routers.plex.rule=Host(`plex.${DOMAIN}`)"
      - "traefik.http.routers.plex.tls.certresolver=cloudflare"
      - "traefik.http.services.plex.loadbalancer.server.port=32400"

      # Middlewares
      - "traefik.http.routers.plex.middlewares=plex-headers@docker"
      - "traefik.http.middlewares.plex-headers.headers.customResponseHeaders.X-Robots-Tag=noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex"
      - "traefik.http.middlewares.plex-headers.headers.SSLRedirect=true"
      - "traefik.http.middlewares.plex-headers.headers.SSLHost=plex.${DOMAIN}"
      - "traefik.http.middlewares.plex-headers.headers.SSLForceHost=true"
      - "traefik.http.middlewares.plex-headers.headers.STSSeconds=315360000"
      - "traefik.http.middlewares.plex-headers.headers.STSIncludeSubdomains=true"
      - "traefik.http.middlewares.plex-headers.headers.STSPreload=true"
      - "traefik.http.middlewares.plex-headers.headers.forceSTSHeader=true"
      - "traefik.http.middlewares.plex-headers.headers.contentTypeNosniff=true"
      - "traefik.http.middlewares.plex-headers.headers.browserXSSFilter=true"

      # Container updates
      - "dockupdater.enable=true"

Legacy PTS/MHA Configuration (Traefik v1.x/v2.x) - DO NOT USE

# This configuration is outdated and provided only for reference
plex:
  labels:
    - "traefik.enable=true"
    - "traefik.frontend.rule=Host:plex.domain.com"  # OLD SYNTAX
    - "traefik.port=32400"                          # OLD SYNTAX
    - "traefik.docker.network=proxy"

Network Configuration

Network Mode Options

  1. Host Mode (Recommended for full functionality):
    network_mode: host
    
  2. Enables all discovery protocols
  3. Required for DLNA
  4. Simplifies remote access

  5. Bridge Mode (For network isolation):

    networks:
      - proxy
    ports:
      - "32400:32400/tcp"
      - "1900:1900/udp"
      - "3005:3005/tcp"
      - "5353:5353/udp"
      - "8324:8324/tcp"
      - "32410:32410/udp"
      - "32412:32412/udp"
      - "32413:32413/udp"
      - "32414:32414/udp"
      - "32469:32469/tcp"
    

Initial Setup

  1. Claim Your Server:
  2. Visit https://plex.tv/claim
  3. Copy the claim token
  4. Add to environment: PLEX_CLAIM=claim-xxxxxxxxxxxxx
  5. Start the container

  6. First Access:

  7. Local: http://localhost:32400/web
  8. Remote: https://plex.yourdomain.com

  9. Library Setup:

  10. Add library folders from /media
  11. Set up automatic scanning
  12. Configure transcoding settings

Hardware Acceleration

Intel Quick Sync (QSV)

devices:
  - /dev/dri:/dev/dri

NVIDIA GPU

runtime: nvidia
environment:
  - NVIDIA_VISIBLE_DEVICES=all

Performance Optimization

Transcoding

  • Use RAM disk: /dev/shm for transcoding
  • Allocate sufficient RAM (4GB minimum)
  • Enable hardware acceleration when available

Database Optimization

# Optimize database (run monthly)
docker exec plex sqlite3 /config/Library/Application\ Support/Plex\ Media\ Server/Plug-in\ Support/Databases/com.plexapp.plugins.library.db "VACUUM;"
docker exec plex sqlite3 /config/Library/Application\ Support/Plex\ Media\ Server/Plug-in\ Support/Databases/com.plexapp.plugins.library.db "REINDEX;"

Empty Trash

# Empty all library trash
./scripts/plex/plex-empty-trash.sh

Backup Considerations

Critical Paths

  • /config/Library/Application Support/Plex Media Server/Preferences.xml
  • /config/Library/Application Support/Plex Media Server/Plug-in Support/Databases/

Exclude from Backups

  • /config/Library/Application Support/Plex Media Server/Cache/
  • /config/Library/Application Support/Plex Media Server/Metadata/
  • /config/Library/Application Support/Plex Media Server/Media/

Common Issues

Cannot Access Outside Network

  • Ensure port 32400 is forwarded
  • Check "Remote Access" settings in Plex
  • Verify Cloudflare proxy settings (disable for Plex subdomain)

DLNA Not Working

  • Must use network_mode: host
  • Check firewall rules for UDP ports

Transcoding Failures

  • Verify /dev/shm has sufficient space
  • Check permissions on transcode directory
  • Monitor CPU/GPU usage during transcoding

Integration with Other Services

Tautulli (Statistics)

  • Monitor Plex activity
  • Generate usage reports
  • Send notifications

Overseerr/Petio (Requests)

  • User request management
  • Automatic Sonarr/Radarr integration

Sonarr/Radarr

  • Automatic media management
  • Quality upgrades
  • Metadata management

Migration from PTS/MHA

Key changes from legacy setup:

  1. Traefik Labels: Complete syntax change
  2. Old: traefik.frontend.rule
  3. New: traefik.http.routers.plex.rule

  4. SSL Certificates:

  5. Old: Let's Encrypt HTTP challenge
  6. New: Cloudflare DNS challenge

  7. Authentication:

  8. Old: Plex authentication only
  9. New: Optional Authelia SSO integration

  10. Health Checks: Now included by default

  11. Container Updates:

  12. Old: Watchtower
  13. New: dockupdater

Additional Scripts

Located in /scripts/plex/: - plex-empty-trash.sh: Empty all library trash - plex-optimize-db.sh: Optimize Plex database - plex-backup.sh: Backup Plex configuration

Resources


Last Updated: January 2025