Jellyfin media server, and using remote disks

Have I mentioned I have discovered Jellyfin ?

Everyone wants their own home media server to avoid having to locate that elusive DVD you want to watch again, which may have degraded to the point it is unwatchable anyway so should have been backed up to disk in the first place. Of course backing it up to disk may still mean you have to move a disk to the TV you want to watch it on, so still moving things around. A media server solves that.

There are quite a few about, Kodi has existed for what seems like forever and is probably the gold standard, Plex has been around for a while, and I have found Jellyfin.

I chose to use remote external hard drives to host my media and I had to work through some issues for that so I have a section on the issues you will hit and how to work around them at the end of this post, they were not issues with Jellyfin but with permissions.

A bonus for me is that the Jellyfin client application can be installed on Chromecast devices (I have two) and Android tablets (I have one) and smart android based TVs which can access your Jellyfin media server just using your home network internal 192.168.x.x address (note: Android tablets can cast to the chromecast using the Jellyfin app, the the Linux Jellyfin app cannot… and web browsers cannot cast to chromecast on internal network addresses either so probably the google library was used; lots of internet search results saying that is because google requires you to cast to a DNS name secured by https (presumably via its DNS servers) so having a client installable on the chromecast (or smart TV) that can locate the media only by local ip-address was essential to me).

Note: google searches while investigating the case issue show PLEX is not affected… because PLEX routed through the PLEX servers; not sure exactly how that works but I wanted something that could use 192.168.1.nnn addresses and not go near the internet so chose Jellyfin.

Jellyfin and other similar media library implementations will helpfully try to locate movie covers, cast biographies, and a lot of other stuff by querying internet servers such as IMDB for every movie or show you add. To get any useful information from those queries it relies on you having a directory stucture and naming standard each solution expects and none of us tend to backup in the expected naming standard so expect a lot of folder renaming and file relocations just to get it to look like you spent some time on it and expect to have to locate DVD covers manually, Jellyfin will try to work out how to display your media backups as they are if possible and also has a “folder” view that can be enabled, but that is not as pretty as taking the time into sorting them into movies and shows (assuming you already backup in categories here).

I would say if you are copying in a huge archive of backups to a media server for the first time let it do the lookups (in my case it populated about 5% of my titles) and then turn external lookups off and just enter everything yourself going forward; a bit of effort in locating media covers and movie info but easier than trying to rename a decades worth or archives and constantlt rescanning.

Anyway, why did I chose Jellyfin over the others

  • It has a damn very footprint. I created a new Debian12 VM with only 1Gb memory assigned, with 4Tb of movies and shows (on a remote external disk) for it to scan/manage and it is using zero swap… but I did create a new VM rather and install natively than use a container (jellyfin provide a docker container) as that best suoted hos I wanted to use it
  • Even if naming standards are not followed it can still in many cases work out shows and movies
  • They have implemented a optional “folder view” facility, not brilliant but it can find and handle some edge cases with a lot of directories to traverse; not especially well but it beats having to rename a decades worth of collected backups
  • Easy to manually edit images and metadata to put DVD cover pictures and year of release etc into the displays, if you remember to tick the store images locally option for each library
  • There is a jellyfin client that can be installed on ChromeCast devices (and presumably any android TV) that can directly use the Jellyfin server by internal network ipaddress
  • Media can be added via local directories, nfs or samba (you really should read my notes on remote disks below first)
  • It can be installed from the Debian12 repos into me new VM with a simple “apt install jellyfin”

How I decided to use it

I chose a VM rather than a container as a lot of information (such as save graphics images locally) does not seem to be stored in the directories on the media library disk themselves and as it takes a lot of effort to locate and setup images I would not want to lose all that info which I would if I deleted a container in order to start it on another machine; moving a VM disk to another machine will not lose any info (moving a VM disk I find easier than snapshotting containers and volumes and trying to move them about). I also store a copy of the VM disk on each media external disk.

While Jellyfin allows the use of remote disks within the application itself (I think it can mount samba/CIFS directories itself) I decided to use only local filesystem mount points such as /mnt/media1 /mnt/media2 etc and mount remote disks manually so I have control over what remote disks are mounted and can move the external disks between machines as needed without needing to reconfigure jellyfin as the application will always refer to teh same mountpoints (plus I would prefer to use NFS rather than CIFS); so both the disks and VM are portable and do not need to be on the same physical machine :-). Be sure to read my notes on Samba/CIFS and NFS issues you will hit below.

Another advantage of using a VM is that I can keep a resonably up to date copy of the VM disk image on the external media disk itself so as long as I backup the media disk I can spin it up anywhere (yes a snapshot of a container could have been taken if I had gone the container way; containers are a lot harder to upgrade without losing data however).

