Tellyard

Tellyard

Docker app from Tellyard's Repository

Overview

A live TV tuner for Plex and Jellyfin that you'll forget is running.

Tellyard shows up in Plex and Jellyfin as a network tuner. You list your channels in one file. When someone tunes in, Tellyard finds the channel's live stream on YouTube, Twitch, a broadcaster's page or an HLS address and passes it on without re-encoding. When they stop watching, it stops. The guide merges XMLTV schedules with placeholder blocks, so it is never empty.

Tellyard ships no channels. It starts with an empty line-up: put your channels.toml in /mnt/user/appdata/tellyard/config and it is loaded within a minute. Then add the tuner in Plex at Unraid-IP:5004 and the guide at http://Unraid-IP:5004/guide.xml.

Tellyard

A live TV tuner you'll forget is running.

CI ghcr.io Docker Hub

tellyard.sandobserver.com

Tellyard presents itself to Plex and Jellyfin as an HDHomeRun network tuner. You list your channels in one file. When a viewer tunes in, Tellyard finds the channel's current stream, picks its best quality and hands it over without re-encoding. When the viewer leaves, it stops. Nothing is downloaded while nobody watches, and it runs as one small container with no database.

What you get

  • On demand. A stream runs only while someone watches, and up to TUNERS at once.
  • YouTube, Twitch, web players and HLS. Live channels on YouTube, Twitch, Kick and other sites through yt-dlp, broadcaster pages that embed an HLS playlist, and direct HLS playlists. The stream is found again on every tune, so expiring links never break playback.
  • A guide that is never empty. Real schedules from any XMLTV source, with placeholder blocks in every gap. Shows are filed as TV episodes, with a category.
  • Tries to reconnect. A stalled or dropped source is restarted on its own, up to three tries in a row.
  • Quality check. tellyard check tunes each channel and reports the resolution it really sends, so a channel below your minimum never slips in.
  • One file. Channels live in channels.toml, reloaded while Tellyard runs.

Getting started

You need Docker on a 64-bit Intel, AMD or ARM machine, and Plex or Jellyfin. Watching live TV is free; recording in Plex needs Plex Pass.

1. Write your channel list

Create a config folder and copy channels.example.toml into it as channels.toml. Replace the examples with your channels. See Channels.

2. Create the compose file

Save this as compose.yml next to the config folder.

services:
  tellyard:
    image: ghcr.io/sandobserver/tellyard:latest
    container_name: tellyard
    restart: unless-stopped
    init: true
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    mem_limit: 512m
    environment:
      # Time zone for log timestamps
      - TZ=America/New_York
      # Streams that may play at the same time
      - TUNERS=4
      # Lowest resolution `tellyard check` accepts: off, or a height such as 1080
      - MIN_HEIGHT=off
    volumes:
      - ./config:/config:ro
      - ./data:/data
    ports:
      - "5004:5004"

./data is where Tellyard caches the guide and the yt-dlp files between restarts.

Tellyard has no login. Anyone who can reach port 5004 can start streams, so keep it on your home network and do not forward the port to the internet. See Security.

3. Start it

In the folder with compose.yml:

mkdir -p ./data && sudo chown 1000:1000 ./data
docker compose up -d

Tellyard runs as user 1000 and writes only to ./data and /tmp.

Without Compose
mkdir -p ./data && sudo chown 1000:1000 ./data
docker run -d --name tellyard --restart unless-stopped \
  --init --read-only --tmpfs /tmp --cap-drop ALL \
  --security-opt no-new-privileges:true --memory 512m \
  -e TZ=America/New_York -e TUNERS=4 -e MIN_HEIGHT=off \
  -v ./config:/config:ro -v ./data:/data -p 5004:5004 \
  ghcr.io/sandobserver/tellyard:latest

4. Check your channels

docker exec tellyard tellyard check

This tunes each channel once and reports the resolution it really sends. Fix or remove any channel that fails before adding Tellyard to Plex.

5. Add it to your media server

Tellyard does not announce itself on the network, so enter its address by hand: your server's address with port 5004, for example 192.168.1.10:5004. Its guide is http://192.168.1.10:5004/guide.xml.

  • Plex: Settings > Live TV & DVR > Set up Plex DVR. Enter the address, then choose Have an XMLTV guide on your server? Click here to use it and enter the guide address. On an iPhone, iPad or Apple TV, turn on Force Direct Play in the Plex app. See Plex.
  • Jellyfin: Dashboard > Live TV. Add a tuner device of type HDHomeRun with the address, then add an XMLTV guide provider with the guide address.

Unraid

Open Apps, search for Tellyard and choose Install. It starts with no channels. Put your list in place from the Unraid terminal, starting from the example:

curl -fsSL -o /mnt/user/appdata/tellyard/config/channels.toml \
  https://raw.githubusercontent.com/SandObserver/Tellyard/main/channels.example.toml
nano /mnt/user/appdata/tellyard/config/channels.toml

Tellyard loads the file within a minute. Check the channels with docker exec Tellyard tellyard check (on Unraid the container is named Tellyard), then add it to your media server as in step 5, with your Unraid server's address. The template runs as Unraid's nobody user (--user=99:100) with the same lockdown as the compose file, and restarts the container after a crash.

If Apps does not list Tellyard yet, save the template from the Unraid terminal, then pick Tellyard under Docker, Add Container, Template:

