What did I use for this?
- Raspberry Pi 4 Model B 4GB RAM
- Micro-HDMI to HDMI cable
- Raspberry Pi Official USB-C Power Supply
- Raspberry Pi 4 Official Case
Ordered all of the above from Pimoroni.
(Ignore the Raspberry Pi Zero 2 W, it is for another project)
You can actually make it work on a Pi Zero 2 W, but the lowest I’d actually recommend is a Raspberry Pi 3B+ (1 GB). A Pi 4 (2 GB) is the practical baseline for a smooth, SSD-based Jellyfin server.
What “bare minimum” really depends on: Direct Play only (your TV/app natively supports the file’s codec): very light CPU. Transcoding (server converts video on the fly): heavy CPU/GPU → needs stronger Pi.
Best experience: Pi 5 (more CPU headroom, faster I/O).
- Micro SD (128 GB)
- SAMSUNG T5 EVO Portable SSD 2TB

What is a Raspberry PI?
- A tiny, low-cost computer about the size of a deck of cards.
- You can plug in power, HDMI, keyboard/mouse, and a microSD/SSD, then install an operating system (like Raspberry Pi OS).
- It’s great for DIY projects (media servers, retro gaming, home automation, learning to code).
- Models vary in power; the Raspberry Pi 4 has enough muscle for a home media server with USB 3.0 and true gigabit Ethernet.
What is a Jellyfin?
- Jellyfin is a free, open-source media server.
- It’s a self-hosted alternative to Plex/Emby: no subscriptions, no tracking, your data stays with you.
- You install it on a computer (like a Raspberry Pi), point it at your movies/TV/music/photos, and it organizes them with artwork and metadata.
- You can then stream your media to phones, tablets, browsers, smart TVs, or streaming sticks via the Jellyfin app or web interface.
- You get your own “Netflix-style” library without paying monthly fees.
How to do this?
The basic overview is to first format your MicroSD card with a Raspberry PI compatible OS. Once done insert the MicroSD card into the raspberry pi, connect a wired mouse, keyboard and an external monitor for the initial OS setup. After setup you can configure it to run ssh so that you can remotely login to the raspberry and dont need to use all the peripherals. Setup Jellyfin and connect it with your External SSD and transfer your media into the SSD and voila! You have your own streaming service.
(The steps mentioned here is for using Jellyfin internally within your own home network. You can obviously setup Jellyfin in an external VPS, connect it to a domain and then use it exactly like a streaming service across the internet)
1. Setup your Raspberry PI + Micro SD + OS of your choice
This step is simple and almost self explainatory. However if you are still unsure have a look at this Youtube tutorial:
For simplicity since I am using this internally within my own network, I have setup a simple username/password SSH authentication.
2. Update & give the Pi a stable IP
sudo apt update sudo apt full-upgrade -y sudo reboot
Next you have to setup a Stable IP. The best way to do this is via Router Reservation. In your router reserve the Raspberry PI’s IP address so that it persists across reboots and your Home Router which most of the time acts as the DHCP assigns the same IP to the raspberry pi.
If you have more than one raspberry pi, you can reserve the IP based on the PI’s MAC address.
Verify that you have the correct IP:
hostname -I
3. Mount the SSD at boot (ext4)
Identify the partition and format if needed:
⚠️ Formatting will erase all data
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,MODEL # suppose it's /dev/sda1 sudo umount /dev/sda1 2>/dev/null || true sudo mkfs.ext4 -L media1 /dev/sda1 # skip this if you already have data sudo mkdir -p /mnt/media sudo blkid /dev/sda1 # note the UUID
Add to
/etc/fstab
:UUID=<YOUR-UUID> /mnt/media ext4 defaults,nofail,x-systemd.automount 0 2
Activate:
sudo systemctl daemon-reload sudo mount -a df -h | grep /mnt/media
Create folders:
sudo mkdir -p /mnt/media/{Movies,TV,Music,Photos}
4. Permissions that “just work” (Pi user + Jellyfin)
Use a shared group and inheritance so files are always writable:
sudo groupadd media 2>/dev/null || true sudo usermod -aG media piuser sudo chown -R root:media /mnt/media sudo find /mnt/media -type d -exec chmod 2775 {} \; # setgid on dirs sudo find /mnt/media -type f -exec chmod 664 {} \; # Optional but great: default ACL so new files stay group-writable sudo apt -y install acl sudo setfacl -d -m g:media:rwx /mnt/media sudo setfacl -m g:media:rwx /mnt/media
Open a new SSH session so your new group applies.
5. Install Jellyfin (official repo, bookworm, arm64)
sudo apt install -y ca-certificates curl gnupg curl -fsSL https://repo.jellyfin.org/jellyfin_team.gpg.key \ | gpg --dearmor \ | sudo tee /usr/share/keyrings/jellyfin-archive-keyring.gpg >/dev/null sudo tee /etc/apt/sources.list.d/jellyfin.sources >/dev/null <<'EOF' Types: deb URIs: https://repo.jellyfin.org/debian Suites: bookworm Components: main Architectures: arm64 Signed-By: /usr/share/keyrings/jellyfin-archive-keyring.gpg EOF sudo apt update sudo apt install -y jellyfin sudo usermod -aG media jellyfin sudo systemctl enable --now jellyfin sudo systemctl restart jellyfin
Jellyfin is now live on at: http://<pi-ip>:8096
⚠️ (If your OS is 32-bit, change Architectures: arm64 → armhf.)
6. (Optional) Put Jellyfin’s data/cache on the SSD
This step is optional but it reduces SD-card wear and tear through all the reads and writes.
sudo systemctl stop jellyfin sudo mkdir -p /mnt/media/.jellyfin-data sudo rsync -aH /var/lib/jellyfin/ /mnt/media/.jellyfin-data/lib/ sudo rsync -aH /var/cache/jellyfin/ /mnt/media/.jellyfin-data/cache/ sudo mv /var/lib/jellyfin /var/lib/jellyfin.bak sudo ln -s /mnt/media/.jellyfin-data/lib /var/lib/jellyfin sudo mv /var/cache/jellyfin /var/cache/jellyfin.bak sudo ln -s /mnt/media/.jellyfin-data/cache /var/cache/jellyfin sudo chown -R jellyfin:jellyfin /mnt/media/.jellyfin-data sudo systemctl start jellyfin
7. First-run wizard & libraries
Open http://<pi-ip>:8096:
- Create admin user.
- Add libraries with the exact folders (e.g.,
/mnt/media/Movies
,/mnt/media/Photos
, later/mnt/media/TV
).
- Finish → Jellyfin scans in the background.
Add a TV library later:
Dashboard → Libraries → Add Media Library → TV Shows → folder
/mnt/media/TV
Recommended naming:
TV/Show Name (2016)/Season 01/Show Name S01E01.mkv TV/Show Name/Season 00/Show Name S00E01.mkv # specials
8. Copying media from your Mac (best options)
A. SMB (Finder-friendly & fast)
Apple’s SFTP in Finder is unreliable/removed; SMB is the smooth path. Install & configure Samba on the Pi:
sudo apt update sudo apt install -y samba sudo tee -a /etc/samba/smb.conf >/dev/null <<'EOF' [media] path = /mnt/media browseable = yes read only = no guest ok = no create mask = 0664 directory mask = 0775 force group = media EOF sudo smbpasswd -a piuser sudo systemctl restart smbd
On your Mac: Finder → Go → Connect to Server… →
smb://<pi-ip>/media
→ log in as piuser.(Tip: you can auto-mount the share at login by adding it to Login Items.)
B. rsync over SSH (great for incremental syncs)
From your Mac:
rsync -avhP --partial --exclude='.DS_Store' --exclude='._*' \ "/Users/boredtoolbox/Movies/" \ piuser@<pi-ip>:/mnt/media/Movies/
Add
--chmod=Du=rwx,Dg=rwx,Fu=rw,Fg=rw
if you ever see odd perms on arrival.macOS ext4 note: If you prefer to unplug the SSD and copy directly on the Mac, macOS can’t write ext4 natively. Either install a driver (e.g., Paragon extFS) or reformat the SSD as exFAT (cross-platform) and mount with uid/gid/umask options on the Pi. Otherwise, keep the SSD on the Pi and copy over the network (SMB/rsync). Another option is basically use Linux, which can write ext4 natively, to copy the data over to the SSD
9. Troubleshooting
A. Jellyfin shows no items? Quick fixes
- Check the path: Dashboard → Libraries → Folders must be /mnt/media/... (not a mistyped path).
- Check read access:
sudo -u jellyfin ls -lah /mnt/media/Movies | head id jellyfin | grep media || { sudo usermod -aG media jellyfin; sudo systemctl restart jellyfin; }
- Scan: Dashboard → Libraries → Scan all libraries (or Scheduled Tasks → Scan media library → Run).
- Mount is RW:
mount | grep ' /mnt/media ' # should include 'type ext4' and 'rw'
B. Stability: SSD quirks, power, and logs
If the Pi “crashes” or vanishes under load with a USB SSD, it’s usually bus power or a UAS quirk. But here are some ways you can check, run these on the pi after it “comes back” or you force a power off and power on:
Did it actually reboot, or just hang?
last -x | head # shows recent reboots/shutdowns uptime -s # boot time
- If you see recent reboot entries → likely undervoltage or thermal.
- If no reboot, but it becomes unreachable → often network or USB/power sag causing a freeze.
Check for undervoltage / thermal throttling
vcgencmd get_throttled dmesg -T | egrep -i 'under-voltage|throttl|voltage' vcgencmd measure_temp
Interpret
get_throttled
(hex flags):- 0x0 = healthy
- bit 0 = currently undervoltage
- bit 16 = undervoltage has occurred
- bit 2/18 = throttled (often power/heat)
- bit 3/19 = soft temp limit (hot)
If you see any of those bits set (especially 0/16), it’s a power problem even if the red LED looked “on”.
Fast power fixes (most common root cause)
- Use the official Raspberry Pi 4 PSU (5.1V, 3A) or a known-good 5V/3A USB-C supply with a short, thick cable. Phone chargers and long/thin cables sag.
- Your USB SSD can spike current; try one of:
- Plug the SSD via a powered USB 3.0 hub.
- Try a different SSD/cable (some USB-SATA bridges are noisy).
- Temporarily unplug the SSD for 30–60 min and see if the “shutoffs” stop → confirms power budget issue.
- Avoid back-powering via hubs/TV ports.
Thermal check (less common, but easy to rule out)
Pi 4 soft limit is ~80 °C.
watch -n1 vcgencmd measure_temp
If you’re flirting with 80 °C, add a fan or heatsink, or improve airflow. Bits 3/19 in
get_throttled
mean temps are driving throttling.Make logs persistent so we can catch the exact cause next time
sudo mkdir -p /var/log/journal sudo systemd-tmpfiles --create --prefix /var/log/journal sudo systemctl restart systemd-journald
Then after the next incident:
sudo journalctl -b -1 -e --no-pager # end of previous boot's logs
USB/SSD sanity checks
- Look for filesystem/USB resets:
dmesg -T | egrep -i 'usb .* reset|xHCI|ext4.*error|I/O error'
- Quick disk health:
sudo apt -y install smartmontools sudo smartctl -a /dev/sda | sed -n '1,80p'
Network-only vanishing? (power is fine, but you lose SSH)
Sometimes it’s just Wi-Fi saving power:
# Disable Wi-Fi power save sudo tee /etc/NetworkManager/conf.d/wifi-powersave-off.conf >/dev/null <<'EOF' [connection] wifi.powersave = 2 EOF sudo systemctl restart NetworkManager
Or stick to Ethernet for the server.
Stability: SSD quirks, power, and logs
If the Pi “crashes” or vanishes under load with a USB SSD, it’s usually bus power or a UAS quirk:
- Power: Use the official 5.1V/3A PSU (short, thick cable). A powered USB 3.0 hub fixes brownouts instantly.
- Disable UAS for quirky enclosures:
lsusb # note your SSD’s ID, e.g. 04e8:6200 (Samsung T5 EVO) sudo cp /boot/firmware/cmdline.txt{,.bak} echo "$(cat /boot/firmware/cmdline.txt) usb-storage.quirks=04e8:6200:u" | sudo tee /boot/firmware/cmdline.txt sudo reboot dmesg -T | egrep -i 'uas|usb-storage.quirks' # should say UAS ignored, using usb-storage
- Persistent logs (for post-mortems):
sudo mkdir -p /var/log/journal sudo install -d -m 0755 /etc/systemd/journald.conf.d printf "[Journal]\nStorage=persistent\nSystemMaxUse=200M\n" | sudo tee /etc/systemd/journald.conf.d/persistent.conf sudo systemctl restart systemd-journald
After any reboot:
sudo journalctl -k -b -1 -p warning..emerg --no-pager | tail -n 200
Reference:
Photo by Nikolay Kovalenko on Unsplash