# 🧪 Examples, Recipes & Ecosystem Stacks This chapter provides concrete copy & paste solutions for common scenarios spanning the different pillars of the Tuliprox architecture, concluding with the ultimate Docker deployment stack. ## 1. Quickstart: Minimal Provider Setup To use Tuliprox, you need to configure at least three core files: 1. `config.yml`: Defines the core server settings. 2. `source.yml`: Defines the upstream provider and your output targets. 3. `api-proxy.yml`: Defines your local/external server addresses and the users who can access the targets. ### Scenario: Minimal Xtream Setup You have an Xtream provider (`http://fantastic.provider.xyz:8080`) and want to simply "pass through" the streams while utilizing the Web UI. **1. `config.yml` (Core Engine):** ```yaml api: host: 0.0.0.0 port: 8901 web_root: ./web storage_dir: ./data update_on_boot: true ``` *This configuration starts Tuliprox on port 8901. Downloaded playlists are stored inside the `data` folder.* *Setting `update_on_boot: true` is helpful during initial setup to immediately pull provider data.* **2. `source.yml` (Inputs & Targets):** ```yaml inputs: - type: xtream name: my_provider url: http://fantastic.provider.xyz:8080 username: tvjunkie password: junkie.secret sources: - inputs: - my_provider targets: - name: clean_list output: - type: xtream ``` *Here we define the input source based on the provider's information and create a 1:1 mapped target (`clean_list`). The optional target filter is omitted, so every entry passes the processing stage.* **3. `api-proxy.yml` (Servers & Users):** ```yaml server: - name: default protocol: http host: 192.168.1.41 port: 8901 timezone: Europe/Berlin message: Welcome to tuliprox - name: external protocol: https host: tv.my-domain.com port: 443 timezone: Europe/Berlin path: iptv user: - target: clean_list credentials: - username: me password: mypass proxy: redirect # Tuliprox only redirects the player; it does not proxy the video stream server: default ``` *We define two server endpoints (internal LAN and external HTTPS). We then bind a user to the `clean_list` target.* *Using `proxy: redirect` saves bandwidth on your server during initial testing.* **Resulting Client Endpoints:** You can now enter the following credentials into your IPTV player (e.g., TiviMate, IPTV Smarters): * **Portal URL:** `http://192.168.1.41:8901` * **Username:** `me` * **Password:** `mypass` Start `tuliprox`, fire up your IPTV-Application, enter credentials and watch. ### Scenario: Minimal M3U Setup If your provider uses standard M3U instead of the Xtream Codes API, simply adjust the input type in `source.yml`. Tuliprox automatically extracts credentials from the URL if present. **`source.yml` (M3U Variation):** ```yaml inputs: - type: m3u name: my_m3u_provider url: "http://fantastic.provider.xyz:8080/get.php?username=tvjunkie&password=junkie.secret&type=m3u_plus&output=ts" cache_duration: 1d ``` --- ## 2. Advanced Filtering (Exclusion Logic & Templates) A 1:1 pass-through is rarely what you want. Upstream provider lists are often cluttered with countries or VOD sections you don't need. Tuliprox uses a custom DSL (Domain Specific Language) for filtering. You need a basic understanding of Regular Expressions (Regex). A good site for learning and testing is[regex101.com](https://regex101.com/) (ensure you select the **Rust** flavor). ### The Basics DSL filters are applied in `source.yml` at the `target` level. The tilde `~` operator executes a Regex match. Evaluatable fields include `Group`, `Title`, `Name`, `Url`, and `Type`. * **Simple Inclusion:** Include all categories: `Group ~ ".*"` * **Case-Insensitive Inclusion:** Include all categories whose name contains "shopping": `Group ~ "(?i).*Shopping.*"` * **Reversing Logic (Exclusion):** I don't want any shopping categories: `NOT (Group ~ "(?i).*Shopping.*")` * **Specific Channel Exclusion:** Filtering a specific channel, even if it appears in multiple groups: `NOT (Title ~ "FR: TV5Monde" AND Group ~ "FR: TF1")` ### Complex Matrix (Bracket Logic) Allow everything from Germany (DE) and France (FR), except Series and Commercials. Always allow Australia (AU). ```text ((Group ~ "^(DE|FR).*") AND NOT (Group ~ "(?i).*SERIES.*" OR Group ~ "(?i).*COMMERCIAL.*")) OR (Group ~ "^AU.*") ``` ### Refactoring with Templates (The DRY Principle) As you can see, filter strings can quickly become massive and unmaintainable. This is where **Templates**[**Templates**](./configuration/template.md) come into play. You can disassemble a monolithic filter into smaller, readable parts and combine them. ```yaml templates: - name: NO_SHOPPING value: 'NOT (Group ~ "(?i).*Shopping.*" OR Group ~ "(?i).*Einkaufen.*" OR Group ~ "(?i).*téléachat.*")' - name: GERMAN_CHANNELS value: 'Group ~ "^DE: .*"' - name: FRENCH_CHANNELS value: 'Group ~ "^FR: .*"' - name: NO_TV5MONDE_IN_TF1 value: 'NOT (Group ~ "FR: TF1" AND Title ~ "FR: TV5Monde")' - name: EXCLUDED_CHANNELS value: '!NO_TV5MONDE_IN_TF1! AND !NO_SHOPPING!' # Final combination - name: MY_CHANNELS value: '!EXCLUDED_CHANNELS! AND (!GERMAN_CHANNELS! OR !FRENCH_CHANNELS!)' inputs: - type: xtream name: my_provider url: http://fantastic.provider.xyz:8080 sources: - inputs: - my_provider targets: - name: curated_list output: - type: xtream filter: "!MY_CHANNELS!" ``` *The resulting playlist now cleanly contains all French and German channels, minus any shopping channels or specifically blacklisted streams.* --- ## 3. Generating Custom Fallback Videos (FFmpeg) If a provider stream returns a 404 or the user hits their connection limit, it is much more elegant to play an info video ("Channel Offline") than letting the player hang endlessly on a dropped HTTP connection. Tuliprox searches the `custom_stream_response_path` folder for exactly named `.ts` files (MPEG-TS). You can turn a simple image (`blank_screen.jpg`) into a clean, 10-second fallback stream with a silent audio track (crucial for player A/V sync!) using FFmpeg: ```bash ffmpeg -y -nostdin -loop 1 -framerate 30 -i blank_screen.jpg -f lavfi \ -i anullsrc=channel_layout=stereo:sample_rate=48000 -t 10 -shortest -c:v libx264 \ -pix_fmt yuv420p -preset veryfast -crf 23 -x264-params "keyint=30:min-keyint=30:scenecut=0:bframes=0:open_gop=0" \ -c:a aac -b:a 128k -ac 2 -ar 48000 -mpegts_flags +resend_headers -muxdelay 0 -muxpreload 0 -f mpegts channel_unavailable.ts ``` Move `channel_unavailable.ts` into your resources folder. Tuliprox will loop this file from RAM until the user switches channels or the `custom_stream_response_timeout_secs` limit is reached. --- ## 4. The Ultimate Docker Ecosystem Stack Running Tuliprox bare-metal is fine, but running it behind a modern DevSecOps stack provides SSL termination, VPN routing to bypass ISP blocks, and firewall protection against brute-force attacks. In the repository under `docker/container-templates/`, you will find ready-to-use Docker Compose files. ### Components of the Stack 1. **Traefik (Reverse Proxy Ingress):** Handles incoming port 443 traffic, auto-renews Let's Encrypt certificates (via Cloudflare DNS-01 challenge), and applies strict Content-Security-Policy headers. 2. **Gluetun (VPN Egress):** A WireGuard/OpenVPN client container. It connects e.g. to Mullvad or Proton VPN. Tuliprox can then be configured to route its upstream provider requests through this Socks5 proxy, completely hiding your server's IP from the IPTV provider. 3. **CrowdSec (WAF & Bouncer):** Analyzes Traefik access logs in real-time. If someone tries to brute-force your Tuliprox Web UI or run path-traversal attacks, CrowdSec instructs the Traefik Bouncer plugin to drop their IP at the edge. 4. **IPTV-org-epg (EPG guide):** Generates a local XMLTV guide for the selected channels and makes it available to Tuliprox. ### How to wire it up **1. Create the Docker Networks:** ```bash docker network create proxy-net docker network create crowdsec-net ``` **2. Configure Gluetun & Socks5:** In `container-templates/gluetun/.env.wg`, add your Wireguard details. In `container-templates/gluetun/.env.socks5-proxy`, set user/pass for the proxy. Start it: `docker-compose up -d`. It exposes port 1388 internally. **3. Configure Tuliprox to use the VPN:** In your `config.yml`, point the global proxy setting to the Socks5 container: ```yaml proxy: url: socks5://gluetun:1388 username: "" password: "" ``` *Note: Ensure Tuliprox and the Socks5 container share the `proxy-net` network.* **4. Protect Tuliprox with Traefik Labels:** In your Tuliprox `docker-compose.yml`, add the Traefik labels to route traffic securely: ```yaml labels: - "traefik.enable=true" - "traefik.http.routers.tuliprox-secure.entrypoints=websecure" - "traefik.http.routers.tuliprox-secure.rule=Host(`tv.yourdomain.com`)" - "traefik.http.routers.tuliprox-secure.tls=true" - "traefik.http.routers.tuliprox-secure.tls.certresolver=cloudflare" # Attach CrowdSec Bouncer and Security Headers - "traefik.http.routers.tuliprox-secure.middlewares=cs-bouncer-traefik-plugin@file,default-security-headers@file" - "traefik.http.services.tuliprox.loadbalancer.server.port=8901" ``` This architecture ensures your IPTV provider only sees the VPN IP, your clients only see your secure `tv.yourdomain.com` domain, and malicious bots are blocked instantly by CrowdSec before they even reach the Rust backend. >**⚠️ Important:** make sure you add >[tuliprox-cover-whitelist.yaml](../../docker/container-templates/crowdsec/crowdsec/config/parsers/s02-enrich/tuliprox-cover-whitelist.yaml) > to `crowdsec/config/parsers/s02-enrich/tuliprox-cover-whitelist.yaml` in your Crowdsec instance. > Otherwise, you could quickly end up banning yourself. **5. Configure IPTV-org-epg:** Copy the desired channel entries from the IPTV-org `sites` files to `container-templates/iptv-org/data/channels.xml`. For every channel, `xmltv_id` must exactly match the corresponding `@epg_channel_id` in Tuliprox. For example, `xmltv_id="BBCOne.uk@LondonHD"` matches `@epg_channel_id = "BBCOne.uk@LondonHD"`. If necessary, adjust `xmltv_id` in `channels.xml` or set the corresponding `@epg_channel_id` in `mapping.yml`. Start it: `docker-compose up -d`. Add the generated guide to the corresponding input in your `source.yml`: ```yaml epg: sources: - url: http://iptv-org-epg:3000/guide.xml ```