backup
Hardlink-based incremental directory snapshots. Creates dated snapshot directories where unchanged files share inodes with the previous snapshot, consuming zero additional disk. Each snapshot is a complete, browsable directory tree.
Parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
source_dir |
Yes | -- | Directory to back up. |
target_path |
Yes | -- | Base directory for dated snapshots. Snapshots are created as subdirectories named YYYY.JJJ.HH.MM (year, Julian day, hour, minute). |
retain |
No | 30 |
Days of snapshots to keep. Older snapshots are pruned after each run. |
schedule |
No | daily |
Dedup window: daily, hourly, or weekly. Only one snapshot is created per window. |
exclude |
No | -- | Comma-separated glob patterns to skip (e.g., *.swp,*.tmp,cache/*). |
cross_fs |
No | fail |
Behavior when source and target_path are on different filesystems. See below. |
min_free_space |
No | 1G |
Refuse to run if the target filesystem has less than this much free space (e.g., 1G, 500M). Guards against filling the disk mid-backup. |
pre_command |
No | -- | Shell command run before the backup. A non-zero exit aborts the run. |
post_command |
No | -- | Shell command run after a successful backup (e.g., to sync the snapshot offsite). |
revert |
No | false |
When true, run on_revert to undo this resource instead of applying. See Reversal. |
on_revert |
No | -- | Shell command run locally to reverse this resource. Required when revert: true. |
Reversal
backup performs an action with no inferable inverse, so reversal is operator-declared: pair the resource with an on_revert: command (e.g. to prune the snapshots it created).
on_revert:— a shell command, run locally on the agent, that undoes the resource. Inert until triggered.revert: truerunson_revert:once, then reports settled on subsequent runs (idempotent).revert: truewith noon_revert:is rejected atconfig publish.- A normal (non-revert) apply clears a spent revert, re-arming it.
Removing the resource from config does not undo it — that only stops enforcement. Use revert: true with a declared on_revert: to actively undo.
cross_fs Values
| Value | Behavior |
|---|---|
fail |
Refuse to run. Error message explains the constraint and how to fix it. |
copy |
Full copy instead of hardlinks. Logs a warning on every run. |
warn |
Same as copy but only warns on first run. |
Hardlinks cannot span filesystems. If source and target_path are on different mount points, the executor cannot deduplicate. The default fail prevents accidental disk usage. Set cross_fs: copy only after understanding the storage impact.
Idempotency
The executor checks if a snapshot already exists within the current schedule window (same day for daily, same hour for hourly, same week for weekly). If yes, it skips. Only runs once per window regardless of convergence frequency.
How It Works
- Check if today's snapshot exists. If yes, skip.
- Find the most recent existing snapshot as a reference.
- Walk the source directory tree.
- For each file: compare size and mtime against the reference snapshot.
- Unchanged: create a hardlink to the reference copy (zero disk cost).
- Changed or new: copy the file.
- Prune snapshots older than
retaindays.
Disk Usage Example
100 GB source directory, 1% daily change rate:
- 30 daily snapshots with hardlinks: ~100 GB + (30 x 1 GB) = ~130 GB
- 30 daily full copies: 3,000 GB
Examples
Daily /etc backup with 30-day retention
resources:
- name: etc-backup
type: backup
source_dir: /etc
target_path: /var/backups/etc
retain: "30"
Produces:
/var/backups/etc/
2026.088.06.00/
2026.089.06.00/
2026.090.06.00/ <-- today
Hourly config backup
resources:
- name: app-config
type: backup
source_dir: /opt/app/config
target_path: /var/backups/app
retain: "7"
schedule: hourly
exclude: "*.log,tmp/*"
Cross-filesystem with explicit opt-in
resources:
- name: remote-backup
type: backup
source_dir: /data
target_path: /mnt/nas/backups/data
cross_fs: copy
retain: "14"
Platform
Linux, macOS, FreeBSD, Windows (NTFS). Uses std::fs::hard_link which maps to POSIX link() on Unix and CreateHardLinkW on Windows.
Notes
- Source and target_path must be on the same filesystem for hardlink dedup. Use
cross_fs: copyto override with full copies. - Symlinks in the source tree are skipped (not followed or copied).
- Directory permissions are preserved on Unix.
- The executor runs with
nice/ionicepriorities inherited from the agent process. - Snapshot directory names use UTC time.