curl -fsSL -o /boot/config/plugins/dockerMan/templates-user/my-Tellyard.xml \
  https://raw.githubusercontent.com/SandObserver/Tellyard/main/templates/tellyard.xml

Channels

Each channel in channels.toml needs a number, a name, a logo and one source:

[[channel]]
number = 101
name = "Example News"
logo = "https://example.com/logos/example-news.png"
hls = "https://example.com/live/news/master.m3u8"
[channel.guide]
category = "News"

Channels lists every option and how to find sources, logos and guides. Tellyard reloads the file within a minute of a change and keeps the previous channels if the new file has a mistake. After adding or removing channels, refresh the guide in Plex.

Only add streams you are allowed to watch.

Commands

Run a command inside the container:

docker exec tellyard tellyard check
Command What it does
serve Run the tuner (the container default).
validate Read channels.toml and list the channels.
check [NUMBER...] Tune each channel and report the resolution it sends. Exits 1 if any fails.
guide [-o FILE] Build the guide once.
health Exit 0 when the running service is healthy, or print why it is not. Used by the container health check.

Settings

Set these as environment variables.

Setting What it does Default
TUNERS Streams that may play at the same time. 4
MIN_HEIGHT Lowest resolution tellyard check accepts, such as 1080. off accepts any. A channel's own min_height in channels.toml overrides it. off
DEVICE_NAME Name shown in Plex. Tellyard
DEVICE_ID 8 hexadecimal characters. Plex remembers the tuner by this. derived from the name
BASE_URL Address Plex should use, such as http://192.168.1.10:5004. Set it when the address Plex connects with is not reachable for streams. from the request
GUIDE_DAYS Days of listings to publish. 3
GUIDE_REFRESH_HOURS How often the guide is rebuilt. 6
YTDLP_ARGS Extra yt-dlp arguments, for example extractor options.
LOG_LEVEL debug, info, warning or error. info
HEARTBEAT_URL Address Tellyard calls once a minute while it is healthy, for a monitor such as Uptime Kuma or Healthchecks.
LISTEN_PORT Port inside the container. If you change it, change the right side of ports: too. 5004
CHANNELS_FILE The channel list inside the container. Keep the default. /config/channels.toml
DATA_DIR Folder inside the container for the guide and caches. Keep the default. /data

Documentation

Contributing

See CONTRIBUTING.md for setup, checks and releases. Changes are listed in CHANGELOG.md.

Legal

Tellyard is an independent project. It is not affiliated with or endorsed by Plex, SiliconDust (HDHomeRun), YouTube, Twitch, Kick or any broadcaster. Their names appear only to say what Tellyard works with.

Tellyard ships no channels, stream addresses or logos. It plays only the sources you list. It contains no code to decrypt DRM or to get around logins, paywalls or region limits. You are responsible for making sure you may watch each source you add and that your use follows its terms.

License

Apache License 2.0. See NOTICE for the name and the third-party software in the container image.

Media gallery

Requirements

Plex or Jellyfin, and a channels.toml listing the live streams you may watch. Tellyard ships no channels.

Download Statistics

99
Total Downloads

Related apps

Explore more like this

Explore all

Details

Repository
ghcr.io/sandobserver/tellyard:latest
Last Updated2026-10-17
First Seen2026-10-18

Runtime arguments

Network
bridge
Privileged
false
Extra Params
--user=99:100 --restart=unless-stopped --init --read-only --tmpfs=/tmp --cap-drop=ALL --security-opt=no-new-privileges:true --memory=512m

Template configuration

Tuner PortPorttcp

Port Plex and Jellyfin use for the tuner, the guide and the /healthz check.

Target
5004
Default
5004
Value
5004
ChannelsPathro

Folder with your channels.toml. Tellyard reloads it within a minute of a change.

Target
/config
Default
/mnt/user/appdata/tellyard/config
Value
/mnt/user/appdata/tellyard/config
DataPathrw

Guide and yt-dlp caches. Rebuilt when missing.

Target
/data
Default
/mnt/user/appdata/tellyard/data
Value
/mnt/user/appdata/tellyard/data
TunersVariable

Streams that may play at the same time.

Target
TUNERS
Default
4
Value
4
Minimum HeightVariable

Lowest resolution tellyard check accepts, such as 1080. off accepts any. A channel's own min_height in channels.toml overrides it.

Target
MIN_HEIGHT
Default
off
Value
off
Device NameVariable

Name shown in Plex.

Target
DEVICE_NAME
Default
Tellyard
Value
Tellyard
Device IDVariable

8 hexadecimal characters. Plex remembers the tuner by this.

Target
DEVICE_ID
Base URLVariable

Address Plex should use, such as http://192.168.1.10:5004. Set it when the address Plex connects with is not reachable for streams.

Target
BASE_URL
Guide DaysVariable

Days of listings to publish.

Target
GUIDE_DAYS
Default
3
Value
3
Guide Refresh HoursVariable

How often the guide is rebuilt.

Target
GUIDE_REFRESH_HOURS
Default
6
Value
6
yt-dlp ArgumentsVariable

Extra yt-dlp arguments, for example extractor options.

Target
YTDLP_ARGS
Heartbeat URLVariable

Address Tellyard calls once a minute while it is healthy, for a monitor such as Uptime Kuma or Healthchecks.

Target
HEARTBEAT_URL
Log LevelVariable

debug, info, warning or error.

Target
LOG_LEVEL
Default
info
Value
info