Skip to content

Getting Started

This is the end-to-end path: from a freshly installed tunlx to a client app playing a stream. Every step below is shown with the screen you will actually see.

If you have not installed tunlx yet, start with Installation and come back here.

No provider yet? See it work first

Sign in, click Add Proxy and choose Start Regional Wizard. It builds a free channel lineup for a country from the public iptv-org catalog in four steps and ends with the address to paste into a player. Step 3 describes it. The rest of this guide is the manual path, for a provider you already have.

Prefer to be guided?

On a brand-new install the dashboard offers an onboarding wizard the first time you sign in, and there is a terminal wizard (./tunlx --xtremeWizard) that builds a whole channel lineup for you. Both are covered in Setup Wizards. This page is the manual path, so you can see what each piece does.


Step 1 — Sign in

tunlx serves its dashboard on port 6060 by default. Open http://<host-ip>:6060 and you land on the sign-in screen.

The tunlx sign-in screen

On a first run with no config.json, tunlx generates one, together with an admin password for the user admin. Look for this block in the startup output (or in docker compose logs tunlx):

================================================================
CRITICAL: No configuration file found. Generating default config.
Your admin username is: admin
Your default admin password is: xXxXxXxXxXxX
It is also saved in /app/data/initial-admin-password.txt until you change it.
Sign in on the dashboard; you will be asked to choose your own.
================================================================

If you did not see it, the sign-in page tells you where to look, and the same password is in initial-admin-password.txt next to config.json (with the Compose file, ./data/initial-admin-password.txt). Signing in with it opens a Choose your own password dialog before the dashboard: the generated password stops working and the file is deleted as soon as you do. Until then nothing else opens, for any session: every page sends you back to that dialog (which has a Sign out button), and every API call is refused with a 403 whose body says passwordChoiceRequired. A script that signed in with the generated password starts by posting currentPassword, newPassword and confirmPassword to /change-password. The new password is stored bcrypt-hashed, and the Account button in the dashboard's header (the person-with-gear icon) changes the username or password again later.

To choose the password up front, set TUNLX_ADMIN_PASSWORD (8–72 bytes) before the first start; nothing is generated or written to disk then. If you lose the password, see Troubleshooting.


Step 2 — Find your way around

After signing in you get the operations dashboard: system health at the top, then every proxy you have configured as a card.

The tunlx dashboard in Simple mode

Simple mode vs Advanced mode

The dashboard opens in Simple mode, which hides the machinery you do not need on day one. The pill at the right of the navbar (it reads Simple mode) switches to Advanced mode, which adds composite proxies, Xtream service editing, the config editor, import/export, and the extra filter tabs. Anything that needs Advanced mode offers a Switch to Advanced button when you click it.

The same dashboard in Advanced mode, showing all proxy types

You need Advanced mode for most of this guide, so switch it on now. See Dashboard Modes for exactly what each mode reveals.

The navbar is the control surface

The icons on the right of the navbar are how you reach everything that is not a proxy: the setup wizard, the web player, Networking, the config editor, stream health tests, activity and telemetry, and the UI-mode toggle. The two chips on the left show your current inbound and outbound routing at a glance. On a phone, and on a tablet or any other touch screen narrower than 1400 px, the same actions are in the menu button, each with its name, because a touch screen has no hover to show one.


Step 3 — Choose what you are building

Click Add Proxy and tunlx asks what you are adding: one of three shapes, or the Regional wizard for when you have no provider. The shape is the most important decision in the whole product, so it is worth understanding before you click.

The proxy type chooser

flowchart TD
    A[What do you have?] --> B{One upstream<br/>Xtream provider?}
    B -->|Yes| C{Want to change<br/>what it offers?}
    C -->|No, just front it| D[Standard Proxy]
    C -->|Merge or curate it| E[Composite Proxy]
    B -->|No, I have raw<br/>stream URLs| F[Xtream Service]

    D --> D1[Stable URL for a provider line<br/>Per-proxy egress routing<br/>EPG auto-refresh]
    E --> E1[Pick categories from several proxies<br/>One set of credentials for clients]
    F --> F1[You own categories, channels and viewers<br/>Full Xtream Codes API, no upstream panel]
Type Use it when Guide
Standard Proxy You have a provider line and want a stable endpoint in front of it, with your own routing and EPG schedule. Standard Proxies
Composite Proxy You have two or more proxies and want to publish one merged catalog under a single login. Composite Catalogs
Xtream Service You have stream URLs (or want to pull from iptv-org) and want tunlx itself to be the panel. Xtream Services

No provider yet?

Choose Start Regional Wizard, the card next to Standard Proxy. It builds a free lineup for a country from the public iptv-org catalog in four steps (country, preview, name and login, done) and ends with the URLs to paste into a player. It is the quickest way to see tunlx work from end to end without a provider.

The rest of this guide walks the Standard Proxy path, because it is the shortest route to working playback. Steps 6 and 7 show where the other two diverge.


Step 4 — Create a Standard proxy

Choosing Create Standard Proxy opens the proxy form.

The standard proxy configuration dialog

The form asks for your provider first, then a name and a port, and folds everything else under Advanced options. Fill in what is above that fold and leave the rest alone for now:

  1. Server URL, with your provider's scheme and port: http://line.northstar.example:8080. If you have an M3U link instead, paste it into M3U Playlist URL and press Auto-fill: it fills this and the login for you.
  2. Username and Password — the credentials your provider issued. tunlx uses these upstream; your clients never see them.
  3. Proxy Name — how the proxy appears on the dashboard and in URLs. Letters, numbers and single dashes, no spaces. Until you type one, it follows the Server URL (line.northstar.example gives northstar); an IP address gives nothing to suggest, so give it a name yourself.
  4. Bind Port — the port this proxy listens on, which your IPTV app connects to. A free one (from 8100) is filled in for you; change it only if you want a particular port. There is no bind-host field; the address clients use is the host's own, shown on the card.

