Cloud-Native Media Server: rclone + Jellyfin on a Budget VPS
Running your own media server usually means choosing between a home NAS (cheap but limited by your upload speed) or a VPS (fast but expensive at scale). There’s a third path: use object storage for the bulk of your media and stream it through a lightweight VPS to your devices.
The Architecture
%%{ init: { 'look': 'handDrawn' } }%%
graph LR
A[Cloud Storage<br/>Wasabi / Dropbox<br/>2TB+] -->|rclone mount<br/>encrypted| B[VPS<br/>Jellyfin server<br/>2 vCPU]
B -->|stream| C[TV / Mobile / Browser]
A -->|direct upload<br/>rsync / FTP| D[Upload station<br/>home PC]
The VPS doesn’t store the media — it streams it from cloud storage. The actual 2TB lives in cheap object storage (~$6/month on Wasabi). The VPS just handles authentication, transcoding, and delivery.
Why rclone?
rclone can mount object storage as a local filesystem with encryption:
# Install rclone
curl https://rclone.org/install.sh | sudo bash
# Configure your cloud storage
rclone config
# Choose "s3" provider, endpoint, and credentials
# Set up encryption
rclone config
# Choose "crypt" backend on top of s3
# This encrypts files before they leave your machine
The encryption layer means your media is private even if the cloud provider has a breach. Files are encrypted with a passphrase you control, and only the VPS (with the decryption key) can read them.
Mounting with Systemd
# /etc/systemd/system/rclone-media.service
[Unit]
Description=rclone media mount
After=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/rclone mount \
--vfs-cache-mode writes \
--allow-other \
--dir-cache-time 72h \
--poll-interval 15s \
crypt-media: /mnt/media
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
systemctl enable rclone-media
systemctl start rclone-media
--vfs-cache-mode writes is critical — it caches writes locally before uploading, preventing data loss on transient disconnects. --poll-interval 15s ensures newly uploaded files appear quickly in Jellyfin.
Jellyfin Setup
# docker-compose.yml
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
network_mode: host
volumes:
- ./config:/config
- ./cache:/cache
- /mnt/media:/media:shared
environment:
- TZ=Europe/Warsaw
restart: unless-stopped
docker-compose up -d
Jellyfin runs with --network-mode host to simplify DLNA and casting. Point it at /media (where rclone mounts the encrypted cloud storage) and it indexes everything automatically.
Transcoding Considerations
%%{ init: { 'look': 'handDrawn' } }%%
graph TD
A[Client requests<br/>H.265 4K] --> B{Jellyfin detects<br/>codec mismatch?}
B -->|direct play<br/>client supports codec| C[Stream from<br/>cloud directly]
B -->|transcode needed<br/>client is weak| D[VPS transcodes<br/>to H.264]
D --> E[Stream to<br/>client]
C --> F[No VPS<br/>CPU used]
E --> G[Heavy VPS<br/>CPU usage]
The VPS transcodes on the fly when a client can’t handle the original format. This is the main reason you need 2 vCPUs — 4K transcoding is CPU-intensive. For 1080p h.264, a single vCPU is usually enough.
Upload Workflow
%%{ init: { 'look': 'handDrawn' } }%%
graph LR
A[Home PC] -->|rsync over SSH| B[VPS<br/>temp directory]
B -->|rclone move<br/>to crypt-media| C[Encrypted<br/>cloud storage]
C -->|auto-appears in| D[Jellyfin<br/>library]
# From home PC
rsync -avz --progress \
/path/to/movies/ \
user@vps:/srv/media-upload/
# On VPS — moves to cloud storage
rclone move /srv/media-upload/ crypt-media:movies \
--bwlimit 10M \
--transfers 2
Use --bwlimit to avoid saturating your home upload bandwidth during uploads.
What I’ve Been Running
Six months in, the setup has been reliable. Jellyfin discovers new content automatically as rclone syncs it. Streaming performance is solid — a 10GB 4K remux buffers for ~5 seconds on a 100Mbps connection, then plays continuously. The total monthly cost: ~$10 (VPS) + ~$6 (Wasabi 2TB).
The main limitation is that you’re streaming everything through the VPS — if the VPS has a slow uplink, 4K streaming suffers. For 1080p h.264, this setup is near-perfect. For 4K remuxes, consider a home NAS as a direct-play source and use the VPS+cloud approach for remote access.