Media Servers
Three different media services are packaged with this project:
- Emby (freemium)
- Jellyfin (free)
- Plex (freemium)
All three of these servers are well known and well supported. But only one should be spun up with this project. They are a heavy resource and you must choose the one that best fits your needs.
Command Line Arguments for the media servers These arguments are for the startup.sh script to help you spin up your environment quickly.
Media Server Arguments | Options | Description |
---|---|
Starts all containers without a media server. | |
emby | Starts all containers with Emby as the Media Server |
jellyfin | Starts all containers with Jellyfin as the Media Server |
plex | Starts all containers with Plex as the Media Server |
EmbyServer
- Just Emby Commands
- Emby is a closed source media server
Type | Command |
---|---|
Start | docker compose up emby -d |
Shutdown | docker compose down emby |

- Once started, Emby should be hit from this url
URL | |
---|---|
Non-SSL | http://localhost:8096 |
SSL | https://localhost:8920 |
Image | emby/embyserver |
- You can change your logo from the default logo by uncommenting the docker compose:
- ./images/logowhite.png:/app/emby/system/dashboard-ui/modules/logoscreensaver/logowhite.png
- ./images/logowhite.png:/app/emby/system/dashboard-ui/modules/themes/logowhite.png
- ./images/logodark.png:/app/emby/system/dashboard-ui/modules/themes/logodark.png
- Simply create a logo in Photoshop or Canva or something. You can use the same logo for
logowhite
andlogodark
or you can use different ones. That is what Emby refers to in the source code!
- This process may also be the same for Jellyfin and Plex since they are Linuxserver.io images.
- See this entire process documented on this site in Other Info.
Emby Example Docker Compose
services:
############ Media Consumption ############
## NOTE - DON'T RUN EMBY AND JELLYFIN AT THE SAME TIME! THEY WILL HAVE PORT CONFLICTS!
emby:
image: lscr.io/linuxserver/emby:latest
container_name: ${EMBY_CONTAINER_NAME}
env_file:
- ./.env
- ../../.env
environment:
- PUID=${UID}
- PGID=${GID}
- TZ=${TIMEZONE}
# - NVIDIA_VISIBLE_DEVICES=all
# - NVIDIA_DRIVER_CAPABILITIES=all
volumes:
- ${DEFAULT_CONTAINER_DATA_LOCATION}/Emby:/config # Configuration directory
# - ./images/logowhite.png:/app/emby/system/dashboard-ui/modules/logoscreensaver/logowhite.png ## Uncomment and create your own logo in the image directory to customize your server
# - ./images/logowhite.png:/app/emby/system/dashboard-ui/modules/themes/logowhite.png ## Uncomment and create your own logo in the image directory to customize your server
# - ./images/logodark.png:/app/emby/system/dashboard-ui/modules/themes/logodark.png ## Uncomment and create your own logo in the image directory to customize your server
- ${LOCAL_TV_PATH}:/media/Synology/Television # Media directory
- ${LOCAL_MOVIES_PATH}:/media/Synology/Movies # Media directory
- ${LOCAL_BACKUPS_PATH}:/media/Synology/Backups #Backups Directory
- ${DEFAULT_CONTAINER_DATA_LOCATION}/ssl:/ssl # Add SSL Certs to this directory
ports:
- ${EMBY_HOST_PORT}:8096 #http port
- ${EMBY_HOST_PORT_SSL}:8920 #ssl port
# runtime: nvidia # Expose NVIDIA GPUs if any (Apple Silicon does not use this)
# network_mode: host # Enable DLNA and Wake-on-Lan
# devices:
# - /dev/dri:/dev/dri # VAAPI/NVDEC/NVENC render nodes, enable for NVIDIA Too i think?
# - /dev/nvidia-uvm:/dev/nvidia-uvm # Added nvidia devices here
# - /dev/nvidia-uvm-tools:/dev/nvidia-uvm-tools # Added nvidia devices here
# - /dev/nvidia-modeset:/dev/nvidia-modeset # Added nvidia devices here
# - /dev/nvidiactl:/dev/nvidiactl # Added nvidia devices here
# - /dev/nvidia0:/dev/nvidia0 # Added nvidia devices here
# - /dev/nvidia1:/dev/nvidia1 # Added nvidia devices here (i have a 2nd GPU so i needed this too)
# - /dev/vchiq:/dev/vchiq # MMAL/OMX on Raspberry Pi
# - /dev/video10:/dev/video10 #optional other video cards
# - /dev/video11:/dev/video11 #optional
# - /dev/video12:/dev/video12 #optional
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.${EMBY_CONTAINER_NAME}.rule=Host(`${EMBY_CONTAINER_NAME}.${PROJECT_HOSTNAME}`)"
- "traefik.http.routers.${EMBY_CONTAINER_NAME}.entrypoints=https"
- "traefik.http.routers.${EMBY_CONTAINER_NAME}.tls=true"
- "traefik.http.services.${EMBY_CONTAINER_NAME}.loadbalancer.server.port=${EMBY_HOST_PORT}"
networks:
- homelab
profiles:
- emby
Emby Example .env
file
EMBY_HOST_PORT="8096"
EMBY_HOST_PORT_SSL="8920"
EMBY_CONTAINER_NAME="emby"
There's a lot of commented lines in the above Emby config. Most of that is fine to keep commented out. I left everything I have found in there for you to be able to pick and choose what you need based on what your host machine needs.
- Nvidia stuff will only work if you have an nvidia video card
- vchiq will only work if you have a raspberry pi
- Apple silicon is not currently supported for hardware acceleration (as of April 2024) with Docker passthrough.
Jellyfin
- Just Jellyfin Commands
- Jellyfin is an free and open source off-shoot alternative to Emby
- The UI is similar, but yet very different from Emby, but lots of nods to the original project's direction and structure.
Type | Command |
---|---|
Start | docker compose up jellyfin -d |
Shutdown | docker compose down jellyfin |

