Run Nostalgex on your own server
The same web tuner that runs at nostalgex.app, as a small Docker container sitting next to your media server. It serves the tuner over plain http on your own network, which is the one thing the hosted site can't do.
That matters if you run Jellyfin or Emby on a plain http:// address. Browsers won't let an https page talk to a plain http server, so nostalgex.app can't reach your box no matter what you type into it. Run the tuner yourself and that wall is gone.
What this is
Nostalgex turns your own Plex, Jellyfin or Emby library into live TV channels with a real channel guide. There are three ways to watch it: the Apple TV app, the hosted web tuner, and this, a Docker container you run yourself.
The container is nginx serving the tuner's static files on port 8080. No database, no backend, nothing to sign up for, nothing installed on your media server. Start it, open http://YOUR-SERVER-IP:8080 in a browser on your network, and connect the same way you would on the hosted site.
The mixed-content wall, and why this is the fix
nostalgex.app is served over https. Browsers block an https page from reaching a plain http:// address or a raw LAN IP, and there's no setting that turns that off. It's a rule of the web, not a choice I made.
Plex slips past it because plex.direct hands out real certificates for local addresses. Jellyfin and Emby usually don't have that, so a server at http://192.168.1.50:8096 is simply unreachable from the hosted tuner.
Running the container puts the tuner on plain http too, on the same network as your server. Same origin rules, same protocol, no block. Everything that was impossible in a browser tab now works.
The second reason people want this: nothing of mine sits in the path. Your browser talks to the container and your server. The only outside requests are listed below, and you can switch them off.
Who doesn't need it
Worth saying plainly, because this is extra work and plenty of people can skip it.
- You use Plex and you watch on an Apple TV. Install the free App Store app and stop reading. It connects straight to a local server, plain http included, and it's the best version of Nostalgex there is.
- You use Plex and you want it in a browser. The hosted tuner already works. plex.direct gives your server a real certificate, so there's nothing to get around.
- Your Jellyfin or Emby is already on https with a valid certificate through a reverse proxy, Tailscale Serve or a Cloudflare Tunnel. The hosted tuner reaches that fine. You might need one CORS header at the proxy, which the support page walks through.
What's left is the case this is built for: Jellyfin or Emby on a plain http address on your LAN, and you want it in a browser instead of on an Apple TV. Or you'd rather run the whole thing yourself.
What you need
- A machine that stays on, with Docker. A Synology or Unraid NAS, a mini PC or NUC, a Raspberry Pi 4 or 5, or a spare Mac. If it already runs your media server, run it there.
- The same network as your media server. The browser has to reach both, so they need to be on the same LAN.
- amd64 or arm64. Both are published. There's no armv7 build, so older Pi and Synology models are out.
- One free port. 8080 by default. Change the left side of
-pif something else already has it.
That's the whole list. It's nginx serving static files as a non-root user (uid 101), it runs happily with a read-only root filesystem as long as /tmp is writable, and it uses almost nothing while it sits there.
Get it running
docker run
docker run -d --name nostalgex -p 8080:8080 --restart unless-stopped ghcr.io/chadmueller/nostalgex:latest
Or compose
Drop this next to your other compose files and run docker compose up -d. There's a fuller version in the repo at docker/compose.yaml.
services:
nostalgex:
image: ghcr.io/chadmueller/nostalgex:latest
container_name: nostalgex
ports:
- "8080:8080"
environment:
NOSTALGEX_ENRICHMENT: "on" # "off" for no outside requests, see below
read_only: true
tmpfs:
- /tmp
restart: unless-stopped
Then open it
Go to http://YOUR-SERVER-IP:8080 in any browser on your network, using whatever address the machine answers on: http://192.168.1.20:8080, http://nas.local:8080, whatever you already use. Connect Plex, Jellyfin or Emby the same way you would on the hosted tuner.
Updating
docker compose pull && docker compose up -d, or docker pull ghcr.io/chadmueller/nostalgex:latest and recreate the container. Tags are latest, 1.0 and 1.0.0 style versions, so you can pin a line if you'd rather not move with latest.
Building it yourself
The whole thing is in the repo, so you don't have to trust my image:
docker build -t nostalgex .
docker run -d --name nostalgex -p 8080:8080 nostalgex
Enrichment needs the shared cache's address and public anon key at build time: add --build-arg VITE_SUPABASE_URL=... --build-arg VITE_SUPABASE_ANON_KEY=..., or point them at your own Supabase project. Without them it builds with enrichment off. To skip Docker entirely, npm run build:selfhost writes the same files to dist-selfhost/ and any static server will do, as long as it serves .cjs as JavaScript.
What leaves your network
The point of running it yourself is knowing where things go, so here's the whole list for the container's tuner.
| Where | When | Turn it off |
|---|---|---|
| Your media server | Always. Sign-in and playback go straight from the browser to your server. | |
| plex.tv | Plex only: PIN sign-in and finding your server, like every Plex app. | Use Jellyfin or Emby |
| The shared metadata cache (Supabase) and the nostalgex.app TMDB/OMDb relay | On by default. Nine or more channels need keywords, studios or IMDb ratings to fill (TEEN MOVIES, TRUE CRIME, CULT CLASSICS and others). Only TMDB and IMDb ids leave the browser: no titles, no server address, no credentials. | NOSTALGEX_ENRICHMENT=off |
There are no analytics, no scripts or fonts from a CDN, and no MusicBrainz or Deezer lookups in the image. With NOSTALGEX_ENRICHMENT=off and Jellyfin or Emby, the browser talks to the container and your media server and nothing else. With it on, those channels fill the way they do on Apple TV.
The switch is an environment variable, so it's one line in your compose file:
environment:
NOSTALGEX_ENRICHMENT: "off"
A value the container doesn't recognise is treated as off, on purpose. A typo shouldn't quietly send requests you tried to stop.
Where it works
Here's the honest state of it. Nothing in this table says "works" unless it's actually been run there.
| Where | Status | What that means |
|---|---|---|
| Desktop browsersChrome, Safari and Firefox on a Mac | Works | Tested. This is the surface the tuner is built for. |
| iPhone and iPadSafari | Works | Tested from the container on a real iPhone and iPad. Plays inline with the phone and tablet layouts, and the controls sit in a menu on the phone. |
| Google TVTV Bro browser | Works | Tested on a Google TV. The remote moves an on-screen cursor and OK clicks, so everything is a button: UP and DOWN under the guide, CLOSE in Settings, and OK on the picture in full screen brings up channel, sound and exit. Back belongs to the browser. Sound starts off; turn it on once and it comes back with your first click next time. Surround audio not tested yet. |
| Other TV browsersFire TV Silk, Samsung and LG | Untested | No results yet, good or bad. TV browsers vary a lot and some cannot decode surround audio. If you try one, tell me what happened. |
| Apple TVtvOS | Use the app | tvOS has no web browser. The free App Store app does this job properly, with the Siri Remote and no mixed-content rule. |
| Roku | No | Roku has no web browser, so there is nothing to open the tuner in. |
Last updated 2026-10-15. Anything not listed here has not been tried. Tell me what you ran it on and this table gets another row.
When it doesn't work
A reverse proxy puts the wall back
This is the one that catches people. If you put the tuner behind https at https://nostalgex.mydomain.com and your Jellyfin is still plain http, the browser blocks Jellyfin again, for exactly the reason you installed the container to avoid.
Serve the tuner and your media server the same way. Both on plain http inside your network is the simple setup and the one this is built for. If you want https, put both behind it.
No armv7
amd64 and arm64 only. Older Raspberry Pi and Synology models won't pull the image. A Pi 4 or 5 on a 64-bit OS (uname -m says aarch64) is fine.
Surround audio on TV browsers
Some smart TV browsers can't decode surround audio, so a file with a 5.1 track can play silently or not at all. That's the browser, not the tuner. If a channel won't play on a TV, try it on a laptop or a phone first to see whether it's the file or the device, and use the Apple TV app on a TV.
Music video genres
MusicBrainz and Deezer lookups are off in the image, because they'd be outside requests. The music video channels still work and still show titles and artists. Genre splits are thinner than they are on Apple TV.
Help
Discord join the server. Quickest way to get an answer, and where new versions get mentioned first.
Bugs and feature requests GitHub Issues.
Email support@nostalgex.app.
Reporting a problem with the container? The useful bits: which server you're on (Plex, Jellyfin or Emby) and its version, what the machine running Docker is, the browser you opened it in, the output of docker logs nostalgex, and anything red in the browser's dev console.
If you've run it somewhere that isn't in the table above, say so even if it worked. That table only grows from real reports.
More setup help is on the support page, and the full technical write-up is in the repo README. Nostalgex is MIT licensed and free, and it's staying that way. If it gives you a good Friday night you can buy me a coffee.