Syncs Tailscale (or Headscale) host IPs to a cloudflare hosted DNS zone. Basically works like Magic DNS, but with your domain. The main benefit for me is the ability to use letsencrypt with certbot + dns challenge
- Adds ipv4 and ipv6 records for all devices
- Removes DNS records for deleted devices
- Updates DNS records after the hostname/alias changes
- Add a pre- and/or postfixes to dns records
- Checks if DNS records is part of tailscale network (100.64.0.0/12 or fd7a:115c:a1e0::/48) before deleting records :P
- Support Tailscale and Headscale (tested with v0.22.3)
docker run --rm -it --env-file ~/git/tailscale-cloudflare-dnssync/env.txt ghcr.io/marc1307/tailscale-cloudflare-dnssync:latest
Envfile:
# mode=<tailscale or headscale, default to tailscale if empty, optional>
cf-key=<cloudflare api key>
cf-domain=<cloudflare target zone>
# cf-sub=<subdomain to use, optional>
ts-key=<tailscale api key>
ts-tailnet=<tailnet>
# ts-clientid=<oauth clientid, optional>
# ts-clientsecret=<oauth clientsecret, optional>
# prefix=<prefix for dns records, optional>
# postfix=<postfix for dns records, optional>
ts-tailnet can be found in the Tailscale Settings
Settings -> General -> Organization
or at the top left on the admin panel.
secrets:
cf-key:
file: "./cloudflare-key.txt"
# either, use ts-key for an api key or ts-clientid and ts-clientsecret for oauth
ts-key:
file: "./tailscale-key.txt"
ts-clientid:
file: "./tailscale-clientid.txt"
ts-clientsecret:
file: "./tailscale-clientsecret.txt"
services:
cloudflare-dns-sync:
image: ghcr.io/marc1307/tailscale-cloudflare-dnssync:latest
environment:
- ts_tailnet=<tailnet>
- cf_domain=example.com
- cf_sub=sub # optional, uses sub domain for dns records
- prefix=ts- # optional, adds prefix to dns records
- postfix=-ts # optional, adds postfix to dns records
secrets:
- cf-key
- ts-key
python3 -m venv env
source env/bin/activate
pip install -r app/requirements.txt
cd app
python app.py
[DEFAULT]
mode= # optional; tailscale or headscale; defaults to tailscale
cf-key= # mandatory; cloudflare api key
cf-domain= # mandatory; cloudflare domain
cf-sub= # optional; add a subdomain
ts-tailnet= # mandatory in tailscale mode; tailnet name
ts-key= # mandatory in tailscale mode if apikey is used; tailscale api
ts-client-id= # mandatory in tailscale mode if oauth is used; tailscale oauth client id
ts-client-secret= # mandatory in tailscale mode if oauth is used; tailscale oauth client secret
hs-baseurl= # mandatory in headscale mode; headscale url
hs-apikey= # mandatory in headscale mode; headscale apikey
mode=headscale
cf-key=<cloudflare api key>
cf-domain=<cloudflare target zone>
hs-baseurl=https://headscale.example.com
hs-apikey=≤headscale api key>
- Login to Cloudflare Dashboard
- Create API Key at https://dash.cloudflare.com/profile/api-tokens
- Template: Edit Zone
- Permissions:
Permission | Zone - DNS - edit
Resource | include - specific zone - <your zone>
- Login to Tailscale website
- Create API key at: https://login.tailscale.com/admin/settings/authkeys
- Login to Tailscale website
- Create OAuth client at: https://login.tailscale.com/admin/settings/oauth with Devices Read permission
- Create a API Key using
headscale apikeys create --expiration 90d