Install Nova Core
From a fresh Linux box to live IP streams in a few minutes. One static binary, no dependencies.
System requirements
| OS | A systemd-based Linux. Tested on Debian 11/12 & Ubuntu 20.04+. Also works on Fedora / RHEL / Rocky / AlmaLinux, openSUSE, Arch, Raspberry Pi OS (64-bit), Armbian. |
| Kernel | DVB drivers loaded, with your tuner exposed at /dev/dvb/*. |
| CPU | x86-64-v2 (≈2009+) for the amd64 build, i386 (32-bit x86, SSE2 / Pentium 4+) for the i386 build, or arm64 / armv7. |
| Privileges | root — install writes to /opt/nova-core and registers a systemd service. |
| Dependencies | None. No ffmpeg, no Python, no libc — a single static binary. |
Non-systemd distros (Alpine, Void, Devuan) can run the binary manually, but the -install command needs systemd.
Download
Grab the build for your CPU architecture — the link always points at the latest release:
| amd64 | nova-core-linux-amd64.tar.gz |
| arm64 | nova-core-linux-arm64.tar.gz |
| armv7 | nova-core-linux-armv7.tar.gz |
| i386 | nova-core-linux-i386.tar.gz |
Each tarball ships a .sha256 next to it — verify before extracting:
# example for amd64
sha256sum -c nova-core-linux-amd64.tar.gz.sha256
Install
Quick install (one command)
The fastest path — this detects your CPU, downloads the latest release, unpacks it and runs the installer. Run it as root:
curl -fsSL https://novaheadend.com/install.sh | sudo sh
Manual install
Prefer to do it by hand? Download your build from the table above, then extract and run the installer as root:
tar -xzf nova-core-linux-amd64.tar.gz
sudo ./nova-core -install
Either way, the installer copies the binary to /opt/nova-core, writes a default config, registers a systemd service, starts it, and prints the bootstrap admin password. You'll see something like:
Nova Core installed
URL http://<your-ip>
user admin
pass 3f8c… (change it in Settings → Users)
The service is now enabled (starts on boot) and listening on two ports: :80 (admin UI) and :8000 (public stream egress).
Docker
Prefer a container? There's an official multi-arch image (amd64 / arm64):
docker run -d --name nova-core \
--network host \
--device /dev/dvb \
-v nova-config:/config \
-v nova-data:/opt/nova \
ghcr.io/novaheadend/nova-core:latest
The bootstrap admin password is printed in docker logs nova-core. Pass your tuner devices with --device /dev/dvb/… (or --privileged), and --network host keeps UDP multicast and client access simple. The image rebuilds automatically on every release.
First login
- Open
http://<your-ip>in a browser (admin UI is on port 80). - Log in with
adminand the printed password. - Go to Settings → Users and set your own password immediately.
Add a tuner
- Open Tuners → Add Tuner.
- Pick the physical adapter and the type (DVB-S / S2 / T / T2 / C).
- Enter frequency, polarization and symbol rate for the transponder.
- Click Scan to lock and list the services on that mux, pick the service you want, then Save.
LNB, DiSEqC & Unicable
For DVB-S/S2 tuners, Add/Edit Tuner → Advanced exposes the LNB and dish wiring. The defaults suit a single Universal LNB on its own cable — you only need these for other setups.
LNB type
- Universal (default) — standard Ku LNB, LO 9750/10600, band switch at 11700 MHz.
- C-band — LO 5150 MHz, high-side injection.
- Ka-band — LO 18250 MHz.
- Custom — enter your own oscillators in LOF1 / LOF2 / SLOF (MHz) for a non-standard LNB.
DiSEqC switch
If several LNBs or satellites feed one tuner through a DiSEqC switch, set DiSEqC switch to the port (1–4 = A–D) for the satellite this tuner should use. Leave it Off for a single LNB.
Force tone
The 22 kHz band-select tone is chosen automatically from the frequency. Force tone (On/Off) overrides it only if your wiring needs a fixed value — normally leave it on Auto.
Unicable / SCR — one cable, many tuners
Unicable (SCR/JESS) lets several tuners share a single coax, each on its own user band. Under Unicable / SCR pick the mode:
- Unicable I — SCR (EN 50494) — up to 8 user bands.
- Unicable II — JESS (EN 50607) — up to 32 user bands.
Then set the User band index and its User band IF (MHz) — both printed on your LNB or multiswitch. Each tuner on the same cable must use a different user band, or they collide.
Create a stream
- Open Streams → Add Stream.
- Input: select the tuner and the programme (PNR) you scanned.
- Output: choose HTTP-TS (pull) or UDP (multicast push).
- Save — the stream starts immediately and is playable.
/playlist.m3u). This step is only for advanced users who need custom UDP multicast output, per-stream tuning, or a fixed stream ID.Access your streams
Every enabled stream is reachable on the stream port (:8000 by default):
| HTTP-TS | http://<host>:8000/stream/ts/<id> |
| Playlist | http://<host>:8000/playlist.m3u — every enabled stream as M3U |
| UDP | udp://<group>:<port> — when a UDP output is configured |
Open any of these in VLC, mpv, or load /playlist.m3u into your IPTV player.
Channel order
The order channels appear in /playlist.m3u — and in the master guide — follows your Streams list. On the Streams page, click the edit-order button next to Playlist to move channels up or down, then Save order. This is the channel numbering your set-top box or IPTV app will show.
EPG (program guide)
Nova harvests the DVB EIT (Event Information Table) straight off a mux and publishes it as XMLTV — the format your IPTV player loads for a program guide. No external grabber, no scraping, no third-party EPG service.
One tuner, the whole bouquet
Most operators broadcast the EPG for every channel on a single mux (a network-wide EIT schedule that includes other-transponder events). Nova tunes that one transponder and collects the guide for hundreds of channels at once — you don't need a tuner per channel. A single budget-mode tuner sitting on the EPG mux gives you the complete lineup's guide.
Add an EPG job
- Open the EPG page → + Add job.
- Tuner: the adapter on the EPG-carrying mux. Enable Budget mode on it for the complete EIT.
- XMLTV filename: any
*.xmlname, e.g.guide.xml. (epg.xmlis reserved for the master guide — see below.) - Save — Nova section-filters SDT (channel names) + EIT (events) and rewrites the XMLTV on each refresh.
Per-job options
| Refresh | How often (seconds) Nova re-harvests and rewrites the file. |
| Offset (min) | Minutes added to every event start time — use it if the broadcaster's EIT clock lags (e.g. +60). |
| Prune days | Days of past events to keep before trimming. |
| Future days | Days ahead to include in the guide. |
Bind a guide to a channel
The raw harvested XMLTV is keyed by the broadcaster's service ids, which differ from your stream ids and can clash across networks. To get a guide your player lines up with the right channel, bind each stream to one channel of an EPG job:
- Edit a stream → EPG Guide → pick the EPG job, then search and select the channel.
- Nova re-keys that channel's programmes onto the stream's own id, so the guide always matches the channel — no manual id mapping, no cross-network collisions.
- Bindings point at a stable job id, so renaming the job's file or label later never breaks them.
The master guide
Nova merges every bound stream into a single guide at the reserved name /epg/epg.xml, matched to /playlist.m3u (each bound channel carries a tvg-id). Point your IPTV player at one playlist + one guide and everything lines up:
http://<host>:8000/playlist.m3u # channels
http://<host>:8000/epg/epg.xml # merged master guide
http://<host>:8000/epg/guide.xml # a raw per-mux job (optional)
Works out of the box with TiviMate, Jellyfin, Plex and Xtream-style panels. The raw per-job files stay available for tools that prefer service-id-keyed XMLTV.
Channel logos
Give a channel a logo and it shows up in your player. Edit a stream → Channel logo → paste an image URL. Nova downloads it once, stores it under <DataDir>/logos/, serves it locally, and adds a tvg-logo to /playlist.m3u — so the icon keeps working even if the source link later goes down. The editor previews the remote image as you type and the locally-served copy once you save.
Settings
Everything below lives under Settings in the UI. All values persist to nova.json and survive restarts. Port and runtime changes auto-restart Nova so the new values take effect.
General
| Admin UI port | Port the admin UI + JSON-RPC listen on (default 80). Changing it auto-restarts Nova so the new listener binds. |
| Stream port | Port the public stream egress (HTTP-TS) listens on (default 8000). Kept separate from the admin port so you can firewall them differently. |
| GC percent (GOGC) | Garbage collector runs when the heap grows this percent since the last collection. 50 keeps RAM tight (more frequent GC, slightly more CPU); 100 is the Go default (less GC, more RAM). Empty = built-in 50. |
| Memory limit (GOMEMLIMIT) | Soft heap ceiling in MB. The runtime runs GC aggressively as the heap approaches it, so RSS stays under it even under load. 2048 (2 GiB) fits ~25 HD streams. Raise for larger installs. |
Streaming
| Restart scheduler | Optionally restart all streams automatically at a chosen day(s) + time — a daily refresh for long-running headends. Off by default. |
| HTTP-TS buffer | Per-client send buffer in KiB. Bitrate-aware: sized to cover a few seconds of a slow client's stall without dropping it. Larger = more tolerance for laggy clients, more RAM per viewer. |
Network
Nova handles the modprobe + sysctl writes for these on save and at boot — you never touch the shell.
| Kernel TCP buffer | Caps per-socket TCP send/receive buffers (MB). Linux auto-tunes each socket up to this ceiling based on RTT × bandwidth. 16 MB covers VPN clients with 100–500 ms RTT. Empty = system defaults. |
| UDP send buffer | Per-socket SO_SNDBUF for UDP/RTP egress (MB). Bigger = more cushion before the kernel drops packets. 4 MB fits ~250 ms of a 128 Mbps mux. Bump for full-mux multicast (50 Mbps+). |
| TCP congestion | Congestion control algorithm. Picking bbr also switches the default qdisc to fq (BBR's pacing needs it). Leave default unless you know you want BBR. |
IP whitelist (access control)
The IP Whitelist tab controls who can pull streams. It gates the stream egress port only (:8000) — the admin UI stays behind its own login. Both lists take one entry per line, plain IPs or CIDR blocks, IPv4 or IPv6.
| Allow list | If non-empty, only these IPs/ranges may reach /stream/… and /playlist.m3u. Empty = open to everyone. |
| Deny list | These IPs/ranges are blocked outright, and a deny takes precedence over allow — handy for banning one abusive client while the allow list stays open. |
Example — only your LAN and one office IP may pull streams:
# Allow list (one per line)
192.168.1.0/24
203.0.113.5
Update & uninstall
Built-in updater (recommended)
Nova can update itself — no manual download. Open Settings → General → Software updates:
- Check now queries the public GitHub releases repo and tells you if a newer build is out; Update now applies it on demand. Release notes shows what changed.
- Check for updates automatically — a once-a-day check that only reads the latest version string from the GitHub API (no download), so the UI flags when an update is available.
- Automatically install updates — at the hour and minute you set, Nova downloads the build for your CPU, verifies its SHA-256, swaps the running binary and restarts the service.
Every apply (manual or automatic) keeps a .bak of the previous build next to the binary, so an update can be rolled back. Your config (nova.json) is never touched.
Manual update
Prefer to do it yourself? Download the new release, stop the service, replace the binary, start again — your config is untouched:
sudo systemctl stop nova-core
sudo cp nova-core /opt/nova-core/nova-core
sudo systemctl start nova-core
Uninstall
sudo ./nova-core -uninstall # removes service + binary, keeps config JSON
Troubleshooting
| permission denied on /dev/dvb | The service must run as root (it does after -install). Running the binary manually as a normal user can't open frontends. |
| Scan: device or resource busy | The tuner is already locked (by a stream, idle monitor or EPG). Nova snoops a live tuner when re-scanning its own transponder. |
| Stream shows SCRAMBLED | The channel is encrypted. Nova Core is free-to-air only and does not descramble encrypted channels. |
| Logs | journalctl -u nova-core -f, or the Logs page in the UI. |