Tailscale and networking

Private networking for the self-hosted control plane, including Tailscale and access patterns.

Written By Zoro

Last updated 3 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_ADMIN
  • devices: /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):

VariableRole
TAILSCALE_AUTH_KEYPre-auth key for enrolling or refreshing nodes
TAILSCALE_OAUTH_CLIENT_SECRETOAuth client secret for Tailscale API use from the app
TAILSCALE_TAILNETWhich tailnet the product should target

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

  1. Public HTTP/S on ports 80 and 443 via Traefik (typical).
  2. Tailscale subnet routing or MagicDNS so operators hit the dashboard without public exposure (you still terminate TLS appropriately for your threat model).
  3. A corporate reverse proxy in front of Traefik; preserve Host headers 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).

Related