- Once started, Jellyfin should be hit from this url
URL | |
---|---|
Non-SSL | http://localhost:8096 |
SSL | https://localhost:8920 |
Image | linuxserver/jellyfin |
Jellyfin Example Docker Compose
services:
## NOTE - DON'T RUN EMBY AND JELLYFIN AT THE SAME TIME! THEY WILL HAVE PORT CONFLICTS!
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: ${JELLYFIN_CONTAINER_NAME}
env_file:
- ./.env
- ../../.env
environment:
- PUID=${UID}
- PGID=${GID}
- TZ=${TIMEZONE}
# - JELLYFIN_PublishedServerUrl="${JELLYFIN_CONTAINER_NAME}.${PROJECT_HOSTNAME}" #optional
volumes:
- ${DEFAULT_CONTAINER_DATA_LOCATION}/Jellyfin:/config
- ${LOCAL_TV_PATH}:/Television # Media directory
- ${LOCAL_MOVIES_PATH}:/Movies # Media directory
- ${DEFAULT_CONTAINER_DATA_LOCATION}/ssl:/ssl # Add SSL Certs to this directory
labels:
- "traefik.enable=true"
- "traefik.http.routers.${JELLYFIN_CONTAINER_NAME}.rule=Host(`${JELLYFIN_CONTAINER_NAME}.${PROJECT_HOSTNAME}`)"
- "traefik.http.routers.${JELLYFIN_CONTAINER_NAME}.entrypoints=https"
- "traefik.http.routers.${JELLYFIN_CONTAINER_NAME}.tls=true"
- "traefik.http.services.${JELLYFIN_CONTAINER_NAME}.loadbalancer.server.port=${JELLYFIN_HOST_PORT}"
##### JELLYFIN SUPPORTS OIDC AND LDAP PLUGINS FOR AUTHENTIK - https://docs.goauthentik.io/integrations/services/jellyfin/
ports:
- ${JELLYFIN_HOST_PORT}:8096
- ${JELLYFIN_HOST_PORT_SSL}:8920 #optional
- 7359:7359/udp #optional
- 1900:1900/udp #optional
restart: unless-stopped
networks:
- homelab
profiles:
- jellyfin
Jellyfin Example .env
file
JELLYFIN_CONTAINER_NAME="jellyfin"
JELLYFIN_HOST_PORT="8096"
JELLYFIN_HOST_PORT_SSL="8920"
Plex
- Just Plex Commands
- Plex is a self hosted, closed-source media server.
Type | Command |
---|---|
Start | docker compose up plex -d |
Shutdown | docker compose down plex |

