# xTeVe
## M3U Proxy for Plex DVR and Emby Live TV.
Documentation for setup and configuration is [here](https://github.com/xteve-project/xTeVe-Documentation/blob/master/en/configuration.md).
## About this fork
The upstream xTeVe project has been inactive since 2021. This fork is maintained privately for a single trusted LAN. It is Docker-only and built for amd64 only. There are no release archives and no self-update.
What it adds over upstream:
* Web UI redesign with a mobile and accessibility pass (responsive navigation, keyboard flow, focus visibility, ARIA announcements, contrast).
* Plex API guide refresh: after a lineup or XEPG update xTeVe can ask Plex to reload the DVR guide. New settings: `use_plexAPI`, `plex.url`, `plex.token`.
* Strict or relaxed handling of channels whose EPG source went missing in XEPG, with automatic re-mapping.
* A wizard-completed flag so the setup wizard is not shown again on restart.
* First-party Docker image with a static ffmpeg, runtime `PUID`/`PGID`, and a healthcheck.
* Drone CI: vet, tests, web bundle check, Dockerfile lint, compose validation, image publishing.
* Web UI embedded in the binary with `go:embed`.
* Unauthenticated `GET /healthz` endpoint for container health checks.
* The self-updater and the GitHub branch switching are removed.
The plan for further work is in `tasks/improvement-plan.md`.
## Requirements
### Plex
* Plex Media Server (1.11.1.4730 or newer)
* Plex Client with DVR support
* Plex Pass
### Emby
* Emby Server (3.5.3.0 or newer)
* Emby Client with Live-TV support
* Emby Premiere
---
## Features
#### Files
* Merge external M3U files
* Merge external XMLTV files
* Automatic M3U and XMLTV update
* M3U and XMLTV export
#### Channel management
* Filtering streams
* Channel mapping
* Channel order
* Channel logos
* Channel categories
#### Streaming
* Buffer with HLS / M3U8 support
* Re-streaming
* Number of tuners adjustable
* Compatible with Plex / Emby EPG
---
## Running the container
### Image
The image is built by Drone and pushed to a private registry:
```
registry.coadcorp.com/nathan/xteve
```
Tags:
* `latest` and `` from the `master` branch.
* `` and `` from every other branch.
```bash
docker pull registry.coadcorp.com/nathan/xteve:latest
```
The image is linux/amd64 only.
### Start with Docker Compose
Bridge mode (default). The web UI is on port 34400.
```bash
docker compose up -d
```
Host networking. Use this if you want Plex or Emby to discover the tuner by SSDP/DLNA. Multicast does not cross the Docker bridge, so publishing UDP 1900 in bridge mode is not enough on its own. Linux only.
```bash
docker compose -f docker-compose.host.yml up -d
```
In bridge mode you can still add the tuner manually in Plex or Emby with `http://:34400`.
Both compose files pull `registry.coadcorp.com/nathan/xteve:latest`. To build locally instead, uncomment the `build:` block in the compose file, or run `docker build -t xteve:local .`.
### Environment variables
| Variable | Default | Meaning |
|---|---|---|
| `XTEVE_CONFIG` | `/xteve/config` | Config directory inside the container. |
| `XTEVE_PORT` | `34400` | HTTP port xTeVe listens on. |
| `PUID` | `1000` | User id xTeVe runs as. Set it to the owner of the host config directory. |
| `PGID` | `1000` | Group id xTeVe runs as. |
| `TZ` | unset (UTC) | Time zone, for example `Australia/Sydney`. |
The container starts as root, sets the `xteve` user to `PUID`/`PGID`, fixes the ownership of the config directory if needed, and then drops to that user before starting xTeVe. If the container is started with `--user`, the ids are left alone and xTeVe runs as the given user. The old `XTEVE_UID`/`XTEVE_GID` variables are still accepted as aliases.
### Volume
The config lives in `/xteve/config` (declared as a volume in the image). The compose files bind it to `./docker-data/config`. It holds `settings.json`, the mapping and EPG data, backups and the cache, so it is small enough to back up as a whole.
If an older container kept its config in `/config` or `/home/xteve/.xteve`, the entrypoint copies it to the new location on first start.
### Healthcheck
The image has a `HEALTHCHECK` that requests `http://127.0.0.1:${XTEVE_PORT}/healthz` every 30 seconds. The endpoint needs no authentication and returns the version and whether a scan is in progress. `docker ps` shows the state as `healthy` or `unhealthy`.
### ffmpeg
A static ffmpeg and ffprobe are in the image at `/usr/local/bin/ffmpeg` and `/usr/local/bin/ffprobe`, taken from the pinned `mwader/static-ffmpeg` image. In a container xTeVe defaults `ffmpeg.path` to that location. VLC is not included.
---
## Security notes
* This fork is meant for a trusted LAN. Do not put it on the internet.
* Web authentication is off by default. Turn it on under Settings > Authentication before you expose it any further than the LAN, for example through a reverse proxy.
* `/healthz` is always unauthenticated. It reveals the version and scan state only.
* The container starts as root to apply `PUID`/`PGID` and then drops privileges. Start it with `--user` if you prefer it never to run as root.
---
## Development
See [README-DEV.md](README-DEV.md) for the layout, how to build the binary and the web UI, and how CI publishes the image.