Skip to content

MediaFlow Integration

MediaFlow Proxy is a caching and optimization proxy for IPTV streaming. tunlx integrates with it out of the box: turn it on per proxy and tunlx routes the right paths through MediaFlow without changing your client setup.

Why bother

  • Adaptive buffering for HLS streams that stutter on slow upstreams.
  • Range request handling so VOD seeking actually works.
  • Origin offload — MediaFlow does the heavy lifting, your tunlx host doesn't.
  • Header preservation for upstreams that gate on auth headers.

Path routing

When mediaFlowEnabled is true, tunlx routes these client paths through MediaFlow:

Client path MediaFlow target
/live/... /proxy/hls or /proxy/stream (by extension)
/movie/... /proxy/hls or /proxy/stream
/series/... /proxy/hls or /proxy/stream
/hls/... /proxy/hls

Everything else (login, EPG, category lists, account info) still goes directly to the upstream — MediaFlow is only in the data path.

Configure a proxy

{
  "proxies": [
    {
      "name": "iptv-proxy",
      "targetServer": "http://xtream-origin:8080",
      "thisServerHost": "0.0.0.0",
      "thisServerPort": "8080",
      "mediaFlowEnabled": true,
      "mediaFlowURL": "http://mediaflow:8800"
    }
  ]
}
  1. Open the proxy.
  2. Set MediaFlow ON.
  3. Enter the MediaFlow URL (e.g. http://mediaflow:8800).
  4. Save and verify with the built-in player.

Run MediaFlow alongside tunlx

docker run -d \
  --name mediaflow \
  --restart unless-stopped \
  -p 8800:8800 \
  mhdzumair/mediaflow-proxy:latest
services:
  tunlx:
    image: ghcr.io/eyupio/tunlx:latest
    # ...

  mediaflow:
    image: mhdzumair/mediaflow-proxy:latest
    container_name: mediaflow
    restart: unless-stopped
    environment:
      # Listen on 8800 so the default mediaFlowURL (http://mediaflow:8800) works
      - PORT=8800
    ports:
      - "8800:8800"

If you're running Tailnet-only access, put MediaFlow on the same network_mode: service:tailscale namespace so the bridge URL resolves the same way for tunlx:

mediaflow:
  image: mhdzumair/mediaflow-proxy:latest
  network_mode: service:tailscale
  depends_on:
    tailscale:
      condition: service_healthy

Defaults via env vars

Set platform-wide defaults so individual proxies don't need to repeat them:

Variable Purpose
TUNLX_MEDIAFLOW_BASE_URL Fallback mediaFlowURL when a proxy doesn't override it.
API_PASSWORD API password used for MediaFlow calls if not embedded in the URL.
MEDIAFLOW_API_PASSWORD Fallback if API_PASSWORD is unset.

Verify it's actually in the path

After enabling:

# Should answer (from the host; inside the tunlx container use http://mediaflow:8800)
curl -s http://localhost:8800/health

# Should see a request flagged through /proxy/stream or /proxy/hls
docker logs --tail=50 mediaflow

In the dashboard's Activity & Telemetry, the proxy row will show a MediaFlow badge so you can confirm at a glance.

When not to use MediaFlow

  • redirectStreams mode (302 to upstream) — tunlx steps out of the data path entirely. MediaFlow can't see traffic it never receives.
  • Already-fast upstreams — added hop, added complexity, no payoff.
  • Strict per-client-IP origins — MediaFlow becomes the client IP from the upstream's point of view.