This post serves as a personal guide to running a Jellyfin server locally using an external hard drive. The following assumes:
- Debian GNU/Linux 12+ (I’m using a Raspberry Pi 4)
- External hard drive (e.g.
/dev/sda1
) mounted at something like/media/<username>/<hd name>
1. User/group setup
Jellyfin runs as a systemd service with its own user and group, both of which are usually just jellyfin
. To verify this:
$ cat /lib/systemd/system/jellyfin.service | grep "User\|Group"
User = jellyfin
Group = jellyfin
To give jellyfin access to your content, you could of course make it the owner and chmod
away. But you’ll probably want to the ability to create new users in the future and given them access as well. Furthermore, manually setting ownership and permissions each time can be cumbersome and error-prone, not to mention you’ll need to mount your drive as read-write. We’ll see later on how to set permissions automatically at mount-time.
The alternate way to do this is to create a group. New users that need to access media can just be added to that group.
$ sudo groupadd media # create group named media
$ sudo usermod -aG media jellyfin # add jellyfin to group
2. Mounting your drive
You can mount your drive manually with mount(8)
, but the better way is to have it done automatically at boot time. The simplest way to do this is to add an entry to /etc/fstab
, which is read by mount(8)
to determine the overall filesystem structure. (Note that this approach is quite primitive, and there are more modern tools such as udev
, which can handle userspace events as well, but for now we’ll stick to fstab
, as it is the de facto option and available on most Unix systems.)
An entry in /etc/fstab
looks like:
<device> <dir> <type> <options> <dump> <fsck>
First, to get the <device>
uuid and filesystem <type>
, we can search for our drive in blkid(8)
:
$ blkid | grep "/dev/sda1"
/dev/sda1: UUID="93033593-60b5-38ef-8086-e434e74192b0" BLOCK_SIZE="4096" LABEL="TOSHIBA_EXT" TYPE="hfsplus" PARTUUID="fea07a4a-01"
Next, <dir>
is the mount point, e.g. /media/jamesma100/TOSHIBA_EXT
. For <options>
, we’ll want the following:
ro
to mount as read-onlyuid
andgid
are the user/group for the device when mounted. We’ll wantuid
to be yourself andgid
to be set to themedia
group we created earlier. To get these ids, you can run$ id uid=1000(jamesma100) gid=1000(jamesma100) groups=1000(jamesma100),...,1001(media)...
umask=022
to give read-write permissions to yourself and read-only permissions to others. The permissions will now be666 - 022 = 644
for files and777 - 022 - 755
for directories.
The last two fields are filesystem checks - <dump>
is for backups and <fsck>
checks for filesystem corruption. I usually set these to off (0) and on (1), respectively.
Putting it all together:
$ echo "UUID=93033593-60b5-38ef-8086-e434e74192b0 /media/jamesma100/TOSHIBA_EXT hfsplus ro,umask=22,uid=1000,gid=1001 0 1">> /etc/fstab
To test the newly configured fstab
without rebooting, run the following:
$ systemctl daemon-reload
$ sudo mount -a -v
This should remount all your partitions, and the -v
(verbose) option should tell you which, if any, were unsuccessful.
One last thing to note here: if any of the -o
options failed, mount
will not notify you! As an example, I ran into an issue where the filesystem on my hard drive was mounted as read-only, despite specifiying the rw
option since I had to make some modifications.
I had to resort to dmesg(1)
to figure out what was going on.
$ dmesg | tail -n 1
[13719.862245] hfsplus: write access to a journaled filesystem is not supported, use the force option at your own risk, mounting read-only.
Sneaky sneaky!
3. Managing your server
After changing any configuration, you should run
$ systemctl daemon-reload
$ systemctl restart jellyfin
To stop the server:
$ systemctl stop jellyfin
Jellyfin logs go under /var/log/jellyfin
. To view status:
$ systemctl status jellyfin
4. Dealing with crashes
If your hard drive was improperly unmounted for any reason, such a crash, it will usually still remount but prompt the user to perform a consistency check. You should do that and then remount it. Once again, it’s necessary to dig through logs; you will not be notified!
$ dmesg | tail -n 2
[ 137.881974] hfsplus: filesystem was not cleanly unmounted, running fsck.hfsplus is recommended. leaving read-only.
[ 170.342788] hfsplus: Filesystem was not cleanly unmounted, running fsck.hfsplus is recommended. mounting read-only.
Now that we’ve confirmed the issue, we can use fsck
to do a repair. Keep in mind that you will need a fsck
implementation tailored to the filesystem type of your storage device, since fsck
operates directly on disk-specific data structures. In my case, I need a fsck.hfsplus
for the HFS+ filesystem, which is included in the hfsprogs package.
$ sudo apt-get -y install hfsprogs
$ sudo fsck.hfsplus /dev/sda1
$ sudo mount -a -v