Why Host Your Media Server on a VPS
A self-hosted media server on a VPS makes you the owner of your catalog: movies, TV shows, music, and photos stay accessible over HTTPS from a browser, a Smart TV, or a smartphone, with no imposed quota and no analysis of your habits.
Unlike a home machine, a VPS has the stable upload bandwidth essential for remote streaming, a fixed IP to set up a domain, and 24/7 availability with no added electricity cost. Your media library no longer depends on your home connection or hardware.
Jellyfin is entirely free (GPL license) with no paid features whatsoever; Plex offers a more polished client experience but locks hardware transcoding and remote access behind a Plex Pass subscription. The choice therefore comes down to total freedom versus preconfigured convenience.
What You Gain by Hosting It Yourself
- Remote access over HTTPS without going through an external relay or exposing your content to a third party
- No limit on accounts, simultaneous streams, or library size
- On-the-fly transcoding driven by your own VPS resources (CPU or GPU)
- Subtitles, metadata, and cover art fetched automatically and stored on your own server
- With Jellyfin: zero paid features, no telemetry, auditable source code
- Trivial backup and migration: everything fits in a Docker volume and a media folder
- Native DLNA support to stream to TVs and network players without a dedicated client
Prerequisites for a VPS Media Server
For direct streaming (remux without re-encoding), a VPS with 2 vCPUs and 2 GB of RAM is enough. As soon as you enable software transcoding of a 1080p stream, count on 4 vCPUs and 4 GB; for several simultaneous 4K streams, aim for 6 to 8 vCPUs. Hardware transcoding (QSV, NVENC) remains rare on shared VPSes: favor files already compatible with your clients to stay in Direct Play.
On the storage side, plan for a generous volume and ideally a fast disk for metadata. You'll need Docker and Docker Compose installed, a subdomain (e.g. media.your-domain.com) pointing to the VPS IP, and a reverse proxy for TLS.
Deploy Jellyfin (or Plex) with Docker and a Reverse Proxy
Prepare the Directory Tree and Volumes
On the VPS, create
mkdir -p /srv/jellyfin/{config,cache}and a media folder/srv/media/{films,series,musique}. These paths will be mounted as volumes to persist the configuration and cleanly separate content from the database.Write the docker-compose.yml
Declare the
jellyfin/jellyfinservice (orplexinc/pms-docker), mount./config,./cache, and/srv/mediaread-only, and expose port8096(Jellyfin) or32400(Plex) locally only:127.0.0.1:8096:8096. The reverse proxy will handle public exposure.Start the Container
Run
docker compose up -d, then followdocker compose logs -f. Reach the setup wizard through an SSH tunnelssh -L 8096:127.0.0.1:8096 user@vpsto create the admin account before any public exposure.Configure Transcoding
In the Jellyfin interface, go to Dashboard → Playback and set the transcoding path to
/config/transcodes. If your VPS is CPU-limited, force Direct Play and refuse automatic transcoding: the interface will show an error for incompatible files rather than saturating the server. For Plex, the same option is in Settings → Remote Playback.Set Up the Reverse Proxy and SSL
Configure Caddy or Nginx to proxy
media.your-domain.comto127.0.0.1:8096. With Caddy, two lines are enough and the Let's Encrypt certificate is automatic; remember to forward the WebSocket headers for real-time playback. Note for Jellyfin 12: the legacy/emby/and/mediabrowser/prefixes have been removed — if you configured your reverse proxy on those paths, update it to point to the root/.Secure Access with Jellyfin Authentication
Jellyfin natively handles authentication: enable a strong password policy and limit login attempts in Dashboard → Security. For Plex without Plex Pass, remote access requires configuring port forwarding on your network — on a VPS, the reverse proxy is sufficient and preferred. Never open port
8096or32400directly on the firewall: only ports 80/443 should be accessible.Index Your Libraries
In the interface, add the
/media/filmsand/media/seriesfolders, choose the metadata agent, and start the scan. Verify that a file plays in Direct Play from an external client to confirm that the proxy and codecs are correct.Back Up the Configuration
Backing up Jellyfin comes down to two elements: the
./configfolder (database, plugins, preferences) and your media files. Automate a dailytar -czf jellyfin-config-$(date +%Y%m%d).tar.gz ./configand sync to remote storage. For Plex, thePlex Media Server/folder is the equivalent. Test the restore procedure on a test environment before you need it.
Jellyfin 12: What Changes and How to Migrate
Jellyfin 12 was released on September 7, 2026. This version jump — directly from 10.11.x to 12 — reflects the scale of incompatible changes introduced.
Removal of legacy API prefixes. The /emby/ and /mediabrowser/ routes have been permanently removed. Any third-party client or script using them (Infuse in Emby mode, some Kodi plugins, Home Assistant integrations) must be updated to point to the root /. Check each client application before migrating.
Irreversible database migration. Jellyfin 12 replaces its SQLite schema with a restructured relational structure. The migration runs automatically on first startup and cannot be undone. Back up the entire config/ folder — especially data/jellyfin.db — before pulling the updated container image. A rollback requires reverting to the previous version's Docker image.
10.11 plugin incompatibility. Plugins built for Jellyfin 10.11 are not compatible with Jellyfin 12. Check each plugin's compatibility in the official catalog before migrating, or disable them while maintainers release updated versions.
Direct migration supported. Upgrades from 10.10.7 and 10.11.x to 12 are supported — no need to reinstall from scratch. Simply pull the new Docker image, after backing up.
Scroll the table
| Criterion | Jellyfin | Plex |
|---|---|---|
| License / cost | Free (GPL), 100% free | Freemium, paid Plex Pass for key features |
| Hardware transcoding | Included and free | Reserved for Plex Pass subscribers |
| Remote access | Direct via your reverse proxy | Goes through Plex relays (or Pass) |
| Privacy | No telemetry, everything stays on your server | Centralized Plex account and metadata |
| Client quality (TV, mobile) | Good, steadily improving | Very polished and stable |
| DLNA support | Native, no configuration needed | Present, less configurable |
| Plugins and extensions | Rich community catalog, actively evolving | More closed, built-in features |
| Mobile apps | Free (Android, iOS) | Free with ads, Pass for downloads |
| Community | Very active, open source, forums and Matrix | Active, official forum, less open |
| Chromecast | Supported via mobile app | Natively supported |
| Initial setup | A few manual settings | Very guided wizard |
Troubleshooting: The Most Common Errors
Transcoding that fails silently. The player shows a generic error or the video won't start. First check: in Dashboard → Logs, filter on Transcod. If you see ffmpeg not found or Permission denied on the transcoding folder, the container can't find the binary or doesn't have write access to /config/transcodes. Verify the volume is mounted with write permissions and that the Docker image is jellyfin/jellyfin (not an unmaintained fork).
Error "no hardware acceleration". On a VPS without a dedicated GPU, hardware acceleration (VAAPI, QSV, NVENC) is not available. The error appears in logs if you enabled a hardware transcoding option the server cannot honor. Disable it in Dashboard → Playback → Hardware Transcoding and switch back to software transcoding, or force Direct Play.
Remote access blocked behind a reverse proxy (path prefix). If you serve Jellyfin under a subpath like your-domain.com/media/, static resources and the API won't load correctly. Jellyfin recommends a dedicated subdomain (media.your-domain.com) rather than a subpath. If a subpath is unavoidable, configure baseUrl in network.xml and ensure your reverse proxy forwards the full path without rewriting it.
Metadata sync that loops. The library scan runs indefinitely without progressing. Common causes: insufficient permissions on the media folder (Jellyfin must be able to read the files), filenames not conforming to the Title (Year).mkv standard, or connectivity issues to remote metadata agents. Check the scheduled task logs in Dashboard → Scheduled Tasks to identify which step is blocking.
To avoid saturating your VPS CPU, standardize your library in H.264/AAC inside an MP4 or MKV container. A simple ffmpeg remux script (no re-encoding, -c copy flag) repackages your files in a few seconds and relieves the server for good, especially on a VPS without a GPU. This operation doesn't touch video quality: it only changes the wrapper, not the content.