Tailscale and networking
Private networking for the self-hosted control plane, including Tailscale and access patterns.
Written By Zoro
Last updated 25 days ago
Two different Tailscale topics appear in dFlow.
This page covers the control plane container and network posture from docker-compose.yml. For connecting Worker Nodes through a tailnet, use the in-product server flow and Add a self-hosted server under Worker Nodes and Compute in the sidebar (and Compute and worker node issues under Troubleshooting in the sidebar if SSH or mesh access fails).
Control plane: why NET_ADMIN and /dev/net/tun
The payload-app service in the reference Compose file adds:
cap_add: NET_ADMINdevices: /dev/net/tun
That matches product features that interact with Tailscale-style networking from inside the container. If you remove these, tailnet automation in the app may break. Keep them unless your security team signs off on a reduced-capability profile and you accept limited functionality.
Environment variables (control plane)
Set on payload-app (see Environment configuration):
Create keys in the Tailscale admin console with least privilege and rotation policy your org requires. Store them in a secret manager; inject at deploy time.
Network layout with Compose
The sample stack uses a bridge network custom-tailnet. That name is a Docker network label, not your Tailscale tailnet. Services talk to each other by service name (mongodb, redis, traefik, etc.) on that bridge.
Ingress options
Public HTTP/S on ports 80 and 443 via Traefik (typical).
Tailscale subnet routing or MagicDNS so operators hit the dashboard without public exposure (you still terminate TLS appropriately for your threat model).
A corporate reverse proxy in front of Traefik; preserve
Hostheaders and WebSocket settings your team relies on.
Document whichever pattern you choose so application teams know the URL they should use (NEXT_PUBLIC_WEBSITE_URL must match).
Firewall checklist
Allow 80 / 443 from the internet if you use public ingress.
Restrict MongoDB and Redis ports to the Docker bridge or localhost only (default Compose does not publish them; keep it that way).
For Worker Nodes, open SSH from the control plane (public IP or tailnet IP depending on setup).