Automated Backups on Linux
A backup that has never been scheduled, tested, or verified isn’t really a backup, it’s a hope. Automating backups on Linux is straightforward with tools already available on most systems, but the automation itself is the easy part. The parts that actually matter are choosing a sensible strategy, scheduling reliably, and verifying restores work before you need them in an emergency.
The 3-2-1 Rule
A widely used baseline for backup strategy:
- 3 copies of your data (the original plus at least two backups)
- 2 different types of storage media (for example, local disk and cloud object storage, not two copies on the same disk)
- 1 copy stored off-site or offline
This protects against different failure modes independently: a disk failure is covered by having a second copy at all, a whole-machine failure or ransomware event is covered by the off-site copy, and media-type diversity protects against a failure mode specific to one storage type.
Simple Approach: rsync
rsync -av --delete /data/ /backup/current/
-a: archive mode, preserves permissions, timestamps, symlinks, and recurses into directories-v: verbose output--delete: removes files from the destination that no longer exist in the source, keeping the backup an exact mirror
For incremental snapshots that don’t require full copies each time, combine rsync with hard links:
rsync -av --delete --link-dest=/backup/previous/ /data/ /backup/$(date +%F)/
--link-dest tells rsync to hard-link unchanged files from the previous snapshot instead of copying them again. Each snapshot directory looks like a complete, browsable backup, but unchanged files consume no additional disk space, only genuinely changed files use new space.
Archive-Based Approach: tar
tar -czvf /backup/data-$(date +%F).tar.gz /data
Simple and portable, producing a single compressed archive per run. This doesn’t support incremental backups natively as cleanly as the rsync hard-link approach, though tar does support a --listed-incremental mode for true incremental archives if needed. Straightforward full-archive tarballs are often sufficient for smaller datasets where incremental complexity isn’t worth it.
Dedicated Tools: restic and Borg
For more complete backup handling (deduplication, encryption, retention policies, and built-in verification), dedicated tools are usually a better fit than hand-rolled scripts once backup needs grow beyond a single directory copy.
# restic example: initialize a repository, then back up
restic init --repo /backup/restic-repo
restic backup /data --repo /backup/restic-repo
# Borg example: initialize, then back up
borg init --encryption=repokey /backup/borg-repo
borg create /backup/borg-repo::'{now}' /data
Both tools deduplicate data across backup runs (storing only new or changed data blocks, even across different files), encrypt backups at rest, and support pruning old backups according to a retention policy (keep daily for a week, weekly for a month, and so on) without manual bookkeeping.
Scheduling the Backup
Either cron or a systemd timer can trigger a backup script. A simple cron entry running nightly at 2 AM:
# crontab -e
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
For better logging, dependency handling, and integration with systemctl status, a systemd timer paired with a service unit is the more modern equivalent; see the dedicated systemd timers guide for the exact unit file structure.
Whichever scheduler you use, make sure the script:
- Exits with a nonzero status on failure, so scheduling tools can detect it
- Logs enough detail to diagnose a failure after the fact
- Surfaces failures somewhere you’ll actually see them (email, a monitoring webhook, a messaging integration), not just a log file nobody reads
Verifying Backups Actually Work
A backup job completing without errors is not the same as a backup being usable. Corrupted archives, lost encryption keys, and databases backed up mid-write in an inconsistent state can all produce a backup that looks fine and restores to garbage.
Periodically test restores, ideally to a separate environment:
# restic: verify repository integrity
restic check --repo /backup/restic-repo
# actually restore a snapshot to a test location
restic restore latest --target /tmp/restore-test --repo /backup/restic-repo
The only backup you can trust is one you’ve actually restored from. This is worth scheduling as its own periodic task (monthly or quarterly, depending on how critical the data is), not something to leave until an actual emergency forces the first real test.
Frequently Asked Questions
What is the 3-2-1 backup rule?
The 3-2-1 rule recommends keeping at least 3 copies of your data, stored on at least 2 different types of media, with at least 1 copy stored off-site or offline. This protects against multiple failure modes at once: a single disk failure, a whole-machine failure, and site-level disasters like fire, theft, or ransomware that could destroy locally connected backups along with the original data.
Is rsync a real backup solution or just a file copy tool?
rsync is a file synchronization tool, not a purpose-built backup system, but it is commonly used as the basis for backup scripts because it copies only changed data, preserves permissions and timestamps, and can create hard-linked incremental snapshots that look like full backups but consume disk space only for changed files. For more complete backup features like encryption, deduplication, and easier restore verification, dedicated tools like restic or Borg build on similar ideas with more automation.
What is the difference between restic and Borg for Linux backups?
Both are deduplicating, encrypting backup tools with similar core capabilities. Borg has a longer track record and very mature deduplication, but traditionally required direct SSH or local filesystem access to the backup repository. restic supports a wider range of storage backends out of the box, including major cloud object storage providers, without needing a server-side component. Either is a reasonable choice; the decision often comes down to where you want backups stored.
How do I schedule an automated backup script?
Both cron and systemd timers can trigger a backup script on a schedule. A common pattern is a nightly cron entry like 0 2 * * * /opt/scripts/backup.sh, or an equivalent systemd timer for better logging and dependency handling. Whichever you choose, make sure the script exits with a nonzero status on failure and that failures are actually surfaced somewhere you will see them, not just silently logged.
Why do backups need to be tested by actually restoring from them?
A backup job that runs successfully and produces a file of the expected size can still be useless if the archive is corrupted, the encryption key is lost, or the backup captured a database mid-write in an inconsistent state. The only way to know a backup is actually usable is to periodically restore from it, ideally to a separate test environment, and confirm the restored data is complete and functional. Untested backups are a common cause of data loss discovered only during a real emergency.
Should backups be stored on the same server they are backing up?
No, at least not exclusively. A backup stored only on the same disk or server provides no protection against disk failure, accidental deletion, or a compromised server, since whatever destroys the original data is likely to destroy the backup too. Backups should be copied to at least one separate physical location or system, whether that is another server, network-attached storage, or cloud object storage, consistent with the 3-2-1 rule.