Skip to content

Jellyfin

Expose a Jellyfin media server on your Tailscale network with automatic HTTPS.

docker-compose.yml

docker-compose.yml
services:
  tsdproxy:
    image: almeidapaulopt/tsdproxy:2
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - tsdproxy-data:/data
      - ./config:/config
    ports:
      - "8080:8080"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    restart: unless-stopped

  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    environment:
      - PUID=1000
      - PGID=1000
    volumes:
      - jellyfin-config:/config
      - jellyfin-cache:/cache
      - /path/to/media:/media:ro
    labels:
      tsdproxy.enable: "true"
      tsdproxy.name: "jellyfin"
      # HTTPS on 443 -> container port 8096 (HTTP)
      tsdproxy.port.1: "443/https:8096/http"
    restart: unless-stopped

volumes:
  tsdproxy-data:
  jellyfin-config:
  jellyfin-cache:

Labels Explained

LabelValuePurpose
tsdproxy.enable"true"Tell TSDProxy to proxy this container
tsdproxy.name"jellyfin"Tailscale hostname. Your server will be at jellyfin.<tailnet>.ts.net
tsdproxy.port.1"443/https:8096/http"Expose HTTPS on port 443, forwarding to the container’s HTTP port 8096

Access

After starting the containers, authenticate the proxy through the TSDProxy dashboard at http://<your-host>:8080. Once authenticated, Jellyfin is available at:

https://jellyfin.<tailnet-name>.ts.net

Notes

  • Media volumes. Replace /path/to/media with the path to your media library on the host. The :ro flag mounts it read-only, which is fine for playback. If you want Jellyfin to manage library files (download subtitles, write metadata), remove :ro.
  • Port 8096. Jellyfin listens on port 8096 by default. TSDProxy terminates TLS at the Tailscale level, so the connection from TSDProxy to Jellyfin is plain HTTP.
  • Hardware transcoding. If you want VA-API or NVENC transcoding, pass the appropriate device to the Jellyfin container (e.g., devices: ["/dev/dri:/dev/dri"]). This has no interaction with TSDProxy.
  • No Funnel needed. Jellyfin is typically private to your tailnet. If you want to share it publicly, add tailscale_funnel to the port config:
    tsdproxy.port.1: "443/https:8096/http, tailscale_funnel"
    See Funnel for the security implications.
Last updated on