The Honest Part First: Transcoding
Jellyfin serves video in two ways. If the client can play the file as-is (direct play), the server just streams bytes — almost no CPU. If the client needs a different format or a lower bitrate (transcoding), the server has to re-encode on the fly, which is heavy.
- **Direct play** (same file, capable client, enough bandwidth): a small VPS handles several streams.
- **CPU transcoding** (1080p): budget on roughly one stream per 2 vCPU, and expect it to struggle with 4K.
The trick is to avoid transcoding: keep your library in widely-supported formats (H.264/AAC in MP4/MKV) and most clients direct-play. Plan the server for your library, not for worst-case re-encoding.
Step 1: Install Docker
curl -fsSL https://get.docker.com | shStep 2: Compose + Caddy HTTPS
Save as docker-compose.yml. Caddy handles the certificate automatically:
services:
jellyfin:
image: jellyfin/jellyfin:latest
restart: always
volumes:
- config:/config
- cache:/cache
- /srv/media:/media:ro
environment:
- JELLYFIN_PublishedServerUrl=https://media.example.com
caddy:
image: caddy:2-alpine
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
depends_on:
- jellyfin
volumes:
config:
cache:
caddy_data:Note the media mount is read-only (:ro) — Jellyfin never needs to modify your files, so don't give it the chance.
Step 3: The Caddyfile
media.example.com {
reverse_proxy jellyfin:8096
}Bring it up and open the web setup wizard:
docker compose up -dGo to https://media.example.com, create your admin user, and add /media as a library folder.
Step 4: Get Media Onto the Server
Copy files into /srv/media on the host. For a one-off, rsync over SSH from your machine:
rsync -avP ~/Movies/ root@your-server-ip:/srv/media/movies/For an ongoing library, many people sync from object storage or a home NAS with rclone on a schedule.
Step 5: Keep It Private and Updated
- Only Caddy is exposed; Jellyfin's port stays inside the Docker network.
- Turn off "Enable automatic port mapping (UPnP)" — irrelevant on a VPS and a needless surface.
- Update with
docker compose pull && docker compose up -d.
What It Costs
A direct-play Jellyfin for a household runs comfortably on a small-to-mid VPS; the deciding factors are storage for your library and monthly bandwidth for streams. On NoctHost you pay hourly from a prepaid balance, top up with crypto, and get a dedicated IPv4 with a generous transfer allowance — spin up the Pro plan (4 vCPU, 8 GB) if you expect occasional transcoding, or the Standard plan for a pure direct-play setup.