Sync Tailscale devices and services to ControlD DNS rules.
This keeps your ControlD DNS records aligned with what exists in your Tailscale tailnet.
Use case: some clients (for example, browser profiles/containers tied to different endpoints) may not be able to use your local Tailscale DNS resolver. Publishing tailnet host/service names into ControlD makes those names resolvable even when the local resolver isn’t available.
a Client Specific ControlD Resolver for DNS-over-HTTPS (DoH) looks like : https://dns.controld.com/abcd1234/name-goes-here
see more here : https://docs.controld.com/docs/device-clients
- Fetches Tailscale devices and services via the Tailscale API and builds DNS records from their names (supports multiple DNS suffixes and optional bare hostnames).
- Default dry-run mode. Use
--applyto make live changes;--debugfor verbose HTTP output;--quietto suppress startup informational output. - Creates timestamped JSON backups of existing rules before applying changes (live mode).
- Install dependencies:
uv sync- Copy the example config:
cp config_example.py config.py- Edit
config.pyand set your Tailscale and ControlD credentials and settings. - Run (dry run):
uv run syncorpython tailscale_controld_sync.py - Apply changes:
uv run sync --applyorpython tailscale_controld_sync.py --apply - Apply in quiet mode (scheduled tasks):
uv run sync --apply --quietorpython tailscale_controld_sync.py --apply --quiet
When running in live mode the script saves a timestamped backup JSON file named like controld_backup_YYYYMMDD_HHMMSS.json before making changes.