Keep the first proxy boring

Do not switch on MediaFlow, VPN routing, or EPG auto-refresh yet. Get plain playback working first, then add one feature at a time. If you enable three things at once and playback breaks, you have three suspects.

Save. When the proxy is listening, a dialog says so and shows what a player needs: the server address, the username, the password (as dots; the button next to it copies the real one) and the M3U link, each with a copy button, and Open in web player to try it at once. A port that is already taken is refused at this point, with the reason, and nothing is created. The proxy also appears as a card on the dashboard.


Step 5 — Read the proxy card

Click a card's header (or tab to its name and press Enter) to expand it. This is where you spend most of your operational time, so it is worth a proper look.

An expanded standard proxy card

Row What it tells you
Host The address clients should point at. Shows publicBaseURL when you have set one, otherwise the bind host and port.
Target The upstream this proxy fronts.
Route The egress path in force — System, VPN, TS Exit, or Direct. See Inbound & Outbound.
EPG Auto-refresh state and when the guide was last pulled.
Logging Per-proxy verbose toggle, and a Logs button that opens that proxy's live log ring buffer.
Xtream Account Collapsible panel with the upstream credentials and the client-facing URL.
Proxy Connection Collapsible panel with the ready-to-paste connection details for client apps.
Bandwidth / RPS Live throughput and request rate for this proxy alone.

The buttons at the bottom are the per-proxy actions: Play in the built-in player, browse Categories, Clone the proxy, open the OpenAPI explorer, Edit, or Delete.


Step 6 — Verify playback in the browser

Before you touch a TV app, prove the stream works from tunlx itself. Choose Open player in the navbar and pick your proxy, or hit Play on the card.

The built-in web player with a category open

Pick a category on the left, then a channel. If a stream starts here, tunlx is reaching your upstream and re-serving it correctly — everything after this is a client or a networking problem, not a tunlx one. The player's full feature set is covered in Web Player.

Xtream services ask for a viewer login

A Standard or Composite proxy plays straight away. An Xtream service is your own panel, so the player asks for one of the viewer logins you created for it before it will list anything.

The player asking for an Xtream viewer login


Step 7 — Connect a real client

Expand Proxy Connection on the card to get the exact values (the password is drawn as dots; the button next to it copies the real one). There are two ways to hand a lineup to a client app.

Most IPTV apps (TiviMate, IPTV Smarters, OTT Navigator) take these three fields:

Field Value
Server / Portal URL http://<host>:<port> — for example http://203.0.113.10:9101
Username your proxy's Xtream username
Password your proxy's Xtream password

Under the hood the client calls player_api.php, which tunlx answers directly:

curl "http://203.0.113.10:9101/player_api.php?username=USER&password=PASS"

A healthy response contains "auth": 1 and a server_info block.

For players that want a plain playlist:

Playlist: http://<host>:<port>/get.php?username=USER&password=PASS&type=m3u_plus
Guide:    http://<host>:<port>/xmltv.php?username=USER&password=PASS

The playlist comes back with per-channel metadata already filled in:

#EXTM3U
#EXTINF:-1 tvg-chno="1" tvg-id="atlas-news-24.us" tvg-name="Atlas News 24" ...
http://203.0.113.10:9101/live/USER/PASS/101.ts

Set publicBaseURL before going remote

tunlx writes stream URLs into the playlists it generates. If the proxy only knows its LAN address, every URL in the playlist points at a LAN address and remote clients fail after the login succeeds — a confusing failure mode. Set publicBaseURL to the address clients actually reach you on (https://tv.example.org) and the generated URLs follow.


Step 8 — Add reliability, one thing at a time

With baseline playback proven, turn features on individually and re-test between each.


Step 9 — Decide how traffic enters and leaves

Everything so far used plain public networking. The Networking dialog in the navbar sets both directions globally.

The global Networking dialog

flowchart LR
    subgraph IN [Inbound - where listeners bind]
        I1[Public IP]
        I2[Tailscale]
        I3[Both]
    end
    subgraph TX [tunlx]
        P[Proxies and services]
    end
    subgraph OUT [Outbound - where egress goes]
        O1[Public ISP]
        O2[WireGuard VPN]
        O3[Tailscale exit node]
    end
    Clients --> IN --> TX --> OUT --> Upstreams

A per-proxy route overrides the global outbound setting, so one proxy can sit on the VPN while the rest go direct.

Fail-closed is not the default

By default, a proxy whose VPN or exit node is unavailable silently falls back to your ISP connection. If that is unacceptable, enable networking.failClosed globally or strictEgress on the individual proxy. Those proxies then return 503 instead of leaking. Read Inbound & Outbound before you rely on it.


Step 10 — Production checklist

  • Admin password changed from the generated one.
  • publicBaseURL set on every proxy remote clients use.
  • Persistent sessionSecret — otherwise sessions drop on every restart.
  • config.json backed up somewhere you can restore from.
  • Dashboard port 6060 firewalled off, or reachable only over Tailscale.
  • enforceHttps enabled if you terminate TLS in front of tunlx.
  • Fail-closed egress configured if a VPN leak would matter.
  • config.key (next to config.json) backed up and never committed — without it the encrypted secrets in your config cannot be read.

Where to go next