So my key requirements were

  • must not need to go anywhere near the internet, all streaming to be confined to my 192.168.1.x network
  • must have a small footprint (I have so many VMs I am maxing out all my dedicated VM machines)
  • must be usable on ChromeCast [due to casting limitations of the google APIs that means must have a client app]
  • must allow me to move external library disks about; I’m exhausting available USB slots in physical machines and despite whatever anyone tells you USB powered disks (even on on a powered USB hub) just won’t work, so I have to move them about as needed
  • must be easy to setup and use

On the last… while easy to setup and use it requires a specific directory structure which my backup disks do not use. As my backup disks are in a structure that makes sense to me and I choose not to change those I needed another disk to re-layout files for Jellyfin (actually another two, backup everything !, a copy of the VM image is also backed up on the disks providing the libraries which is another advantage of using a VM).

Also on the easy to use the web interface can also easily update DVD cover images from localy saved images (ie: from imdb that may have media cover shots of something snapped from a camera) and easy to edit the metadata fields (if you remeber to tick the store locally box).

While I am a strong believer in backup everything identically; out of pure habbit all my initial testing was on a T2B external disk LUKS encrypted with an ext4 filesystem (nfs mounted to the Jellyfin VM). When I needed to move to a 4Tb I left it as FAT32 so I could test for any issues with CIFS/Samba and see how it compared to NFS (result: CIFS works OK, NFS seems to be faster and have less pauses; all my interfaces and switches are 1Gb but the chomecasts attached to the TVs are using wireless, so the only difference was a change from NFS to CIFS ands I only see pausing using CIFS [and the disk was changed from 2Tb EXT4 to 4TB FAT32] but the pausing is infrequent so certainly usable.

OK, so how to do it

Debian has the Jellyfin server package. Create a new Debian12 VM (as noted only 1Gb of memory is needed, I allocated 2 vCPUs but it can probably work with 1); then “apt update;apt upgrade -y;apt install jellyfin;systemctl stop jellyfin;systemctl disable jellyfin”.

The stop and diable of the jellyfin service you may be curious about… remember my media libraries are on external disks that may be on remote machines (always remote for a VM actually), I need to mount them onto /mnt/mediaN for my setup before manually starting jellyfin.

Then copy some files in using the Movies/Shows filesystem structure; “systemctl start jellyfin”; use the Web interface to add Libraries (I kept shows and movies in seperate libraries as recommended). Jellyfin will scan the libraries as they are added but it will take a while.

To add additional media later you can just copy them into the folders already added to libraries (I had turned off the automatic regular scans for new files but it either does it daily anyway or I missed turning it off in at least one library I copied files into later). You can either wait for them to be detected over time or from the Web interface dashboard request a library scan queued.

Oh yes, you should also create a new user/admin id and remove the default. You can also add additional non-admin users such as kids in which case the rating of teh moves/shows can limit what they can see… I found that pointles as the chromecast app remembers who set it up/logged-on and automatically logs on as that user each time anyway.

Thats it. You can now watch media using the web browser interface. Obviously you want a lot more than that so install the official Jellyfin client application on you tablets, TVs and chromecasts… note when you install the client apps they expect your jellyfin server to be running and will search for it on your home network at install time at which point I find just confirming the ipaddr found is correct and manually entering username/password works better
that trying to run back to the admin gui to look for some hot-plug OK button that never seems to appear.

Then enjoy the benefit of having your media available anywhere… and what I really like is just being able to back-arrow out of something I am watching in the living room and exit the app, and starting the app in the bedroom and going to the “continue watching” section and resume where I left off; don’t know how I lived without it.

And a seperate section on the issues of using remote disks

Disk labels

Lots of external disks have default disk labels with spaces in the name (ie: “One Touch” for seagate one touch drives); that is difficult to manage for entries in fstab, exports and samba. Install gparted, unmount the disk, use gparted on the partition (ie: gparted /dev/sdc2) right click on the partition and change the label; this does it non-destructively. That is a lot esier than trying to figure out where quotes and backslashes are needed in configuration files… and not all config files allow spaces at all.

Disk mount locations, permissions and issues

What you must remember for all these example discussed here is that how I have decided to use Jellyfin is with a remote disk (as my Jellyfin instance runs in a VM the disk will always be remote even if plugged into the same physical machine as the VM) and to avoid having to reconfigure the VM whenever the disk is moved Jellyfin within the VM is always configured to look for its libraries at /mnt/media1. All discussions and examples are related to getting the disk available at /mnt/media1 and writeable by the jellyfin user in the VM.

It should also probably be noted that as things like image uploads seem to be stored in locations within the VM rather than the media disk the media disk(s) probably does not have to be writeable for Jellyfin use but as I had issues with permissions with CIFS shares everything here discusses writeable as it will probably be helpful to know for other unrelated projects as well.

On Linux machines manually plugging in an external disk will normally place it under the logged on users /media/username directory (Debian) or /run.media/username (rhel based). for FAT32 disks (the default for large external HDs) all the files will be set to the ownership of the logged on user; for EXT4 disks I think ownership of permissions is treated as for a normal ext4 filesystem but of course only the logged on user can traverse the initial /media/username directory path.

On Linux machines a FAT32 disk/directory must be exported using Samba (NFS cannot export FAT32). Samba can probably also export an EXT4 filesystem so you may think it easier just to go with Samba; just bear in mind EXT4/NFS is faster and in my experience more stable.
On Windows machines even though disks may get a different drive letter they seem to remember when a drectory has been set to shared on them, but it always pays to check each time.

If you plug in your “Library” disk to a Windows machine it must be FAT32/NTFS and can only be shared via CIFS. If plugging into a Linux machine you can use EXT4 shared by either NFS or Samba or if a FAT32 disk it can only be shared by Samba.

My preference is for EXT4 filesystems as I like to LUKS encrypt all my external drives. I also dislike the need to install and configure Samba on each machine I might want to plug the external disk into when I already have NFS on all the Linux ones anyway.

The main issues with using EXT4 filesystems is that they must be attached to a Linux machne and user ownership and permissions are correctly maintained; an issue in that the Jellyfin processes are not going to be running under the same userid you used to populate the files on your disk, if mounted using samba that can be bypassed (see Samba notes below) but if NFS mounting you must change ownership of all the directories and files to the jellyfin user, which makes it difficult to add additional files using your own userid.

The issues with FAT32 filesystems are that while they can be plugged into both Windows and Linux machines while easy to share from a Windows machine on Linux you will have to install and configure Samba on each machine you might plug it into. You must remember to override the ownership of the remote mount as discussed below on Samba mounts.

On the Jellyfin VM you need to install either the NFS or CIFS tools (or both) depending on what you will use.

Using NFS mounts

You must ensure all the directories on the remote disk are traversable/updateable by the Jellyfin user. But actulally mounting a EXT4 disk using NFS is simple.

Examples are for a EXT4 filesystem with a disk label of JELLYFIN so it is mounted under /media/mark, my Library folders are all under an Exported directory.

An /etc/exports entry on the Linux server exporting the disk (the Jellyfin VM is named jellyfin), when updating/changing it remember to “systemctl restart nfs-mountd.service”.

/media/mark/JELLYFIN/Exported jellyfin(rw,sync,no_subtree_check,no_root_squash)

Also on the server exporting the disk (only has to be done once) “firewall-cmd –add-service nfs;firewall-cmd –add-service nfs –permanent”.

An /etc/fstab entry on the Jellyfin VM, when updating fstab remember to “systemctl daemon-reload”. Note that I use noauto as I choose to manually mount my remote media.

vmhost3:/media/mark/JELLYFIN/Exported  /mnt/media1   nfs noauto,nofail,noexec,nosuid,noatime,nolock,intr,tcp,actimeo=1800 0 0

Using CIFS/Samba mounts to a disk on a Windows machine

Examples are for a FAT32 filesystem, my Library folders are all under an Exported directory.

On the Windows machine use file explorer to select the Exported directory, right click on it and select properties, select the sharing tab and share the directory with a name of Exported.

Critical notes: to avoid having to enter Windows user credentials each mount use a creditials file as shown below; and even more importantly the mounted files will be default only be updateable by root so use the the fstab CIFS mount options uid/gid to set owndership (as far as the VM mounting it is concerned) to the jellyfin UID and GID (values for you install can be obtained by grepping jellyfin from passwd and group). With those set correctly a “ls -la” of the mounted filesystem will show owner:group as jellyfin which is required.

An /etc/fstab entry on the Jellyfin VM, when updating fstab remember to “systemctl daemon-reload”.

//192.168.1.178/Exported /mnt/media1 cifs noauto,uid=103,gid=110,credentials=/home/jellyfin/smb_credfile_windows.txt

An example of a credentials file for a Win10 Home machine being used to “share” the directory

username=windozeuser
password=userpassword
domain=

Using CIFS/Samba mounts to a disk on a Linux machine running Samba

Obviously the first step on the machine you will be plugging the disk into would be “apt install samba -y” (or dnf install if on a rhel type OS).

Then “systemctl stop smbd;systemctl disable smbd”. Required as not only do we need to edit the config remember that we are using external disks that may not be plugged in so lets not allow Samba to automatically start.
At this time may as well also “firewall-cmd –add-service samba;firewall-cmd –add-service samba –permanent”.

Critical notes: remembering that externally mounted disks are normally mounted under /media/username and only username can traverse the path you do not want any defaults when the directory is shared by samba to anonymous users (anonymous users will be treated as user nobody which will not have permissions which is why normally Samba mounts are on world writeable directories or secured to a group/user in smbpasswd but we do not want to waste time with that here), so you must use the force_user entry to the user that owns the files on the server which in my case is always going to me me (mark) for disks under /media/mark.

Example of share needed to be added to /etc/samba/smbd.conf (after changes “systemctl restart smbd”).

[Exported]
path = /media/mark/JELLYFIN/Exported
browseable = yes
writable = yes
read only = no
guest ok = yes
force user = mark

Critical notes: to avoid having to enter Windows user credentials each mount use a creditials file as shown below; and even more importantly the mounted files will be default not be uodateable by the jellyfin user so use the the fstab CIFS mount options uid/gid to set ownership (as far as the VM mounting it is concerned) to the jellyfin UID and GID (values for you install can be obtained by grepping jellyfin from passwd and group). With those set correctly a “ls -la” of the mounted filesystem will show owner:group as jellyfin which is required.

An /etc/fstab entry on the Jellyfin VM, when updating fstab remember to “systemctl daemon-reload”.

//192.168.1.179/Exported /mnt/media1 cifs noauto,uid=103,gid=110,credentials=/home/jellyfin/smb_credfile_samba.txt

An example of a credentials file for a Linux machine with default samba setup (default domain is WORKGROUP) and the Exported directory above (Yes it does prompt for user root and an empty password (on Debian12 with the default setup anyway; probably need to use smbpasswd to setup groups/users but not for this jellyfin post)

username=root
password=
domain=WORKGROUP

CIFS/Samba troubleshooting notes

On the client server you are going to mount onto you must “apt install cifs-utils” (DFebian12, rhel may use a different package name). It installs a lot of stuff so you may want to remove it again after testing.

To list shares available on the remote server using/testing a credential file

smbclient --authentication-file=/home/jellyfin/smb_credfile_samba.txt --list 192.168.1.179

To list shares available on the remote without a credential file (will be prompted for empty ROOT password)

smbclient --list 192.168.1.179

To manually mount/test a mount works before adding it to fstab
Below prompts for password for ROOT@ipaddr, which is just enter anyway

mount -t cifs -o uid=103,gid=110 //192.168.1.179/Exported /mnt/media1

Or with a credential file with root and blank password skips that prompt

mount -t cifs -o uid=103,gid=110,credentials=/home/jellyfin/smb_credfile_samba.txt //192.168.1.179/Exported /mnt/media1

On the Samba server side logs are kept in /var/log/samba and any mount errors if the client was able to contact the server will be in a file named log.servername (so in my case log.jellyfin as jellyfin is the client servername) or if the server name is not resolveable log.ipaddress if you have left the rest of the default samba configuration file untouched.

Update: 09Apr2024
I have discovered using the default FAT32 file system that comes on standard 4Gb external disks either foesn’t like large files or Linux doesn’t play well with that filesystem type; I for some reason (porability) decided to use the default filesystem on a seasgate 4Tb external drive mounted to Linux; a directory containing large files became corrupt [Linux showed “d?????????”; plugging it into a windows machine windows found no errors but when trying to delete the damaged directory windows even though file explorer showed it, it also said the directory did not exist and may have been moved when trying to delete; none if the hits on solutions a google google found on that windows error (there were many, this issue seems to be common for FAT32) worked].
So, don’t use FAT32. I have now ditched FAT32/CIFS for the disk and gone back to EXT4/NFS to serve the disk to my Jellyfin VM as I have been using that combination to serve remote disks for years without issue.
Up to you of course.

About mark

At work, been working on Tandems for around 30yrs (programming + sysadmin), plus AIX and Solaris sysadmin also thrown in during the last 20yrs; also about 5yrs on MVS (mainly operations and automation but also smp/e work). At home I have been using linux for decades. Programming background is commercially in TAL/COBOL/SCOBOL/C(Tandem); 370 assembler(MVS); C, perl and shell scripting in *nix; and Microsoft Macro Assembler(windows).
This entry was posted in Home Life. Bookmark the permalink.