Configuration reference
zolder reads a single machine-local TOML file, zolder.toml. zolder init writes a working one for you; this page is the full reference for hand-editing it afterwards.
Every check section is optional and config-gated per machine — a machine runs only the checks it declares. The Mac and Windows peers drop [zfs]; a box outside the mesh drops [syncthing]. Unknown keys are rejected (the parser uses deny_unknown_fields), so a typo is an error rather than a silently ignored setting.
Complete example
The annotated zolder.example.toml ships with every release. It is embedded verbatim from that source file at build time, and CI parse-tests it against the config structs (example_config_parses in src/config.rs), so this reference cannot drift from what the binary actually accepts:
# zolder machine-local config. The easy path is `zolder init`, which discovers
# Syncthing and writes a working config into the platform config dir for you;
# this file is the full reference for hand-editing afterwards.
#
# Copy to zolder.toml (gitignored) per machine. Every check section is optional
# — a machine runs only what it declares: the Mac/Windows peers drop [zfs]; a
# box outside the mesh drops [syncthing].
# Point this into a synced folder and the mesh itself carries every device's
# status report to the node (fleet aggregation, post-MVP).
status_path = "zolder.json"
[syncthing]
url = "http://127.0.0.1:8384"
api_key_file = "/home/demian/.config/zolder/syncthing-api-key"
device_max_last_seen_hours = 24
[restic]
binary = "restic"
# What `zolder run backup` backs up — typically the synced tree on the node.
paths = ["/data/sync"]
exclude = ["**/node_modules", "**/target"]
[[restic.repo]]
name = "hetzner"
repository = "s3:https://fsn1.your-objectstorage.example/zolder-backup"
password_file = "/home/demian/.config/zolder/restic-password"
env_file = "/home/demian/.config/zolder/restic-hetzner.env"
max_snapshot_age_hours = 36
[[restic.repo]]
name = "scaleway"
repository = "s3:https://s3.nl-ams.scw.cloud/zolder-backup"
password_file = "/home/demian/.config/zolder/restic-password"
env_file = "/home/demian/.config/zolder/restic-scaleway.env"
max_snapshot_age_hours = 36
[canary]
dir = "/data/sync/.zolder/canary"
max_age_hours = 24
# Home node only — omit on Mac/Windows peers.
[zfs]
pools = ["tank"]
[alert]
# Dead-man's switch: pinged on every completed run, `<url>/fail` when unhealthy.
# heartbeat_url = "https://hc-ping.com/<uuid>"
[alert.ntfy]
server = "https://ntfy.sh"
topic = "zolder-CHANGE-ME"
# Bearer token for a self-hosted / protected ntfy topic.
# token_file = "/home/demian/.config/zolder/ntfy-token"The sections below are the field-by-field reference — types, defaults, and semantics for every key above.
Top level
| Key | Type | Default | Notes |
|---|---|---|---|
status_path | path | required | Where zolder check writes its report. zolder init points this at zolder.json in the config dir. Point it into a synced folder and the mesh itself carries every device's status to the node (fleet aggregation, post-MVP). |
[syncthing] — mesh health (optional)
Read-only Syncthing REST health: per-folder sync state and backlog, plus whether every configured peer is connected or was seen recently enough.
| Key | Type | Default | Notes |
|---|---|---|---|
url | string | required | REST API base, e.g. http://127.0.0.1:8384. |
api_key_file | path | required | File holding the API key — never the key itself in config. |
device_max_last_seen_hours | integer | 24 | Fail when a disconnected peer hasn't been seen for longer than this. |
A folder in error or with scan errors fails; a paused folder or a growing backlog warns; a peer unseen past the threshold fails.
[restic] — backup freshness (optional)
Read-only restic freshness per repo: is the newest snapshot young enough? A repo that can't be queried, one with no snapshots, or one whose newest snapshot is past its age threshold all fail.
| Key | Type | Default | Notes |
|---|---|---|---|
binary | string | "restic" | restic binary to invoke; found on PATH by default. |
paths | array of paths | [] | What zolder run backup backs up. The freshness check doesn't use this. |
exclude | array of strings | [] | Extra --exclude globs for the backup run. |
At least one repository must be declared as a [[restic.repo]] table:
| Key | Type | Default | Notes |
|---|---|---|---|
name | string | required | Label in reports, e.g. "hetzner". |
repository | string | required | restic repository URL, e.g. s3:https://…. |
password_file | path | required | restic password file. |
env_file | path | optional | Extra env (credentials) sourced at run time. KEY=VALUE per line; blank lines and # comments are ignored. |
max_snapshot_age_hours | integer | 36 | Fail when the newest snapshot is older than this. |
[canary] — sync liveness (optional)
Each peer writes its own <host>.canary marker into a shared synced folder on every check run and reads the others' freshness — catching "everything reports healthy but nothing actually moves". Failing to write our own marker fails the check (the synced tree isn't writable); a stale or absent peer marker warns.
| Key | Type | Default | Notes |
|---|---|---|---|
dir | path | required | Directory inside a synced folder. |
max_age_hours | integer | 24 | A peer marker older than this is stale. |
[zfs] — pool health (optional, node only)
Shells out to zpool list and reports; any pool not ONLINE fails. zolder never scrubs, imports, or resilvers. Omit this section on the Mac/Windows peers.
| Key | Type | Default | Notes |
|---|---|---|---|
pools | array of strings | required | Pools that must be ONLINE. |
[alert] — notifications (optional)
See Alerting for the full semantics.
| Key | Type | Default | Notes |
|---|---|---|---|
heartbeat_url | string | optional | Dead-man's switch: pinged (GET) on every completed run, <url>/fail when unhealthy. |
[alert.ntfy] — push channel (optional)
| Key | Type | Default | Notes |
|---|---|---|---|
server | string | "https://ntfy.sh" | ntfy server base. |
topic | string | required | ntfy topic to publish alerts to. |
token_file | path | optional | Bearer token for a self-hosted / protected ntfy topic. |