How to Set Up Automated Backups
A backup that runs manually is a backup that gets forgotten. The goal of this guide is a fully automated system that runs daily without intervention, keeps a sensible history of snapshots, and alerts you when something goes wrong. By the end, you will have encrypted, deduplicated backups running on a schedule with automatic pruning of old snapshots.
Step 1: Choose Your Backup Tool and Storage Backend
Your first decision is which tool to use and where to store the backup data. For most self-hosted setups, the practical choices are:
Restic if you want to back up directly to cloud object storage (Backblaze B2, Amazon S3, Wasabi, MinIO) or need cross-platform support including Windows. See the BorgBackup vs Restic vs Kopia comparison for a detailed analysis.
BorgBackup if you are on Linux or macOS and want to back up over SSH to a remote server you control, or to a local external drive. Borg offers superior compression and storage efficiency.
Kopia if you prefer a graphical interface or need centralized backup management for multiple machines through its server mode.
For storage, the most common self-hosted configurations are: a local external drive or NAS as the primary backup target, plus a cloud destination (typically Backblaze B2 at roughly $5/TB/month) for offsite protection. This satisfies the 3-2-1 backup rule at minimal cost.
Step 2: Install the Backup Tool
Restic on Ubuntu/Debian:
sudo apt update
sudo apt install restic
For the latest version (package manager versions can lag behind), download the official binary directly:
wget https://github.com/restic/restic/releases/download/v0.17.3/restic_0.17.3_linux_amd64.bz2
bunzip2 restic_0.17.3_linux_amd64.bz2
chmod +x restic_0.17.3_linux_amd64
sudo mv restic_0.17.3_linux_amd64 /usr/local/bin/restic
BorgBackup on Ubuntu/Debian:
sudo apt update
sudo apt install borgbackup
Kopia: Download the latest release from the Kopia website or install via the package repository for your distribution. Kopia also offers a GUI installer for desktop use.
Verify the installation by running restic version or borg --version to confirm the tool is accessible.
Step 3: Initialize an Encrypted Backup Repository
A repository is the storage location where your backup data lives. You must initialize it once before your first backup. During initialization, you set a password that encrypts all backup data.
Restic with Backblaze B2:
export B2_ACCOUNT_ID="your-account-id"
export B2_ACCOUNT_KEY="your-account-key"
restic -r b2:your-bucket-name init
Restic with a local directory:
restic -r /mnt/backup-drive/restic-repo init
BorgBackup with SSH remote:
borg init --encryption=repokey user@backup-server:/srv/backups/myhost
BorgBackup with local storage:
borg init --encryption=repokey /mnt/backup-drive/borg-repo
Store your repository password in a secure location. If you lose this password, your backup data is permanently inaccessible. Write it down and keep it in a safe, store it in a password manager, or both. For automated scripts, store the password in a file readable only by root: echo "your-password" > /root/.restic-password && chmod 600 /root/.restic-password.
Step 4: Run Your First Manual Backup
Before automating anything, verify that a manual backup completes successfully.
Restic:
restic -r b2:your-bucket-name \
--password-file /root/.restic-password \
backup /home /etc /var/www \
--exclude="*.tmp" \
--exclude=".cache"
BorgBackup:
export BORG_PASSPHRASE="your-password"
borg create \
user@backup-server:/srv/backups/myhost::$(hostname)-$(date +%Y-%m-%d) \
/home /etc /var/www \
--exclude "*.tmp" \
--exclude "*/.cache"
Both tools will scan the specified directories, chunk the data, deduplicate against any existing snapshots, compress, encrypt, and upload the result to your repository. The first backup takes the longest because all data is new. Subsequent backups process only changed files and typically complete in seconds to minutes depending on the volume of changes.
After the backup completes, list your snapshots to confirm:
# Restic
restic -r b2:your-bucket-name snapshots
# BorgBackup
borg list user@backup-server:/srv/backups/myhost
Step 5: Configure Retention Policies
Retention policies determine how many old snapshots to keep and when to remove them. Without a retention policy, your repository grows indefinitely. A common sensible policy is: keep 7 daily snapshots, 4 weekly, 12 monthly, and 2 yearly.
Restic:
restic -r b2:your-bucket-name forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--keep-yearly 2 \
--prune
The --prune flag tells Restic to actually remove the data for forgotten snapshots. Without it, the snapshot references are removed but the data chunks remain on disk.
BorgBackup:
borg prune \
user@backup-server:/srv/backups/myhost \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=12 \
--keep-yearly=2
After pruning, run borg compact to reclaim disk space from deleted chunks. This is a separate step in Borg because compaction can be resource-intensive on large repositories.
Step 6: Automate with Cron or Systemd
Wrap your backup, forget, and prune commands into a shell script, then schedule it to run daily.
Example backup script (/root/backup.sh):
#!/bin/bash
set -euo pipefail
export B2_ACCOUNT_ID="your-account-id"
export B2_ACCOUNT_KEY="your-account-key"
RESTIC_REPO="b2:your-bucket-name"
RESTIC_PASSWORD_FILE="/root/.restic-password"
# Run backup
restic -r "$RESTIC_REPO" \
--password-file "$RESTIC_PASSWORD_FILE" \
backup /home /etc /var/www \
--exclude="*.tmp" \
--exclude=".cache" \
--quiet
# Apply retention policy
restic -r "$RESTIC_REPO" \
--password-file "$RESTIC_PASSWORD_FILE" \
forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--keep-yearly 2 \
--prune \
--quiet
# Check repository integrity (weekly, on Sundays)
if [ "$(date +%u)" = "7" ]; then
restic -r "$RESTIC_REPO" \
--password-file "$RESTIC_PASSWORD_FILE" \
check --quiet
fi
Make the script executable: chmod 700 /root/backup.sh
Cron scheduling:
# Edit root crontab
sudo crontab -e
# Add this line to run at 2 AM daily
0 2 * * * /root/backup.sh >> /var/log/backup.log 2>&1
Systemd timer (alternative to cron): Create a service unit and timer unit for more robust scheduling with logging, dependency management, and failure notifications. Systemd timers are preferred on modern Linux systems because they integrate with journald for centralized logging and can be monitored with systemctl status.
Step 7: Test Restoration
A backup is only valuable if you can restore from it. Test restoration immediately after your first successful backup, and schedule periodic restore tests (monthly is a good cadence).
Restic: restore a specific file
restic -r b2:your-bucket-name \
--password-file /root/.restic-password \
restore latest \
--target /tmp/restore-test \
--include "/home/user/documents/important-file.txt"
Restic: restore an entire snapshot
restic -r b2:your-bucket-name \
--password-file /root/.restic-password \
restore latest \
--target /tmp/full-restore
BorgBackup: restore a specific file
cd /tmp/restore-test
borg extract user@server:/srv/backups/myhost::latest \
home/user/documents/important-file.txt
After restoring, compare the restored files with the originals to verify data integrity. Check file sizes, permissions, and a sample of file contents. For large deployments, automate this verification with a script that compares checksums.
Monitoring and Alerting
Once your automated backup is running, you need to know when it fails. The simplest approach is to have your backup script send an email or webhook notification on failure. Add error handling to your backup script that sends an alert if any command exits with a non-zero status. For more sophisticated monitoring, tools like Prometheus with a backup-status exporter, or simple healthcheck services like Healthchecks.io, can track whether your backup script runs on schedule and alert you if it misses a run.
Review your backup logs weekly. Check that backup sizes are consistent (a sudden drop might indicate excluded directories), that pruning is working correctly, and that integrity checks pass without errors. The few minutes spent on weekly log review can catch problems before they become data loss events.
The difference between having backups and not having backups is automation. A manual backup you forget to run is no backup at all. Set up the schedule, configure retention, test restoration, and then let the system work unattended.