- Once started, Plex should be hit from this url
URL | |
---|---|
Non-SSL | http://localhost:32400 |
Image | linuxserver/plex |
Plex Example Docker Compose
services:
plex:
image: lscr.io/linuxserver/plex:latest
container_name: ${PLEX_CONTAINER_NAME}
env_file:
- ./.env
- ../../.env
environment:
- PUID=${UID}
- PGID=${GID}
- TZ=${TIMEZONE}
- VERSION=${PLEX_VERSION}
- "ADVERTISE_IP=https://${PLEX_CONTAINER_NAME}.${PROJECT_HOSTNAME}:443"
- PLEX_CLAIM=${PLEX_CLAIM} #optional
ports:
- ${PLEX_HOST_PORT}:32400
volumes:
- ${DEFAULT_CONTAINER_DATA_LOCATION}/Plex:/config
- ${LOCAL_TV_PATH}:/tv
- ${LOCAL_MOVIES_PATH}:/movies
labels:
########## TODO - SETUP AUTH MIDDLEWARE
- "traefik.enable=true"
- "traefik.http.routers.${PLEX_CONTAINER_NAME}.rule=Host(`${PLEX_CONTAINER_NAME}.${PROJECT_HOSTNAME}`)"
- "traefik.http.routers.${PLEX_CONTAINER_NAME}.entrypoints=https"
- "traefik.http.routers.${PLEX_CONTAINER_NAME}.tls=true"
- "traefik.http.services.${PLEX_CONTAINER_NAME}.loadbalancer.server.port=${PLEX_HOST_PORT}"
restart: unless-stopped
networks:
- homelab
profiles:
- plex
Plex Example .env
file
## PLEX
PLEX_HOST_PORT="32400"
PLEX_CONTAINER_NAME="plex"
PLEX_CLAIM=""
PLEX_VERSION="docker"
Komga
This is technically a media server, but it does not serve video content, just books. This is not included in the media server profiles, but will spin up with the rest of the docker containers.
- Just Komga Commands
- Komga is a free and open source solution to comic books, books, and manga collection management. It's essentially a media server and online reader for all types of books.
Type | Command |
---|---|
Start | docker compose up komga -d |
Shutdown | docker compose down komga |

