Docs
Self-host MediaHub
Pre-release: MediaHub is installed from the repository. You need Go 1.26+ and Node 22+ on a Linux host with systemd to build and install it.
1. Build it
cd qelvue-mediamanager
make servermake server builds the web admin first and then the binary at bin/qelvue-mediamanager. Use make release instead if you want the .sha256 sidecar as well — the installer checks it when it is present.
Do not deploy a bare go build: it embeds no web UI, so every page answers 404. Build on a machine with Node and copy the binary to the host.
2. Install it
sudo deploy/install.shRun it from inside qelvue-mediamanager/; it installs /opt/qelvue-mediahub/bin/qelvue-mediamanager, keeps the previous binary as qelvue-mediamanager.prev, creates /etc/qelvue-mediahub/mediahub.env on the first run, installs the qelvue-mediahub.service unit, then enables the unit, restarts it and checks that it answers before reporting success.
A box that still has the old StreamFlow layout (/opt/streamflow) is refused by this installer on purpose — run sudo deploy/migrate-to-qelvue-mediahub.sh there instead.
3. Create the first account
sudo cat /var/lib/qelvue-mediahub/setup-tokenThe one-time setup token is written to that file (0600) before the first account exists, and is also printed in journalctl -u qelvue-mediahub. Open the admin page, paste the token and create the owner account with a password — there are no default accounts.
4. Where it listens
- The default address is 127.0.0.1:8480, set by
QELVUE_MM_LISTENin/etc/qelvue-mediahub/mediahub.env. Keep it on loopback when a reverse proxy ortailscale serveis in front of it. - The server also binds :8096 — Jellyfin's and Emby's default port — with the same handler, so a media client that assumes that port finds it.
5. Connect a TV or a media app
The Qelvue apps pair with the box and need no password. A Jellyfin or Emby app signs in instead, and two things are worth knowing before you call it broken.
- A profile with a PIN needs both halves in the password box. Type the account password, a colon, then the PIN —
<account password>:<PIN>, for exampleopen-sesame:4821. The PIN on its own no longer works, and neither does the password on its own. The username is the account name, oraccount/profileto pick a profile. This applies to Jellyfin and Emby apps only; signing in to the admin page or the web app in a browser is unchanged. - “Can’t reach the server from this device” on a shell that is installed on the TV. The server answers
/api/*and/healthzfrom another address only when that address is named inQELVUE_MM_ALLOWED_ORIGINSin/etc/qelvue-mediahub/mediahub.env. The installed Android build sendshttps://localhost; a Tizen or Apple TV build sends the literalnull; a hosted web build sends its own address. Add the one you use, then restart —sudo systemctl restart qelvue-mediahub. The list is read once at start-up, so this is a restart, not a rebuild.*is refused on purpose.
After install
- In Qelvue, go to Settings → MediaHub and pair with the code shown in the server's admin page.
- Settings use
QELVUE_MM_*environment variables (data folder, port, log level). The pre-renameSTREAMFLOW_*names are still read when the new one is unset.
Requirements
- Linux with systemd for the installer; Go 1.26+ and Node 22+ to build.
- ffmpeg and ffprobe on the PATH. Without them the server still runs and VOD plays, but live streams and recording do not, and it logs that once at startup.
- 64-bit CPU, 1 GB RAM minimum. GPU transcoding needs the Pro Pass, which is planned.
- Video plays directly from your provider by default; MediaHub only handles the guide, names and sync unless you switch on routing.
Not available yet
These addresses are described elsewhere as if they worked. They do not: there is no container image and no release file at either of them. Build from source with the steps above instead.
ghcr.io/qelvue/mediahub:latest— no image is published (the registry denies it). Build from source instead.github.com/qelvue/mediahub/releases— no release has been published. Build from source instead.- Unraid community app and the TrueNAS custom-app recipe both point at that image, so neither works yet. Build from source instead.