Guide
Upgrades, backups, and moving in
Keep TelltaleDNS current, keep a copy of everything you set up, move it to a new machine, and bring your settings over from Pi-hole or Technitium.
- Your version and channel
- Update checks
- Upgrade
- Upgrade a cluster
- Back up
- Restore on a new machine
- Move in from Pi-hole or Technitium
- Troubleshooting
Read the release notes first. Releases before 1.0 can still change configuration keys and APIs, and each release's notes call out every such change. They're on the releases page.
Your version and channel
Every build says exactly what it is, the same way on every architecture:
$ telltale --version
telltale 0.1.0-edge.64 (commit 3f46fd4, built 2026-10-05T12:00:00Z, channel edge, aarch64-unknown-linux-musl)
- Releases are
0.1.0. Builds ofmain(the edge channel) are0.1.0-edge.<run>. A local build isdevwith its commit. - Where else it shows: the web UI's sidebar, Settings → System → Version and updates (with how the node was installed:
native,container, orhelm),GET /api/v1/system/info(buildandupdate), the metrictelltale_build_info{version,commit,channel,target}, and the Cluster page for every node.
Each install type picks its channel its own way:
| Install | Releases | Edge (builds of main) |
|---|---|---|
Native (install.sh) | sudo sh install.sh (the latest release) | sudo sh install.sh --edge, or self-update --channel edge |
| Container image | :latest (the newest stable release), or :X.Y.Z, :X.Y, :X | :edge, built from every commit on main |
| Helm chart | a release version | 0.1.0-edge.<n> chart versions, which follow main |
The edge channel publishes several builds a day.
Update checks
Each node checks for a newer build of its channel by itself. Nothing is installed: TelltaleDNS never updates itself from the UI.
- When: a minute after the node starts, then every 24 hours (an hour after a failed check).
- How: the node reads its channel's
releases.json, which is published with every release and signed with the release key. An index whose signature doesn't verify is ignored. - The result is
up_to_date,available,newer(a dev build), orunknown(not checked yet, or failing). - Where it shows: an update pill next to the version in the sidebar, the Version and updates panel (with the step for your install), each node's version on the Cluster page, and
telltale_update_available(1 when an update exists).
To look now, an admin clicks Check now under Settings → System → Version and updates (or POST /api/v1/system/update-check). Clicks less than a minute apart show the last result without fetching again.
Air-gapped? [updates] check = false means nothing leaves the node. [updates] index_url points at a mirror, which is still verified with the built-in key. See the configuration reference.
Upgrade
The Version and updates panel shows the step for your install. Here are all three.
Raspberry Pi / Linux (native)
For an install made with install.sh:
sudo telltale self-update --check # only look
sudo telltale self-update --restart # upgrade and restart
sudo telltale self-update --channel edge --restart # builds from main
- It verifies the signature with the release key built into the binary and checks the binary's SHA-256, test-runs the download, swaps it in atomically, and keeps the previous binary as
telltale.old. - Or re-run the installer:
sudo sh install.shupgrades the binary in place. When/etc/telltale/telltale.tomlalready exists it asks no questions and only upgrades; your config is kept.
Docker
With Docker Compose (the recommended way on a Pi), in the folder with compose.yaml:
docker compose pull && docker compose up -d
telltale self-update refuses to run in a container: pull a new image instead. Your data lives in the /var/lib/telltale volume, the only path the container writes to.
Kubernetes
Run helm upgrade with the new chart version and the same values file you installed with, or bump the chart version in your GitOps values (Argo CD, Flux):
helm upgrade telltale oci://ghcr.io/paimonsoror/charts/telltale --version <version> \
-n telltale -f my-values.yaml
The chart is published with every release, plus 0.1.0-edge.<n> builds that follow main. The chart's join secret for resolver pods is kept across upgrades. Every value is on Helm values; the rest of the chart is in Run on Kubernetes.
Upgrade a cluster
- Upgrade one node at a time, the replicas first. DNS keeps answering throughout if your clients have two DNS servers (each node is one).
- Upgrade the primary last.
- Check the Cluster page. Its versions check lists the mix of versions until the last node is upgraded.
- A half-upgraded cluster is fine. Versions one cluster protocol apart work together (N and N−1, either way round).
- A replica older than its primary keeps working, unless the primary starts using settings the older version doesn't know. Then the replica keeps serving its last version, and its sync status says to upgrade it.
More in Build a cluster and the cluster docs.
Back up
A backup is one file. Make one before a big change, and whenever you'd hate to set things up again.
- In the web UI: an admin clicks Settings → System → Download a backup.
- Through the API:
GET /api/v1/backup. - On the server, safe while TelltaleDNS runs:
telltale backup create -o pi.ttbk # settings, users, history
telltale backup create --include-qlog -o pi.ttbk # also the query log (can be large)
telltale backup show pi.ttbk # check it and list what's in it
Downloads from the UI and API leave out the query log; use the command for that. Each download is recorded in the audit log as backup.create.
In a backup
The config files the node was started with; users (password hashes, two-factor secrets) and API tokens; devices, names, and forwarded domains made in the UI; the audit log, statistics history, and anomaly baselines; and the query log, with --include-qlog.
Left out
Sign-in sessions (everyone signs in again); downloaded lists, compiled snapshots, and the cache, which are rebuilt; and the cluster identity and its CA key.
Keep it private. It holds password hashes and API tokens. The file is zstd-compressed tar with a manifest of BLAKE3 checksums, written owner-only (0600).
Restore on a new machine
- Install TelltaleDNS on the new machine (see Get started), and copy the backup file to it.
- Stop TelltaleDNS there. Restore refuses while TelltaleDNS runs on that data directory, because it can't take the directory's lock.
- Restore:
Every file is checked before anything is written, so a damaged or truncated backup changes nothing. Existing files are only replaced withtelltale backup restore pi.ttbk--force(the installer writes a starter config, so a fresh install already has one). - Start TelltaleDNS and sign in again. Lists are downloaded and compiled again.
- Point your router's DHCP DNS setting at the new machine.
- Where files go: data goes back to the directory it came from, or
--data-dir; config files go back where they were, or--config-dir. - A different data directory? The restored config still names the old one. Restore says so; set
data_dir(or add a small file that does). - Running it as root is fine: files are given the data directory's owner, so the
telltaleservice user can read them. - A cluster member starts on its own after a restore: run
telltale cluster init, or join it again (Build a cluster).
Details: Backups and moving to a new machine.
Move in from Pi-hole or Technitium
Pi-hole and Technitium DNS Server are the projects that inspired TelltaleDNS, and the importers bring the setup you built there along with you. Each one writes a TelltaleDNS config file and checks that it loads before writing it. The short version is on Get started.
From Pi-hole
telltale import pihole PATH -o pihole.toml
PATH is a Teleporter export (Settings → Teleporter → Export: a .zip from Pi-hole v6, a .tar.gz from v5), a gravity.db, or a copy of /etc/pihole.
What comes over: upstream DNS servers, conditional forwarding, local DNS and CNAME records, adlists (switched-off ones stay with enabled = false), allowed and denied domains (exact and regex), groups, clients (IP, CIDR, MAC), DHCP reservations as named devices, and the DNSSEC, rate-limit, and blocking-mode settings.
What doesn't: query history, the admin password, and API tokens. The header of pihole.toml lists, by setting name, everything else with no equivalent, such as clients matched by host name or network interface (add their IP or MAC instead), the DHCP server, and Pi-hole-only settings.
- On a fresh install, use the file as is next to your node settings:
telltale run -c telltale.toml -c pihole.toml. - Into an existing setup, merge it by hand: both files define the
defaultupstream group and group. - An upstream on the Pi-hole machine itself (
127.0.0.1#5335, usually unbound) is flagged: keep that resolver running next to TelltaleDNS.
Every row of the mapping: Moving from Pi-hole.
From Technitium
The importer reads a running Technitium DNS Server through its API. First create an API token in Technitium (Administration → Sessions → Create Token).
TECHNITIUM_TOKEN=… telltale import technitium http://192.168.1.2:5380 -o technitium.toml
Pass the token in TECHNITIUM_TOKEN or in a file with --token-file. It's never a command-line argument, so it doesn't show up in ps, and it never appears in the output.
What comes over: forwarders, primary zones as local records, forwarder zones (conditional forwarding), block list URLs and blocked and allowed zones, the blocking type, Advanced Blocking app groups, the blocking bypass list, DHCP reservations as named devices, and the DNSSEC, rate-limit, and cache-saving settings.
What doesn't: the header lists it, including secondary and stub zones, forwarders given only by name, the DHCP server, and encrypted listeners (set those up in Encrypted DNS).
Technitium's backup files use a private binary format, so the importer reads the documented API instead. Every row of the mapping: Moving from Technitium.
Zone files from any DNS server (Technitium's Zones → Export Zone, BIND, PowerDNS) become [[record]] entries for your config:
telltale import zone exported.zone > records.toml
The header lists anything with no local equivalent; SOA and NS aren't needed. Names under the zone that you don't import still resolve normally, so a split-horizon domain keeps working. Keep your old server running until TelltaleDNS answers the way you expect, then point your router at TelltaleDNS.
Troubleshooting
| What you see | What to do |
|---|---|
The update status is unknown | The node hasn't checked yet, or the check is failing; a failed check is retried after an hour. On a network with no internet access, set [updates] index_url to a mirror, or [updates] check = false. |
telltale self-update refuses to run | It doesn't run in containers. Pull a new image instead: docker compose pull && docker compose up -d. |
| A replica's sync status says to upgrade it | The primary uses settings the replica's version doesn't know. The replica keeps serving its last version; upgrade it. |
backup restore refuses to start | TelltaleDNS is running on that data directory. Stop the service first. |
backup restore won't replace existing files | Add --force if you mean to overwrite them. |
| The restored node uses the wrong data directory | You restored into a different one: set data_dir in the config (or add a small file that does). |
| A restored cluster member runs on its own | The cluster identity isn't in a backup. Run telltale cluster init, or join it again. |
| "Address already in use" on port 53 after moving from Pi-hole | Pi-hole or another resolver on the same machine must be stopped first. See Get started. |