- Once started, Komga should be hit from this url
URL | |
---|---|
Non-SSL | http://localhost:8341 |
Image | gotson/komga |
Docs | Komga Docker Docs |
Komga Example Docker Compose
services:
komga: ###### NEED TO CONFIGURE LIKE UBUNTU SERVER so no data is lost
image: gotson/komga:latest
container_name: ${KOMGA_CONTAINER_NAME}
env_file:
- ./.env
- ../../.env
volumes:
- ${DEFAULT_CONTAINER_DATA_LOCATION}/Komga/config:/config
- ${LOCAL_BOOKS_PATH}:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.${KOMGA_CONTAINER_NAME}.entrypoints=https"
- "traefik.http.routers.${KOMGA_CONTAINER_NAME}.tls=true"
- "traefik.http.routers.${KOMGA_CONTAINER_NAME}.service=${KOMGA_CONTAINER_NAME}"
- "traefik.http.routers.${KOMGA_CONTAINER_NAME}.rule=Host(`${KOMGA_CONTAINER_NAME}.${PROJECT_HOSTNAME}`)"
- "traefik.http.services.${KOMGA_CONTAINER_NAME}.loadbalancer.server.url=http://komga:${KOMGA_HOST_PORT}" #komga in the url here is the service name which cannot be dynamic --- komga requires a url with a port in it for access
ports:
- ${KOMGA_HOST_PORT}:25600
user: "${UID}:${GID}"
# remove the whole environment section if you don't need it
environment:
- PUID=${UID}
- PGID=${GID}
- TZ=${TIMEZONE}
- KOMGA_LIBRARIES_SCAN_STARTUP=${KOMGA_LIBRARIES_SCAN_STARTUP}
- KOMGA_REMEMBERME_KEY=${KOMGA_REMEMBERME_KEY}
- JAVA_OPTS=${KOMGA_JAVA_OPTS}
restart: unless-stopped
networks:
- homelab
profiles:
- all
- komga
Komga Example .env
file
## Komga
KOMGA_CONTAINER_NAME="komga"
KOMGA_HOST_PORT="8341"
KOMGA_LIBRARIES_SCAN_STARTUP="true"
KOMGA_JAVA_OPTS="-Xmx8g" ## 8 GB - this helps reduce times waiting for pages to process and reduces crashing
KOMGA_REMEMBERME_KEY=""
Navidrome
- Dedicated Music Server
- This is not included in the media server profiles, but will spin up with the rest of the docker containers.
- Just Navidrome Commands
- Navidrome is a selfhosted alternative to something like spotify
Type | Command |
---|---|
Start | docker compose up navidrome -d |
Shutdown | docker compose down navidrome |

- Once started, navidrome should be hit from this url
URL | |
---|---|
Non-SSL | http://localhost:4533 |
Image | deluan/navidrome |
Docs | Navidrome Docs |
Navidrome Example Docker Compose
services:
navidrome:
container_name: ${NAVIDROME_CONTAINER_NAME:-navidrome}
image: deluan/navidrome:latest
ports:
- "${NAVIDROME_HOST_PORT:-4533}:4533"
env_file:
- ./.env
- ../../.env
labels:
- "traefik.enable=true"
- "traefik.http.routers.${NAVIDROME_CONTAINER_NAME}.rule=Host(`${NAVIDROME_CONTAINER_NAME}.${PROJECT_HOSTNAME}`)"
- "traefik.http.routers.${NAVIDROME_CONTAINER_NAME}.entrypoints=https"
- "traefik.http.routers.${NAVIDROME_CONTAINER_NAME}.tls=true"
- "traefik.http.services.${NAVIDROME_CONTAINER_NAME}.loadbalancer.server.port=${NAVIDROME_HOST_PORT}"
## Middlewares
- ${NAVIDROME_AUTHENTIK_MIDDLEWARE:-}
environment:
# Optional: put your config options customization here. Examples:
ND_SCANSCHEDULE: ${NAVIDROME_SCANSCHEDULE:-1h}
ND_LOGLEVEL: ${NAVIDROME_LOG_LEVEL:-info}
ND_BASEURL: "${NAVIDROME_BASEURL:-}"
ND_ENABLESHARING: ${NAVIDROME_ENABLE_SHARING:-false}
networks:
- homelab
volumes:
- "${DEFAULT_CONTAINER_DATA_LOCATION}/Navidrome:/data"
- "${LOCAL_MUSIC_PATH:-../lidarr/.local/music}:/music:ro"
profiles:
- navidrome
- all
Navidrome Example .env
file
## Navidrome
NAVIDROME_CONTAINER_NAME="navidrome"
NAVIDROME_HOST_PORT="4533"
NAVIDROME_SCANSCHEDULE="1h"
NAVIDROME_LOG_LEVEL="info"
NAVIDROME_BASEURL=""
NAVIDROME_ENABLE_SHARING=true