Tailscale Access¶
Run tunlx on your Tailnet — listeners, dashboard, and even outbound egress — without exposing anything to the public internet. tunlx supports two modes:
Embedded tsnet
tunlx runs its own Tailscale node inside the binary. No sidecar. Configured via tailscale. in config.json or TUNLX_TS_ env vars.
Sidecar container
Use the official tailscale/tailscale image alongside tunlx with network_mode: service:tailscale. Easier when you already run Tailscale that way.

This guide covers the sidecar pattern in detail (compose-friendly) and includes notes on the embedded mode where they differ.
Embedded tsnet quick start¶
For a containerless or single-binary deploy, enable the embedded node:
Precedence is config.json → TUNLX_TS_* env vars → defaults. The first
start logs the node in to your Tailnet using TS_AUTHKEY; state is then
reused from stateDir across restarts.
Once running, the dashboard's Networking panel exposes:
- Current Tailnet status (logged-in, IPs, peers)
- Inbound mode picker (
public/tailscale/both) - Outbound mode picker (
public/vpn/tsexit) - Exit-node selector populated from
/tailnet/peers
See Inbound & Outbound Modes for the topology overview.
Sidecar pattern¶
The sidecar pattern keeps a vanilla Tailscale container alongside tunlx
and uses network_mode: service:tailscale for shared networking.
Enable Tailscale-Only During Install¶
When running install.sh, choose Tailscale access when prompted.
For silent mode:
TUNLX_ADMIN_PASSWORD='change-me-now' \
TUNLX_TAILSCALE_ONLY=1 \
TUNLX_TAILSCALE_AUTHKEY='tskey-auth-XXXXXXXX' \
TUNLX_TAILSCALE_HOSTNAME='tunlx' \
bash install.sh --silent
This configures:
tunlxwithnetwork_mode: service:tailscale- a
tailscalesidecar service - persistent Tailnet state in
tailscale_state
Convert an Existing Install to Tailscale-Only (Manual)¶
If you already installed tunlx in host mode, switch the compose stack manually.
- Back up your compose file.
-
Update your compose stack:
-
Set
tunlx.network_mode: service:tailscale - Add
depends_on: tailscale - Add a
tailscaleservice - If you run MediaFlow, also set
mediaflow.network_mode: service:tailscale
Example:
services:
tunlx:
image: ghcr.io/eyupio/tunlx:latest
restart: unless-stopped
environment:
- commandLine=-configFile=/app/data/config.json
volumes:
- ./data:/app/data
- /var/run/docker.sock:/var/run/docker.sock
- /etc/wireguard:/etc/wireguard
cap_add:
- NET_ADMIN
- NET_RAW
devices:
- /dev/net/tun
network_mode: service:tailscale
depends_on:
tailscale:
condition: service_healthy
mediaflow:
image: mhdzumair/mediaflow-proxy:latest
restart: unless-stopped
environment:
# tunlx shares this network namespace — set mediaFlowURL to http://localhost:8800
- PORT=8800
- API_PASSWORD=change-me
network_mode: service:tailscale
depends_on:
tailscale:
condition: service_healthy
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
restart: unless-stopped
hostname: tunlx
entrypoint: /usr/local/bin/containerboot
volumes:
- tailscale_state:/var/lib/tailscale
environment:
- TS_AUTHKEY=tskey-auth-XXXXXXXX
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=true
healthcheck:
test: ["CMD-SHELL", "tailscale status >/dev/null 2>&1"]
interval: 10s
timeout: 5s
retries: 12
volumes:
tailscale_state:
- Apply changes.
- Verify Tailnet status.
- Access tunlx from Tailnet-only endpoints.
Use your Tailnet DNS name or Tailnet IP if hostname resolution differs.
How-To: Use an Exit Node (Exit Point)¶
If you want tunlx egress to leave from another Tailscale node:
- Choose an available exit node in your Tailnet.
- Set it from the tailscale sidecar.
docker exec tailscale tailscale up \
--accept-routes \
--exit-node=<exit-node-tailnet-ip-or-name> \
--exit-node-allow-lan-access=true
- Confirm it is active.
- Confirm tunlx egress path.
How-To: Use a VPN Exit Point¶
A VPN exit point means your selected Tailscale exit node itself routes through a VPN provider.
Typical pattern:
- Run VPN on the exit-node host (WireGuard/OpenVPN/provider app).
- Advertise/enable that host as a Tailscale exit node.
- Point tunlx to that exit node with the
tailscale up --exit-node=...command above.
This gives tunlx a Tailnet path with VPN-backed egress.
Optional: Advertise This Host as an Exit Node¶
If you want this Tailscale sidecar host to be selectable as an exit point by other Tailnet devices:
Then approve the exit-node advertisement in the Tailscale admin console.
Per-proxy tsexit¶
Even without flipping the global outbound mode to tsexit, individual
proxies can opt in:
{
"proxies": [
{ "name": "premiumA", "route": "tsexit" },
{ "name": "publicB", "route": "system" }
]
}
Each proxy with route: tsexit sends its egress through the configured
Tailscale exit node, while others use the system route. See
Inbound & Outbound Modes for the topology overview.
Notes¶
- If you also use per-proxy
route: vpnin tunlx, you may create double-hop routing. - Prefer one clear egress policy per workload (either tunlx per-proxy VPN routing, or Tailscale exit-node routing).
Related¶
- Inbound & Outbound Modes — global topology
- WireGuard / VPN — the alternative egress
- CLI & Environment — all
TUNLX_TS_*env vars