Jellyfin Media Server

Russell Bateman
November 2023
last update:

Table of Contents

What is true of Jellyfin?
Installing Jellyfin Media Server
Putting Jellyfin behind a reverse-proxy server
      - Justification of virtual-host configuration and command-line URL
Reverse-proxy success...
Roku success...
Sharing with family and friends outside
Random notes

Jellyfin enables you to collect, manage and stream any of your media (movies, TV shows, miscellaneous videos and music. What sets Jellyfin apart from Plex Media is that it's free and open-source both for use as a server and also as a client. The list of clients is forever changing (upgrading).

Jellyfin supports the following browsers:

 Chrome   Chrome for Android 
 Firefox   Safari for MacOS and iOS 

Jellyfin supports the following client devices:

 Smart TVs and streaming devices 
 Roku   Amazon Fire TV 
 Web OS   Kodi 
 Swiftfin (iOS) 
 Handheld devices 
 Swiftfin (iOS) 
 Desktop applications 
 Jellyfin media player   Jellyfin MPV 

...and many other devices and places to access Jellyfin served up content including Findroid and Finamp (Android), Infuse (iOS), MrMC, XBOX One, Videotape (Windows).

Jellyfin Media Server: What is true?

  1. Is it possible to set up and run Jellyfin along side your Plex Media server—for evaluation purposes or other reasons?
  2. Does the Jellyfin server ever "run home to mama" with logs, reports on what's playing, etc. the way the Plex Media server does?

Installing Jellyfin Media Server

(The first time, I am doing this on tol-eressea in order to test Jellyfin's ability to co-reside with Plex Media without disturbing the latter.)

  1. Go to Jellyfin Downloads for clients: Server. In my case, I'm interested in the install instructions for Debian and Ubuntu because I run the Linux Mint client and headless Ubuntu Server.

  2. Click on the Install Instructions button. I will be more interested in the advanced, repository manual instructions because I want to use apt-get to make it more a part of my system.
    1. Enable the repository to find (and, later, update) the FFmpeg dependencies:
      # add-apt-repository universe
      # mkdir -p /etc/apt/keyrings
      # curl -fsSL | gpg --dearmor -o /etc/apt/keyrings/jellyfin.gpg
      # ll /etc/apt/keyrings/jellyfin.gpg
      -rw-r--r-- 1 root root 2212 Nov 25 21:26 jellyfin.gpg
      # export VERSION_OS="$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release )"
      # export VERSION_CODENAME="$( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release )"
      # export DPKG_ARCHITECTURE="$( dpkg --print-architecture )"
      # cat <<EOF | tee /etc/apt/sources.list.d/jellyfin.sources
      Types: deb
      Suites: ${VERSION_CODENAME}
      Components: main
      Architectures: ${DPKG_ARCHITECTURE}
      Signed-By: /etc/apt/keyrings/jellyfin.gpg
      # ll /etc/apt/sources.list.d/jellyfin.sources
      -rw-r--r-- 1 root root 145 Nov 25 21:34 /etc/apt/sources.list.d/jellyfin.sources
      # cat /etc/apt/sources.list.d/jellyfin.sources
      Types: deb URIs: Suites: bionic Components: main Architectures: amd64 Signed-By: /etc/apt/keyrings/jellyfin.gpg
    2. Next, update the apt repositories, install jellyfin and make Jellyfin a systemd service:
      # apt-get update
      Hit:1 bionic InRelease Hit:2 bionic-security InRelease Hit:3 bionic-updates InRelease Get:4 bionic InRelease [6,637 B] Get:5 bionic/main amd64 Packages [1,956 B] Fetched 8,593 B in 18s (468 B/s) Reading package lists... Done
      # apt-get install jellyfin
      Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: fontconfig-config fonts-dejavu-core jellyfin-ffmpeg5 jellyfin-server jellyfin-web libaacs0 libass9 libbdplus0 libbluray2 libcairo2 libfontconfig1 libgraphite2-3 libharfbuzz0b libmp3lame0 libmpg123-0 libogg0 libopenmpt0 libopus0 libpciaccess0 libpixman-1-0 libtheora0 libvorbis0a libvorbisenc2 libvorbisfile3 libvpx5 libwebp6 libwebpmux3 libx264-152 libx265-146 libxcb-render0 libxcb-shm0 libxrender1 libzvbi-common libzvbi0 ocl-icd-libopencl1 Suggested packages: libbluray-bdj opus-tools opencl-icd The following NEW packages will be installed: fontconfig-config fonts-dejavu-core jellyfin jellyfin-ffmpeg5 jellyfin-server jellyfin-web libaacs0 libass9 libbdplus0 libbluray2 libcairo2 libfontconfig1 libgraphite2-3 libharfbuzz0b libmp3lame0 libmpg123-0 libogg0 libopenmpt0 libopus0 libpciaccess0 libpixman-1-0 libtheora0 libvorbis0a libvorbisenc2 libvorbisfile3 libvpx5 libwebp6 libwebpmux3 libx264-152 libx265-146 libxcb-render0 libxcb-shm0 libxrender1 libzvbi-common libzvbi0 ocl-icd-libopencl1 0 upgraded, 36 newly installed, 0 to remove and 1 not upgraded. Need to get 118 MB of archives. After this operation, 372 MB of additional disk space will be used. Do you want to continue? [Y/n] y Get:1 bionic/main amd64 libogg0 amd64 1.3.2-1 [17.2 kB] Get:2 bionic/main amd64 fonts-dejavu-core all 2.37-1 [1,041 kB] Get:3 bionic/main amd64 fontconfig-config all 2.12.6-0ubuntu2 [55.8 kB] Get:4 bionic/main amd64 libfontconfig1 amd64 2.12.6-0ubuntu2 [137 kB] Get:5 bionic/main amd64 libgraphite2-3 amd64 1.3.11-2 [78.7 kB] Get:6 bionic/main amd64 libharfbuzz0b amd64 1.7.2-1ubuntu1 [232 kB] Get:7 bionic/universe amd64 libass9 amd64 1:0.14.0-1 [88.2 kB] Get:8 bionic/universe amd64 libbluray2 amd64 1:1.0.2-3 [141 kB] Get:9 bionic/main amd64 libmp3lame0 amd64 3.100-2 [136 kB] Get:10 bionic/main amd64 libmpg123-0 amd64 1.25.10-1 [125 kB] Get:11 bionic/main amd64 libvorbis0a amd64 1.3.5-4.2 [86.4 kB] Get:12 bionic/main amd64 libvorbisfile3 amd64 1.3.5-4.2 [16.0 kB] Get:13 bionic/universe amd64 libopenmpt0 amd64 0.3.6-1 [561 kB] Get:14 bionic/main amd64 libopus0 amd64 1.1.2-1ubuntu1 [159 kB] Get:15 bionic/main amd64 libpciaccess0 amd64 0.14-1 [17.9 kB] Get:16 bionic-security/main amd64 libpixman-1-0 amd64 0.34.0-2ubuntu0.1 [229 kB] Get:17 bionic-updates/main amd64 libxcb-render0 amd64 1.13-2~ubuntu18.04 [14.7 kB] Get:18 bionic-updates/main amd64 libxcb-shm0 amd64 1.13-2~ubuntu18.04 [5,600 B] Get:19 bionic/main amd64 libxrender1 amd64 1:0.9.10-1 [18.7 kB] Get:20 bionic-updates/main amd64 libcairo2 amd64 1.15.10-2ubuntu0.1 [580 kB] Get:21 bionic/main amd64 libtheora0 amd64 1.1.1+dfsg.1-14 [170 kB] Get:22 bionic/main amd64 libvorbisenc2 amd64 1.3.5-4.2 [70.7 kB] Get:23 bionic-security/main amd64 libvpx5 amd64 1.7.0-3ubuntu0.18.04.1 [796 kB] Get:24 bionic-security/main amd64 libwebp6 amd64 0.6.1-2ubuntu0.18.04.2 [186 kB] Get:25 bionic-security/main amd64 libwebpmux3 amd64 0.6.1-2ubuntu0.18.04.2 [19.6 kB] Get:26 bionic/universe amd64 libx264-152 amd64 2:0.152.2854+gite9a5903-2 [609 kB] Get:27 bionic/universe amd64 libx265-146 amd64 2.6-3 [1,026 kB] Get:28 bionic/universe amd64 libzvbi-common all 0.2.35-13 [32.1 kB] Get:29 bionic/universe amd64 libzvbi0 amd64 0.2.35-13 [235 kB] Get:30 bionic/main amd64 ocl-icd-libopencl1 amd64 2.2.11-1ubuntu1 [30.3 kB] Get:31 bionic/universe amd64 libaacs0 amd64 0.9.0-1 [51.4 kB] Get:32 bionic/universe amd64 libbdplus0 amd64 0.1.2-2 [46.6 kB] Get:33 bionic/main amd64 jellyfin-server amd64 10.8.12-1 [38.6 MB] Get:34 bionic/main amd64 jellyfin-web all 10.8.12-1 [42.3 MB] Get:35 bionic/main amd64 jellyfin-ffmpeg5 amd64 5.1.3-7-bionic [29.6 MB] Get:36 bionic/main amd64 jellyfin all 10.8.12-1 [2,284 B] Fetched 118 MB in 25s (4,718 kB/s) Extracting templates from packages: 100% Selecting previously unselected package libogg0:amd64. (Reading database ... 107791 files and directories currently installed.) Preparing to unpack .../00-libogg0_1.3.2-1_amd64.deb ... Unpacking libogg0:amd64 (1.3.2-1) ... Selecting previously unselected package fonts-dejavu-core. Preparing to unpack .../01-fonts-dejavu-core_2.37-1_all.deb ... Unpacking fonts-dejavu-core (2.37-1) ... Selecting previously unselected package fontconfig-config. Preparing to unpack .../02-fontconfig-config_2.12.6-0ubuntu2_all.deb ... Unpacking fontconfig-config (2.12.6-0ubuntu2) ... Selecting previously unselected package libfontconfig1:amd64. Preparing to unpack .../03-libfontconfig1_2.12.6-0ubuntu2_amd64.deb ... Unpacking libfontconfig1:amd64 (2.12.6-0ubuntu2) ... Selecting previously unselected package jellyfin-server. Preparing to unpack .../04-jellyfin-server_10.8.12-1_amd64.deb ... Unpacking jellyfin-server (10.8.12-1) ... Selecting previously unselected package jellyfin-web. Preparing to unpack .../05-jellyfin-web_10.8.12-1_all.deb ... Unpacking jellyfin-web (10.8.12-1) ... Selecting previously unselected package libgraphite2-3:amd64. Preparing to unpack .../06-libgraphite2-3_1.3.11-2_amd64.deb ... Unpacking libgraphite2-3:amd64 (1.3.11-2) ... Selecting previously unselected package libharfbuzz0b:amd64. Preparing to unpack .../07-libharfbuzz0b_1.7.2-1ubuntu1_amd64.deb ... Unpacking libharfbuzz0b:amd64 (1.7.2-1ubuntu1) ... Selecting previously unselected package libass9:amd64. Preparing to unpack .../08-libass9_1%3a0.14.0-1_amd64.deb ... Unpacking libass9:amd64 (1:0.14.0-1) ... Selecting previously unselected package libbluray2:amd64. Preparing to unpack .../09-libbluray2_1%3a1.0.2-3_amd64.deb ... Unpacking libbluray2:amd64 (1:1.0.2-3) ... Selecting previously unselected package libmp3lame0:amd64. Preparing to unpack .../10-libmp3lame0_3.100-2_amd64.deb ... Unpacking libmp3lame0:amd64 (3.100-2) ... Selecting previously unselected package libmpg123-0:amd64. Preparing to unpack .../11-libmpg123-0_1.25.10-1_amd64.deb ... Unpacking libmpg123-0:amd64 (1.25.10-1) ... Selecting previously unselected package libvorbis0a:amd64. Preparing to unpack .../12-libvorbis0a_1.3.5-4.2_amd64.deb ... Unpacking libvorbis0a:amd64 (1.3.5-4.2) ... Selecting previously unselected package libvorbisfile3:amd64. Preparing to unpack .../13-libvorbisfile3_1.3.5-4.2_amd64.deb ... Unpacking libvorbisfile3:amd64 (1.3.5-4.2) ... Selecting previously unselected package libopenmpt0:amd64. Preparing to unpack .../14-libopenmpt0_0.3.6-1_amd64.deb ... Unpacking libopenmpt0:amd64 (0.3.6-1) ... Selecting previously unselected package libopus0:amd64. Preparing to unpack .../15-libopus0_1.1.2-1ubuntu1_amd64.deb ... Unpacking libopus0:amd64 (1.1.2-1ubuntu1) ... Selecting previously unselected package libpciaccess0:amd64. Preparing to unpack .../16-libpciaccess0_0.14-1_amd64.deb ... Unpacking libpciaccess0:amd64 (0.14-1) ... Selecting previously unselected package libpixman-1-0:amd64. Preparing to unpack .../17-libpixman-1-0_0.34.0-2ubuntu0.1_amd64.deb ... Unpacking libpixman-1-0:amd64 (0.34.0-2ubuntu0.1) ... Selecting previously unselected package libxcb-render0:amd64. Preparing to unpack .../18-libxcb-render0_1.13-2~ubuntu18.04_amd64.deb ... Unpacking libxcb-render0:amd64 (1.13-2~ubuntu18.04) ... Selecting previously unselected package libxcb-shm0:amd64. Preparing to unpack .../19-libxcb-shm0_1.13-2~ubuntu18.04_amd64.deb ... Unpacking libxcb-shm0:amd64 (1.13-2~ubuntu18.04) ... Selecting previously unselected package libxrender1:amd64. Preparing to unpack .../20-libxrender1_1%3a0.9.10-1_amd64.deb ... Unpacking libxrender1:amd64 (1:0.9.10-1) ... Selecting previously unselected package libcairo2:amd64. Preparing to unpack .../21-libcairo2_1.15.10-2ubuntu0.1_amd64.deb ... Unpacking libcairo2:amd64 (1.15.10-2ubuntu0.1) ... Selecting previously unselected package libtheora0:amd64. Preparing to unpack .../22-libtheora0_1.1.1+dfsg.1-14_amd64.deb ... Unpacking libtheora0:amd64 (1.1.1+dfsg.1-14) ... Selecting previously unselected package libvorbisenc2:amd64. Preparing to unpack .../23-libvorbisenc2_1.3.5-4.2_amd64.deb ... Unpacking libvorbisenc2:amd64 (1.3.5-4.2) ... Selecting previously unselected package libvpx5:amd64. Preparing to unpack .../24-libvpx5_1.7.0-3ubuntu0.18.04.1_amd64.deb ... Unpacking libvpx5:amd64 (1.7.0-3ubuntu0.18.04.1) ... Selecting previously unselected package libwebp6:amd64. Preparing to unpack .../25-libwebp6_0.6.1-2ubuntu0.18.04.2_amd64.deb ... Unpacking libwebp6:amd64 (0.6.1-2ubuntu0.18.04.2) ... Selecting previously unselected package libwebpmux3:amd64. Preparing to unpack .../26-libwebpmux3_0.6.1-2ubuntu0.18.04.2_amd64.deb ... Unpacking libwebpmux3:amd64 (0.6.1-2ubuntu0.18.04.2) ... Selecting previously unselected package libx264-152:amd64. Preparing to unpack .../27-libx264-152_2%3a0.152.2854+gite9a5903-2_amd64.deb ... Unpacking libx264-152:amd64 (2:0.152.2854+gite9a5903-2) ... Selecting previously unselected package libx265-146:amd64. Preparing to unpack .../28-libx265-146_2.6-3_amd64.deb ... Unpacking libx265-146:amd64 (2.6-3) ... Selecting previously unselected package libzvbi-common. Preparing to unpack .../29-libzvbi-common_0.2.35-13_all.deb ... Unpacking libzvbi-common (0.2.35-13) ... Selecting previously unselected package libzvbi0:amd64. Preparing to unpack .../30-libzvbi0_0.2.35-13_amd64.deb ... Unpacking libzvbi0:amd64 (0.2.35-13) ... Selecting previously unselected package ocl-icd-libopencl1:amd64. Preparing to unpack .../31-ocl-icd-libopencl1_2.2.11-1ubuntu1_amd64.deb ... Unpacking ocl-icd-libopencl1:amd64 (2.2.11-1ubuntu1) ... Selecting previously unselected package jellyfin-ffmpeg5. Preparing to unpack .../32-jellyfin-ffmpeg5_5.1.3-7-bionic_amd64.deb ... Unpacking jellyfin-ffmpeg5 (5.1.3-7-bionic) ... Selecting previously unselected package jellyfin. Preparing to unpack .../33-jellyfin_10.8.12-1_all.deb ... Unpacking jellyfin (10.8.12-1) ... Selecting previously unselected package libaacs0:amd64. Preparing to unpack .../34-libaacs0_0.9.0-1_amd64.deb ... Unpacking libaacs0:amd64 (0.9.0-1) ... Selecting previously unselected package libbdplus0:amd64. Preparing to unpack .../35-libbdplus0_0.1.2-2_amd64.deb ... Unpacking libbdplus0:amd64 (0.1.2-2) ... Setting up libx264-152:amd64 (2:0.152.2854+gite9a5903-2) ... Setting up jellyfin-web (10.8.12-1) ... Setting up libxcb-render0:amd64 (1.13-2~ubuntu18.04) ... Setting up fonts-dejavu-core (2.37-1) ... Setting up libaacs0:amd64 (0.9.0-1) ... Setting up libopus0:amd64 (1.1.2-1ubuntu1) ... Setting up libx265-146:amd64 (2.6-3) ... Setting up libgraphite2-3:amd64 (1.3.11-2) ... Setting up libogg0:amd64 (1.3.2-1) ... Setting up libpixman-1-0:amd64 (0.34.0-2ubuntu0.1) ... Setting up libmp3lame0:amd64 (3.100-2) ... Setting up libzvbi-common (0.2.35-13) ... Setting up libxcb-shm0:amd64 (1.13-2~ubuntu18.04) ... Setting up libpciaccess0:amd64 (0.14-1) ... Setting up libxrender1:amd64 (1:0.9.10-1) ... Setting up libvpx5:amd64 (1.7.0-3ubuntu0.18.04.1) ... Setting up libbdplus0:amd64 (0.1.2-2) ... Setting up ocl-icd-libopencl1:amd64 (2.2.11-1ubuntu1) ... Setting up libzvbi0:amd64 (0.2.35-13) ... Setting up libvorbis0a:amd64 (1.3.5-4.2) ... Setting up libmpg123-0:amd64 (1.25.10-1) ... Setting up libwebp6:amd64 (0.6.1-2ubuntu0.18.04.2) ... Setting up libvorbisfile3:amd64 (1.3.5-4.2) ... Setting up fontconfig-config (2.12.6-0ubuntu2) ... Setting up libopenmpt0:amd64 (0.3.6-1) ... Setting up libharfbuzz0b:amd64 (1.7.2-1ubuntu1) ... Setting up libwebpmux3:amd64 (0.6.1-2ubuntu0.18.04.2) ... Setting up libvorbisenc2:amd64 (1.3.5-4.2) ... Setting up libfontconfig1:amd64 (2.12.6-0ubuntu2) ... Setting up libass9:amd64 (1:0.14.0-1) ... Setting up libbluray2:amd64 (1:1.0.2-3) ... Setting up jellyfin-server (10.8.12-1) ... Created symlink /etc/systemd/system/ → /lib/systemd/system/jellyfin.service. Setting up libcairo2:amd64 (1.15.10-2ubuntu0.1) ... Setting up libtheora0:amd64 (1.1.1+dfsg.1-14) ... Setting up jellyfin-ffmpeg5 (5.1.3-7-bionic) ... Setting up jellyfin (10.8.12-1) ... Processing triggers for systemd (237-3ubuntu10.57) ... Processing triggers for man-db (2.8.3-2ubuntu0.1) ... Processing triggers for ureadahead (0.100.0-21) ... ureadahead will be reprofiled on next reboot Processing triggers for libc-bin (2.27-3ubuntu1.6) ...
      # systemctl start jellyfin # service jellyfin start # systemctl status jellyfin
      jellyfin.service - Jellyfin Media Server Loaded: loaded (/lib/systemd/system/jellyfin.service; enabled; vendor preset: enabled) Drop-In: /etc/systemd/system/jellyfin.service.d └─jellyfin.service.conf Active: active (running) since Sat 2023-11-25 21:43:05 UTC; 1min 58s ago Main PID: 26517 (jellyfin) Tasks: 21 (limit: 4915) CGroup: /system.slice/jellyfin.service └─26517 /usr/bin/jellyfin --webdir=/usr/share/jellyfin/web --restartpath=/usr/lib/jellyfin/ --ffmpe Nov 25 21:43:12 tol-eressea jellyfin[26517]: [21:43:12] [INF] ServerId: 0294afcb54d54300b90cf678ce68ddfe Nov 25 21:43:12 tol-eressea jellyfin[26517]: [21:43:12] [INF] Executed all pre-startup entry points in 0:00:00.0931685 Nov 25 21:43:12 tol-eressea jellyfin[26517]: [21:43:12] [INF] Core startup complete Nov 25 21:43:12 tol-eressea jellyfin[26517]: [21:43:12] [INF] Executed all post-startup entry points in 0:00:00.3152099 Nov 25 21:43:12 tol-eressea jellyfin[26517]: [21:43:12] [INF] Startup complete 0:00:06.8236999 Nov 25 21:43:14 tol-eressea jellyfin[26517]: [21:43:14] [INF] StartupTrigger fired for task: Update Plugins Nov 25 21:43:14 tol-eressea jellyfin[26517]: [21:43:14] [INF] Queuing task PluginUpdateTask Nov 25 21:43:14 tol-eressea jellyfin[26517]: [21:43:14] [INF] Executing Update Plugins Nov 25 21:43:14 tol-eressea jellyfin[26517]: [21:43:14] [INF] Update Plugins Completed after 0 minute(s) and 0 seconds Nov 25 21:43:14 tol-eressea jellyfin[26517]: [21:43:14] [INF] ExecuteQueuedTasks
    3. Now the service is running.
  3. Connect via browser to Jellyfin
    root@tol-eressea:~# netstat -tulpn | grep [L]ISTEN
    tcp        0      0*               LISTEN      5081/Plex Plug-in [
    tcp        0      0*               LISTEN      4456/Plex Media Ser
    tcp        0      0*               LISTEN      4803/Plex Plug-in [
    tcp        0      0 *               LISTEN      2342/systemd-resolv
    tcp        0      0    *               LISTEN      2974/sshd
    tcp        0      0*               LISTEN      4591/Plex Tuner Ser
    tcp        0      0  *               LISTEN      10741/jellyfin
    tcp        0      0*               LISTEN      4534/Plex Plug-in [
    tcp6       0      0 :::32400                :::*                    LISTEN      4456/Plex Media Ser
    tcp6       0      0 :::80                   :::*                    LISTEN      3933/apache2
    tcp6       0      0 :::22                   :::*                    LISTEN      2974/sshd

    We see the service running on port 8096 (this is the default).

    We could set up Jellyfin behind a reverse-proxy server like Apache 2 httpd or nginx, but we're in "try it out mode" still and we'll just establish direct contact with Jellyfin remotely (read on).

    As tol-eressea, the server running Jellyfin, is headless, we can't perform set-up from that hardware, so we'll do it from a remote desktop by setting up a tunnel, then using a browser (and just use local port 8888 to access it):

    $ ssh tol-eressea -L 8888:localhost:8096
    russ@tol-eressea's password: *******
    Welcome to Ubuntu 18.04.6 LTS (etc.)
    Last login: Tue Dec 19 18:56:10 2023 from 192.168.105

    Locally (not on headless tol-eressea where Jellyfin is running), we launch a browser and type in http://localhost:8888/.
    This becomes http://localhost:8888/web/index.html#!/home.html.

  4. Let's do some light configuration. We'll set up the Movies library.

    This connects us to Jellyfin in the browser. We see "Welcome to Jellyfin" and "This wizard will help guide you through the setup process. To begin select your preferred language."

    Here's how that went (very cursorily):

    1. "...languages:" English
    2. Click the Next button.
    3. Username: jellifin
    4. Password: (blank)
    5. Click the Next button.
    6. Setup (sic) your media libraries
    7. + Add Media Library
    8. Content type: Movies
    9. Display name: Movies
    10. + Folders
    11. Folder: /plex-movies/Movies
    12. Shared network folder: (blank)
    13. OK button
    14. Library Settings
    15. Prefer embedded titles...
    16.   . . .
    17. OK button
    18. Skip adding a second media library.
    19. Click the Next button.
    20. Click the Next button.
    21. Click the Next button.
    22. Now, you should see a page with:
      • My Media (click to see Movies library; click on title to play)
      • Latest Movies (click to watch title thought to be latest)
      • You will observe that some poster art was chosen differently (from your Plex Media server) as well as summary blurbs being different. This will send us off on a search for how to make Jellyfin use Plex Media's metadata.
  5. Viewing your configured media on a streaming device like Roku...

    Without putting Jellyfin behind a reverse-proxy server like Apache 2, it's impossible to consume any media except via tunnel specially set up in a browser as illustrated just above. That leaves Roku out of the picture. Reverse-proxy set-up will be described separately below.

Putting Jellyfin Media Server behind a reverse-proxy server

Some aimless notes: the tutorials do not explain enough of why they work or they just magically work. I already have 13 web domains running perfectly behind Apache2 (http).

After much failed experimentation, this is what I have:

  • A virtual host file for Apache2, /etc/apache2/sites-available/jellyfin.conf
    —what should the server name be?
     1  <VirtualHost *:80>
     2    ServerName jellyfin
     3   #ServerName tol-eressea
     4   #ServerName
     5    ErrorLog   /var/log/apache2/jellyfin-error.log
     6    CustomLog  /var/log/apache2/jellyfin-access.log combined
     8    ProxyPreserveHost On
    10    ProxyPass            "/embywebsocket" "ws://"
    11      ProxyPassReverse   "/embywebsocket" "ws://"
    13    ProxyPass            "/" ""
    14      ProxyPassReverse   "/" ""
    15  </VirtualHost>

  • How to load modules for Apache2? Restarting Apache2:
    # systemctl restart apache2
    will fail without loading modules unless we enable the proxy modules. This is because of the use of Proxy here and there inside the Apache virtual host file above. So, we do this (use a2dismod to disable):
    # a2enmod proxy
    # a2enmod proxy_http
  • Pierce a hole for our port through the Ubuntu Server firewall. Here are some commands worth knowing including ones that succeed:
    # lsof -i tcp | 8096                 # (our port isn't open)
    (no output if the port hasn't not been opened)
    # nmap -p 8096 localhost             # (our port isn't open)
    Starting Nmap 7.60 ( ) at 2023-12-27 18:05 UTC
    Nmap scan report for localhost (
    Host is up (0.000046s latency).
    Other addresses for localhost (not scanned): ::1
    rDNS record for localhost.localdomain
    8096/tcp closed sac
    Nmap done: 1 IP address (1 host up) scanned in 0.34 seconds
    # nmap -p 32400 localhost            # (to compare)
    Starting Nmap 7.60 ( ) at 2023-12-27 18:06 UTC
    Nmap scan report for localhost (
    Host is up (0.000058s latency).
    Other addresses for localhost (not scanned): ::1
    rDNS record for localhost.localdomain
    32400/tcp open  plex
    Nmap done: 1 IP address (1 host up) scanned in 0.31 seconds
    # ufw allow 8096/tcp              # (pierce 8096 through firewall for TCP)
    Rule added
    Rule added (v6)
    # iptables -L -n | grep 8096     # (verify open)
    ACCEPT     tcp  --              tcp dpt:8096

Justification of virtual-host configuration and command-line URL

In the Jellyfin instance I'm running, I see this at the top of the Dashboard page and this has influenced the ServerName configuration of virtual host file, jellyfin.conf:

    Server >
    Server: tol-eressea            # (this is hostname of
    Version: 10.8.13
    Operating System: Linux        # (specifically Ubuntu Server)
    Architecture: X64

In Networking, I see...


    ┌── Server Address Settings ────
    │ Local HTTP port number:
    │ 8096
    │ ...

Assuming the above, I have concocted these URLs, which fail abjectly despite succeeding through the IP tunnel I set up originally (http://localhost:8888/):


Reverse-proxy success...

This is successful, it will make you log in, either http://tol-eressea:8096/web/index.html or

Roku success...

Because my Roku is on the same network as tol-eressea (I have several here at home), I am able to reach it from that device by simply giving it

  1. hostname and port in the form of (the Roku doesn't have /etc/hosts so it cannot know tol-eressea,
  2. username, jellyfin,
  3. and no password (since I explicitly did not set one).

Sharing with family and friends outside...

To allow access of your server from outside, you must punch a hole through your service router, for example, Google Box or other, for the port you're publishing on (8096 here in our example). I will tackle this soon...

Jellyfin Media Server: Random notes

Add your media library mapping at the very last minute, otherwise you have to trigger a metadata refresh. Everything as well as the scan-in date will already be set and won't change after the fact.

Music on Jellyfin...

I was never able to get Plex Media to serve up music. Jellyfin documentation is similarly sparse. I found the following through experimentation and oblique comments people made when I googled for answers.