Skip to content

Backups with Restic

Restic is a fast, secure backup program with a design very similar to Borg — content-defined deduplication and client-side authenticated encryption — but with first-class support for object storage. It writes directly to S3, Backblaze B2, Azure, Google Cloud Storage, SFTP, or (via rclone) almost anything. That makes it a natural fit when your off-site target is a cloud bucket rather than a Borg/SSH host.

For an SSH-and-append-only-target workflow, compare Backups with Borg.

  • Many backends out of the box (S3, B2, GCS, Azure, SFTP, local) plus rclone.
  • Deduplication across all snapshots in a repository.
  • Authenticated encryption (AES-256 + Poly1305), client-side — the bucket holds only ciphertext.
  • Single static binary, easy to run anywhere including containers.

Restic reads the repository location and password from environment variables, which keeps secrets out of your command history and cron lines:

Terminal window
export RESTIC_REPOSITORY="s3:https://s3.example.com/my-backup-bucket"
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export RESTIC_PASSWORD="a-long-random-passphrase" # or RESTIC_PASSWORD_FILE
restic init
Terminal window
restic backup /etc /srv --tag nightly # creates a snapshot
restic snapshots # list snapshots
restic stats # repository size / dedup ratio

Deduplication and encryption happen automatically — there is no separate flag to enable them.

A systemd timer is more robust than cron (logging, dependency ordering, Persistent= to catch missed runs). The unit reads credentials from an EnvironmentFile:

/etc/systemd/system/restic-backup.service
[Service]
Type=oneshot
EnvironmentFile=/etc/restic/env # RESTIC_REPOSITORY, RESTIC_PASSWORD, keys
ExecStart=/usr/bin/restic backup /etc /srv --tag nightly
ExecStartPost=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
/etc/systemd/system/restic-backup.timer
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target

Enable with systemctl enable --now restic-backup.timer.

forget applies a retention policy to the snapshot index; --prune then deletes the now-unreferenced data:

Terminal window
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check # verify repository integrity (run periodically)
Terminal window
restic restore latest --target /mnt/restore # whole latest snapshot
restic restore <snapshot-id> --include /etc --target /tmp # selected paths
restic mount /mnt/restic # browse all snapshots as files

Run a restore to a scratch directory on a schedule and confirm the data is intact — an untested backup is not a backup. Tie this into your Disaster Recovery runbooks.