README.md

Example setup

keld/ is example content for ~/.config/keld. It contains a config and some env files for the systemd stuff. systemd/user/ contains that systemd stuff. Backup runs daily, verify runs monthly, both read from the env files to ping healthchecks.io and let you know whether your backups failed. Both also use mise to install/execute runitor (for healthchecks) and keld.

config_long.toml is more exhaustive.

1. Copy the configs

mkdir -p ~/.config/keld/timers
cp -r examples/keld/* ~/.config/keld/

2. Edit

Open ~/.config/keld/config.toml and customize it for your backups:

  • Define your presets (e.g., media@hetzner_media, docs@b2_docs)
  • Set your repository URLs
  • Configure environment variables for authentication
  • Set backup sources via _arguments

Backup presets can also define shell hooks:

["media@".backup]
_arguments = ["/home/user/Music/Final"]
_pre_hooks = ["echo preparing media backup"]
_post_hooks = ["echo backup finished with $KELD_RESTIC_STATUS"]

_pre_hooks run before restic backup. If a pre-hook fails, restic is not started and post-hooks do not run. _post_hooks run after restic is attempted, even when restic fails. Post-hooks receive KELD_RESTIC_STATUS and, when restic started, KELD_RESTIC_EXIT_CODE. Use keld --show-command --preset <preset> backup to preview configured hooks without running them.

Keld status names are based on restic's documented exit codes, with one extra status for restic start failures:

Restic exit code KELD_RESTIC_STATUS Meaning
0 success Restic completed successfully.
1 fatal Restic failed; see restic output for details.
2 runtime_error Go runtime error.
3 partial backup could not read some source data.
10 repository_missing Repository does not exist.
11 locked Restic failed to lock the repository.
12 wrong_password Repository password was wrong.
130 interrupted Restic was interrupted.
143 terminated Restic was terminated by SIGTERM.
other non-zero unknown_failure Unknown restic failure; treat as failed.
restic not started start_failed Keld could not start the restic process.

Repeat this to add backups later.

3. Set up healthchecks.io (optional)

Create two checks on healthchecks.io for each backup:

  • One for the backup job
  • One for the verify job

Create env files in ~/.config/keld/timers/:

# ~/.config/keld/timers/mybackup@myrepo.env
CHECK_UUID=your-backup-check-uuid-here

# ~/.config/keld/timers/mybackup@myrepo-verify.env
CHECK_UUID=your-verify-check-uuid-here

Repeat this to add backups later.

4. Install the systemd units

mkdir -p ~/.config/systemd/user
cp examples/systemd/user/* ~/.config/systemd/user/

5. Enable and start the timers

For each backup preset you defined (e.g., media@hetzner_media):

# Escape the @ symbol for systemd instance names
systemctl --user enable keld-backup@media@hetzner_media.timer
systemctl --user start keld-backup@media@hetzner_media.timer

systemctl --user enable keld-verify@media@hetzner_media.timer
systemctl --user start keld-verify@media@hetzner_media.timer

Repeat this to add backups later.

6. Verify everything is working

# List active timers
systemctl --user list-timers

# Check service status
systemctl --user status keld-backup@media@hetzner_media.service

# Test a dry run
keld --show-command --preset media@hetzner_media backup

Repeat this to add backups later.