Nomploy Nomad Packs

← All packs

ersatztv v0.1.0

Media

ErsatzTV — build and stream your own live TV channels from your media collection, exposed as an HDHomeRun tuner with an XMLTV guide for Plex, Jellyfin and Emby. Deployed as a single host-networked Nomad service.

nomad-pack run ersatztv --registry nomploy
…or one line (add registry + run)
curl -fsSL https://packs.nomploy.com/install.sh | sh -s -- ersatztv

Needs nomad-pack on PATH. The script only adds the nomploy registry and runs this pack.

2 tasks http 8409 1 volume image jasongdove/ersatztv:latest tracks :latest image bumped today
Variables 9
values.hcl

Save as values.hcl, edit, then run:

nomad-pack run ersatztv -f values.hcl --registry nomploy
# The name of the Nomad job.
job_name = "ersatztv"

# The Nomad namespace to deploy into.
namespace = "default"

# The datacenters to deploy to.
datacenters = ["*"]

# The ErsatzTV container image. Pin a tag in production.
image = "jasongdove/ersatztv:latest"

# Host port for the ErsatzTV web UI.
port = 8409

# Named volume mounted at /config (database, channels and settings).
data_volume = "ersatztv_data"

# Container timezone (TZ), e.g. Europe/Bratislava.
tz = "UTC"

# Placement constraints. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []

# The task resources.
resources = {
    cpu    = 300
    memory = 256
  }
NameTypeDefaultDescription
job_name string
"ersatztv"
The name of the Nomad job.
namespace string
"default"
The Nomad namespace to deploy into.
datacenters list
["*"]
The datacenters to deploy to.
image string
"jasongdove/ersatztv:latest"
The ErsatzTV container image. Pin a tag in production.
port number
8409
Host port for the ErsatzTV web UI.
data_volume string
"ersatztv_data"
Named volume mounted at /config (database, channels and settings).
tz string
"UTC"
Container timezone (TZ), e.g. Europe/Bratislava.
constraints list
[]
Placement constraints. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
resources object
{
    cpu    = 300
    memory = 256
  }
The task resources.
Back up this pack

This pack stores data in one Docker named volume: ersatztv_data

restic

# Run on the node hosting this pack. Point restic at your repo first:
#   export RESTIC_REPOSITORY="s3:https://<account>.r2.cloudflarestorage.com/<bucket>"
#   export RESTIC_PASSWORD="<repo-password>"
#   export AWS_ACCESS_KEY_ID=<key>  AWS_SECRET_ACCESS_KEY=<secret>
restic backup \
  /var/lib/docker/volumes/ersatztv_data/_data

rclone (sync to S3/R2)

rclone sync /var/lib/docker/volumes/ersatztv_data/_data backup:<bucket>/ersatztv_data

Paths assume the default Docker volume location (/var/lib/docker/volumes). Restore by stopping the job, restoring files into the same volume, and re-running the pack.

Readme

ersatztv

ErsatzTV — build and stream your own live TV channels from your media collection. Schedule movies, shows and music into channels, then watch them through Plex, Jellyfin or Emby via an HDHomeRun-style tuner and an XMLTV guide. A powerful scheduler for a retro "always-on TV" experience.

Single host-networked Nomad service with a persistent config volume.

Deploy

nomad-pack registry add nomploy https://github.com/Nomploy/nomad-packs
nomad-pack run ersatztv --registry=nomploy

Configure

Variable Default Description
port 8409 Web UI port.
image jasongdove/ersatztv:latest Container image. Pin a tag in production (e.g. nvidia/vaapi for HW transcoding).
data_volume ersatztv_data /config — database, channels and settings.
tz UTC Container timezone (TZ).
resources { cpu = 300, memory = 256 } Task resources. Add cores for transcoding.

Add your media libraries, build channels and schedules in the web UI, then point your media server's live-TV/DVR at ErsatzTV's M3U + XMLTV URLs. A prestart init task makes the config volume writable. For hardware transcoding, use the matching image tag and pass through the GPU device. Pin the job to the node holding the volume with constraints.