Guide
Build a cluster
Two or more nodes on one configuration. Every node answers DNS on its own, you change settings in one place, and every node's dashboard shows the whole cluster.
- The roles
- Create it
- What it shares
- When the primary goes down
- Upgrade and maintenance
- Keep an eye on it
- Troubleshooting
Why bother? Give your router's DHCP two DNS servers, and devices keep resolving while one node restarts, upgrades, or loses its SD card. DNS never depends on the cluster: a node answers the same whether its peers are up or not.
The roles
| Role | What it does |
|---|---|
| Primary | Created the cluster and holds its certificate authority. Publishes the configuration and the compiled blocklists; every version is signed. |
| Replica | Follows the primary and answers DNS from the last version it received, even after a restart with the primary down. Joined with an eligible token, it can be promoted to primary; with a plain token, it only follows. |
| Witness | A tiny vote-only process (on a NAS, router, or small VM) that lets two nodes fail over automatically. It answers no DNS. |
| Resolver pod | On Kubernetes with mode: scaled: joins by itself, holds no state, and can't be promoted. See Run on Kubernetes. |
Create it
Run these as the user TelltaleDNS runs as: sudo -u telltale for a native install, or docker compose exec telltale with Compose.
- Create the cluster on the first node. List every URL other nodes might use to reach it.
telltale cluster init --name home --advertise https://192.168.3.2:8443 --site home-pi - Make a join token on it.
--eligiblelets the new node be promoted later; leave it out for a node that should only follow. Treat the token like a password; it's reusable until it expires.telltale cluster token create --ttl 1h --eligible - Join from the second node. Give an eligible node its own
--advertiseURL, so it can be reached if it's ever promoted.telltale cluster join tt_join_... --site office --advertise https://192.168.3.3:8443 - Restart TelltaleDNS on both nodes, then check:
telltale cluster status, or the web UI's Cluster page (both nodes up on Nodes; every check passing on Health). - Hand out both nodes in DHCP as the first and second DNS server. Then check that devices really use the second one: a failover drill (Drill… on a node's row) silences the first for a few seconds and lists who switched and who was stuck.
The cluster port is [cluster] listen (default 0.0.0.0:8443). Only the first node's port must be reachable: joining nodes connect out to it, so they can sit behind NAT. If you also serve DoH on 8443, move one of them (telltale config check warns about the clash).
Trust: the token carries the fingerprint of the cluster's certificate authority, so a node can't be tricked into joining another server. The link between nodes is mutually authenticated TLS.
A Pi joining a Kubernetes cluster works the same way, with the token made inside the controller pod: see Run on Kubernetes.
When the primary goes down
DNS keeps answering on every node either way. Only configuration changes wait until there's a primary again.
Manual failover
- On an eligible node, open the Cluster page and choose Promote this node…. It asks for your password again (and your authenticator code, if you use two-factor sign-in). Or stop the node, run
telltale cluster promote, and start it. - The node continues from the last version it applied, and every node follows it.
- If the old primary comes back, it steps down by itself. Anything it changed in the meantime is listed under Conflicts (Cluster → Health), so you can make those changes again.
Promotion is refused while the primary is up, so a mistake can't split the cluster.
Automatic failover
Two nodes can't tell "the other node is down" from "the link between us is down", so automatic failover needs a third vote: a witness, or a third eligible node.
# On the primary: a token for the witness
telltale cluster token create --witness
# On the witness host (a config with [node] data_dir and [cluster] listen is enough)
telltale cluster join tt_join_... --witness --advertise https://witness.lan:8443 -c witness.toml
telltale cluster witness -c witness.toml # run it as a service
# On the primary, then restart it
telltale cluster set-failover auto
- The primary holds a 15-second lease with a majority of voters. If it disappears, an eligible node is elected in a new epoch, typically within 15 to 25 seconds.
- There are never two primaries writing: a primary that loses its majority stops taking changes before anyone else can be elected. Clock jumps (a Pi setting its time after boot) don't matter.
- With fewer than three voters,
autoacts as manual, and the Cluster page says so.telltale cluster set-failover manualswitches back.
If the cluster's configuration comes from Git, a node that isn't Git-managed can only take over as an emergency primary: see Git, for the whole cluster.
Upgrade and maintenance
- Upgrade one node at a time: the replicas first, then the primary. Versions one cluster protocol apart work together, so a half-upgraded cluster is fine, and the Cluster page's versions check lists the mix until you're done.
- Taking a node down for longer than a restart? Put it in maintenance first: Maintenance… on its row (Cluster → Nodes), or
telltale ctl maintenance start --for 30m --reason "SD card swap". It reports not ready so load balancers move away, its alerts pause, and it keeps answering what still arrives. - Roll configuration changes out in stages if you like: name canary nodes in Settings → Cluster, and a change reaches them first and everyone else after a bake, pinning back by itself if the canaries start failing. Staged rollouts in the docs.
Keep an eye on it
- The Cluster page: the summary on top, then Nodes (topology and every node's state), Health (checks with what to do when one fails), Rollouts, and Events. A tab with something wrong shows a count.
- The health icon at the bottom of the menu turns amber when a node is unreachable or behind on configuration for a minute.
- Metrics on every node:
telltale_cluster_peer_up,telltale_cluster_peer_config_lag,telltale_cluster_behind_seconds, andtelltale_cluster_cert_expiry_timestamp_seconds. The Helm chart's alert rules cover a peer down, configuration behind, failing syncs, and expiring certificates. - Certificates renew themselves: each node's lasts 90 days and is renewed with 30 left. To replace the cluster's certificate authority, run
telltale cluster rotate-caon the primary; DNS keeps answering while it runs.
Troubleshooting
| What you see | What to do |
|---|---|
| A node is behind on configuration | Look at Cluster → Health for its sync error. A node older than the primary keeps serving its last version once the primary uses settings it doesn't know: upgrade it. |
| The node_settings check fails | That node's own file still sets shared sections (upstreams, lists, groups…). The primary's are used; remove them from the node's file. |
| The second node can't join | Make sure it can reach the first node's cluster port (8443 by default) at one of the --advertise URLs, and that the token hasn't expired (telltale cluster token list). |
| Changes are refused with 503 | There's no primary right now: promote one, or wait for automatic failover. DNS isn't affected. |
| A node can't connect after a CA rotation | It was away for the whole rotation: join it again with a new token. |