Automatic m3u8 / xml grabber for TheTvApp
♾️ TheTvApp Automated Grabber ♾️
Docker image which automatically fetches the M3U playlist and EPG (XML) guide data for TheTvApp. Can be loaded into IPTV applications such as Jellyfin.
Makes use of the generous work over at https://github.com/dtankdempse/thetvapp-m3u
About
This container allows you to automatically fetch the latest .m3u8 playlist, and .xml guide files for the TheTvApp IPTV service.
Once the container is started up, an initial grab will be done immediately. After that initial grab, the container will periodically grab new copies of the files every X hours, which can be adjusted by modifying the docker environment variables.
The fetched .m3u8 and .xml files are then placed in a self-hosted nginx webserver which allows you to add the direct links directly into applications such as Jellyfin without having to go back and update the files on your own.
Container supports the following:
- Automatically grabs .m3u8 and .xml files when container started up
- Every 60 minutes, a new copy of the .m3u8 and .xml files will be fetched
- Supports both ports
80and443 - Self-signed SSL certificates (optional)
- Mountable volume to control Nginx webserver files
- Customizable URLs via env var should the m3u8 and xml links change
- Integrated nginx hosted file browser for viewing all downloaded files, along with date and file size
Install
Instructions on using this container
Docker Run
If you want to bring the docker container up quickly, use the following command:
docker run -d --restart=unless-stopped -e CRON_TIME=*/60 * * * * -p 443:443 --name thetvapp -v ${PWD}/thetvapp:/config ghcr.io/aetherinox/thetvapp-docker:latest
Docker Compose
Create a new docker-compose.yml with the following:
services:
thetvapp:
container_name: thetvapp
image: ghcr.io/aetherinox/thetvapp-docker:latest
restart: unless-stopped
volumes:
- ./thetvapp:/config
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- CRON_TIME=*/60 * * * *
Caution
Do not add
"quotation marks toCRON_TIMEenvironment variable. Automated timer will not function if you do.✔️ Correct
environment: - CRON_TIME=*/60 * * * *❌ Incorrect
environment: - CRON_TIME="*/60 * * * *"
Traefik
You can put this container behind Traefik if you want to use a reverse proxy and let Traefik handle the SSL certificate.
Dynamic.yml
Open the Traefik dynamic file which is usually named dynamic.yml. We need to add a new middleware, router, and service to our Traefik dynamic file so that it knows about our new TheTVApp container and where it is.
http:
middlewares:
https-redirect:
redirectScheme:
scheme: "https"
permanent: true
routers:
thetvapp-http:
service: thetvapp
rule: Host(`domain.localhost`) || Host(`thetvapp.domain.com`)
entryPoints:
- http
middlewares:
- https-redirect@file
thetvapp-https:
service: thetvapp
rule: Host(`domain.localhost`) || Host(`thetvapp.domain.com`)
entryPoints:
- https
tls:
certResolver: cloudflare
domains:
- main: "domain.com"
sans:
- "*.domain.com"
services:
thetvapp:
loadBalancer:
servers:
- url: "https://thetvapp:443"
Static.yml
These entries will go in your Traefik static.yml file. Any changes made to this file requires that you reset Traefik afterward.
certificatesResolvers
Open your Traefik static.yml file and add your certResolver from above. We are going to use Cloudflare in this exmaple, you can use whatever from the list at:
certificatesResolvers:
cloudflare:
acme:
email: youremail@address.com
storage: /cloudflare/acme.json
keyType: EC256
preferredChain: 'ISRG Root X1'
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 15
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
disablePropagationCheck: true
Once you pick the DNS / SSL provider you want to use from the code above, you need to see if that provider has any special environment variables that must be set. The Providers Page lists all providers and also what env variables need set for each one.
In our example, since we are using Cloudflare for dnsChallenge -> provider, we must set:
CF_API_EMAILCF_API_KEY
Create a .env environment file in the same folder where your Traefik docker-compose.yml file is located, and add the following:
CF_API_EMAIL=yourcloudflare@email.com
CF_API_KEY=Your-Cloudflare-API-Key
Save the .env file and exit.
entryPoints (Normal)
Finally, inside the Traefik static.yml, we need to make sure we have our entryPoints configured. Add the following to the Traefik static.yml file only if you DON'T have entry points set yet:
entryPoints:
http:
address: :80
http:
redirections:
entryPoint:
to: https
scheme: https
https:
address: :443
http3: {}
http:
tls:
options: default
certResolver: cloudflare
domains:
- main: domain.com
sans:
- '*.domain.com'
entryPoints (Cloudflare)
If your website is behind Cloudflare's proxy service, you need to modify your entryPoints above so that you can automatically allow Cloudflare's IP addresses through. This means your entry points will look a bit different.
In the example below, we will add forwardedHeaders -> trustedIPs and add all of Cloudflare's IPs to the list which are available here:
http:
address: :80
forwardedHeaders:
trustedIPs: &trustedIps
- 103.21.244.0/22
- 103.22.200.0/22
- 103.31.4.0/22
- 104.16.0.0/13
- 104.24.0.0/14
- 108.162.192.0/18
- 131.0.72.0/22
- 141.101.64.0/18
- 162.158.0.0/15
- 172.64.0.0/13
- 173.245.48.0/20
- 188.114.96.0/20
- 190.93.240.0/20
- 197.234.240.0/22
- 198.41.128.0/17
- 2400:cb00::/32
- 2606:4700::/32
- 2803:f800::/32
- 2405:b500::/32
- 2405:8100::/32
- 2a06:98c0::/29
- 2c0f:f248::/32
http:
redirections:
entryPoint:
to: https
scheme: https
https:
address: :443
http3: {}
forwardedHeaders:
trustedIPs: *trustedIps
http:
tls:
options: default
certResolver: cloudflare
domains:
- main: domain.com
sans:
- '*.domain.com'
Save the files and then give Traefik and your TheTvApp containers a restart.
Env Variables & Volumes
This section outlines that environment variables can be specified, and which volumes you can mount when the container is started.
Environment Variables
The following env variables can be modified before spinning up this container:
| Env Var | Default | Description |
|---|---|---|
PUID |
1000 | User ID running the container |
PGID |
1000 | Group ID running the container |
TZ |
Etc/UTC | Timezone |
PORT_HTTP |
80 | Defines the HTTP port to run on |
PORT_HTTPS |
443 | Defines the HTTPS port to run on |
CRON_TIME |
0/60 * * * * | Determines how often the .m3u8 and .xml guide files are updated |
URL_XML |
https://raw.githubusercontent.com/dtankdempse/thetvapp-m3u/refs/heads/main/guide/epg.xml | URL to fetch .xml file |
URL_XML_GZ |
https://raw.githubusercontent.com/dtankdempse/thetvapp-m3u/refs/heads/main/guide/epg.xml.gz | URL to fetch .xml.gz file |
URL_M3U |
https://thetvapp-m3u.data-search.workers.dev/playlist | URL to fetch .m3u8 file |
Please note that you can change the URLs for the files fetched from the internet, but it is highly advised to not do this unless you know for sure that the location paths have changed. To change the URLs to the m3u8, .xml, and .xml.gz; change the following environment variables:
URL_XML=https://url/to/file.xmlURL_XML_GZ=https://url/to/file.xml.gzURL_M3U=https://url/to/file.m3u8
Volumes
The following volumes can be mounted with this container:
| Volume | Description |
|---|---|
./thetvapp:/config |
Path which stores downloaded .m3u8, .xml, nginx configs, and optional SSL certificate/keys |
By mounting the volume above, you should now have access to the following folders:
- 📁 keys
- 📁 log
- 📁 nginx
- 📁 php
- 📁 www
| Folder | Description |
|---|---|
| 📁 keys | Responsible for storing your ssl certificate cert.crt + key cert.key |
| 📁 log | All nginx and php logs |
| 📁 nginx | Contains nginx.conf, resolver.conf, ssl.conf, site-confs |
| 📁 php | Contains php-local.ini, www2.conf |
| 📁 www | Folder where downloaded .m3u8, .xml, and .xml.gz will be downloaded to |
Build
You can build your own copy of the image by running the following:
git clone https://github.com/Aetherinox/thetvapp-docker.git .
docker build -t thetvapp .
Shell / Bash
You can access the docker container's shell by running:
docker exec -it thetvapp ash
Contributors ✨
We are always looking for contributors. If you feel that you can provide something useful to Gistr, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources:
Want to help but can't write code?
- Review active questions by our community and answer the ones you know.
The following people have helped get this project going: