Turn Your Raspberry Pi Into a Netflix-Style Media Server (Jellyfin + Cloudflare)
Turn Your Raspberry Pi Into a Netflix-Style Media Server (Jellyfin + Cloudflare)

How I built a personal streaming platform using Jellyfin, Docker, and Cloudflare — and fixed all the weird issues along the way.
Introduction
I’ve always wanted to build my own “mini data center” — something affordable, powerful, and actually useful. So, when I finally sat down with my Raspberry Pi 4, a 16GB SD card, and a 300GB external hard drive full of movies, I thought: “Why not make my own Netflix?” And not just locally — I wanted something I could access from anywhere. So this guide takes you through the exact process I used, including: • Installing Docker + Portainer • Mounting my external hard drive • Fixing the infamous Jellyfin playback error • Deploying Jellyfin • Making it accessible globally via Cloudflare Tunnel • Solving all the permission issues that nobody warns you about
If you follow this guide, you’ll have a fully working, cloud-accessible Netflix-style server running on a tiny Raspberry Pi. Let’s begin.
What You Need
Here’s my setup:
- Raspberry Pi 4 (2GB RAM)
- 16GB microSD card
- 300GB external hard drive (NTFS formatted — this will matter later!)
- Docker & Portainer installed
- Cloudflare account (free)
- Domain name (comon.tech in my case)
** Everything in this tutorial costs basically zero dollars.**
Installing Docker & Portainer
To make life easy, I deployed Jellyfin using Docker. Install Docker: curl -sSL https://get.docker.com | sh Add your Pi user to the docker group: sudo usermod -aG docker $USER Install Portainer: docker volume create portainer_data
docker run -d \
-p 8000:8000 \
-p 9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Now you can access Portainer at:
https://your-pi-ip:9443
Docker makes everything easier.
Plugging in the External Drive (Where My Problems Began)
My external hard drive had all my movies, so I plugged it into the Pi and ran:
lsblk
It showed up as /dev/sda1.
I mounted it like this:
sudo mkdir -p /media/movies
sudo mount /dev/sda1 /media/movies
I could even see all my movies:
- John Wick (2014).mp4
- Moonfall (2022).mkv
- The Martian (2015).mp4
Everything seemed fine…... BUT playback in Jellyfin failed. And that’s when I realized the real problem.
Fixing the Jellyfin Playback Error (The Hidden NTFS Issue)
When I installed Jellyfin, I could browse the movie list — but playing any movie gave this error:
Playback failed due to a fatal player error.
This was happening even before I exposed Jellyfin publicly. So it wasn’t Cloudflare. It wasn’t Jellyfin. It was the drive.
##❗THE CAUSE My external drive was NTFS (Windows format) and the Pi mounted it with root-only permissions. Meaning: Jellyfin could see the files, but not read them. Huge difference. To confirm:
ls -ld /media/movies
It showed something like:
drwx------ root root /media/movies
Yeah… Jellyfin had zero access.
✅ THE FIX
Install NTFS support:
sudo apt install ntfs-3g
Unmount the drive:
sudo umount /media/movies
Remount with proper permissions:
sudo mount -t ntfs-3g -o uid=1000,gid=1000,umask=022 /dev/sda1 /media/movies
Now check permissions:
ls -ld /media/movies
Should look like:
drwxr-xr-x comon comon /media/movies
🎉 Result
JELLYFIN PLAYBACK WORKS! This was the biggest issue of the entire project — once the drive was readable, everything else worked flawlessly.
Deploying Jellyfin with Docker Compose
Here’s the Docker Compose file I used:
version: "3.8"
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
network_mode: host
volumes:
- /media/movies:/media/movies
- /opt/jellyfin/config:/config
- /opt/jellyfin/cache:/cache
restart: unless-stopped
Run it (if you are running it directly from the CLI):
docker compose up -d
In my case, I was running it through Portainer, so I just restarted it
Jellyfin becomes available at:
http://your-pi-ip:8096
Add your media library:
- Go to Dashboard → Libraries → Add
- Select “Movies”
- Set the path to /media/movies
Your movies should instantly appear.
Your Pi will now Direct Play files, which is more stable.
Making Jellyfin Accessible Globally Using Cloudflare Tunnel
Cloudflare Tunnel allows you to expose Jellyfin securely without port forwarding. Install cloudflared:
curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
rm cloudflared.deb
Login:
cloudflared tunnel login
Create tunnel:
cloudflared tunnel create jellyfin-tunnel
Create config file:
sudo nano /etc/cloudflared/config.yml
bash```
Add:
tunnel: <tunnel-id>
credentials-file: /etc/cloudflared/<tunnel-id>.json
ingress:
- hostname: jellyfin.yourdomain.com (in my case jellyfin.comon.tech) service: http://localhost:8096
- service: http_status:404
## The bug you will likely face (I faced it too):
Cloudflare saves credentials in:
```/home/youruser/.cloudflared/```
But cloudflared expects it in:
```/etc/cloudflared/```
Fix:
```bash
sudo mv ~/.cloudflared/*.json /etc/cloudflared/
sudo chown root:root /etc/cloudflared/*.json
Start service:
sudo cloudflared service install
sudo systemctl start cloudflared
Now visit: https://jellyfin.yourdomain.com (in my case - https://jellyfin.comon.tech) You’ll see Jellyfin globally, securely, and with HTTPS.
Now only you (and whoever you allow) can stream.
Final Thoughts
Turning my Raspberry Pi into a Netflix-style media server was one of the most fun and useful projects I’ve done this year. I learned:
- NTFS permissions matter more than you think
- Docker makes Jellyfin deployment incredibly simple
- Cloudflare Tunnel is magic
- The Raspberry Pi is still one of the most powerful small computers for home labs
And now I have a personal media server, accessible from home, work, or anywhere in the world. If you build this too, you’ll wonder why you didn’t do it earlier.
About the Author
Collins Omondi is the founder of Comon Tech, leading the vision of building scalable digital infrastructure for Africa through AI-first, community-powered innovation.

