rsync, tar, and snapshot tools working together
A reliable backup concept combines efficient incremental synchronization with rsync, portable archives with tar, and consistent snapshots without downtime. This guide shows how these tools, together with the 3-2-1 rule, add up to a resilient strategy for a small server fleet, including the restore tests that are the only thing that truly verifies a backup.
Table of Contents
- 1. Why a Backup Concept Is More Than a Cron Job
- 2. rsync: Efficient Incremental Synchronization
- 3. rsync with Hardlinks: Snapshot-Like History Without a Snapshot Tool
- 4. tar: Portable Archives for Long-Term Archiving
- 5. LVM Snapshots: Consistent Backups Without Downtime
- 6. Btrfs and ZFS Snapshots as an Alternative
- 7. Applying the 3-2-1 Rule in Practice Across a Server Fleet
- 8. Restore Tests: A Backup Is Only Verified Once It Has Been Restored
- 9. Backup Tools Compared Head to Head
- 10. Summary
- 11. FAQ
1. Why a Backup Concept Is More Than a Cron Job
A single rsync call in the crontab feels like a backup, but it is really just one building block of one. A solid backup concept answers four questions at once: how data is transferred efficiently, how it is frozen consistently at a fixed point in time, where the copies physically live, and how it is regularly verified that a restore actually works. Anyone who only answers the first question has a copy, not a strategy.
On a small server fleet with several application servers, a database, and changing storage backends, three classes of tools typically come into play: rsync for efficiently transferring file trees, tar for portable, versionable archives, and snapshot mechanisms like LVM or Btrfs for consistent states during ongoing writes. None of these tools fully replaces the others, each solves a different sub-problem, and in practice they are used together.
The following sections cover each tool in detail, present the 3-2-1 rule as the organizational framework, and close with the most important, and most often neglected, step: the regular restore test, without which any backup strategy remains nothing more than an unproven assumption.
2. rsync: Efficient Incremental Synchronization
On every run, rsync transfers only the blocks of a file that actually changed, not the entire file again. Its delta-transfer algorithm compares checksums between source and destination and identifies exactly the byte ranges that have changed since the last run. For large, slowly-changing datasets such as uploads directories or log archives, this often cuts the amount of data transferred by more than ninety percent compared to a full copy.
The flags -a (archive mode, preserves permissions, timestamps, and symlinks), -v (verbose), and --delete (removes files at the destination that were deleted at the source) form the basis of almost every production call. Over SSH, rsync also transports the data encrypted and authenticated, without needing a separate VPN tunnel. One important detail is the difference between source/ and source as a path: the trailing slash determines whether the contents of a directory or the directory itself get copied into the destination, a detail that, if handled incorrectly, results in doubly nested directory structures.
#!/usr/bin/env bash
set -euo pipefail
# Sync application uploads to a remote backup host over SSH
# Trailing slash on source: copy contents, not the directory itself
rsync -avz --delete \
--exclude='cache/' \
--exclude='*.tmp' \
-e "ssh -i /root/.ssh/backup_ed25519 -p 2222" \
/var/www/app/pub/media/ \
backup@backup01.mironsoft.de:/srv/backups/app-media/
# Dry-run first to preview what would change, without touching anything
rsync -avz --delete --dry-run \
/var/www/app/pub/media/ backup@backup01.mironsoft.de:/srv/backups/app-media/
# Bandwidth-limited nightly sync (2 MB/s) to avoid saturating uplink
rsync -avz --bwlimit=2000 --delete \
/var/lib/mysql-backup/ backup@backup01.mironsoft.de:/srv/backups/db/
3. rsync with Hardlinks: Snapshot-Like History Without a Snapshot Tool
A frequently overlooked rsync feature is --link-dest, which lets you build a daily version history without storing a full copy for every single day. For unchanged files, rsync points a hardlink to the version in the previous backup directory instead of writing the file again. Only files that actually changed consume additional disk space. The result looks, for every day, like a full, independent copy, yet it only uses the disk space of the actual changes.
This pattern, often called "rsync-based snapshots," was the standard way to build space-efficient version histories long before Btrfs or ZFS were widely available, and it is still used as the core principle behind tools like rsnapshot and Borg today. The decisive advantage over a simple daily tar dump: you can jump back to any given day at any time without having to restore incremental archives in the correct order, because every daily directory is fully browsable on its own.
#!/usr/bin/env bash
# daily-snapshot.sh - hardlink-based daily backup history
set -euo pipefail
readonly BACKUP_ROOT="/srv/backups/app"
readonly TODAY="$(date +%Y-%m-%d)"
readonly LATEST_LINK="${BACKUP_ROOT}/latest"
mkdir -p "${BACKUP_ROOT}/${TODAY}"
# --link-dest points to yesterday's snapshot; unchanged files become hardlinks
rsync -a --delete \
--link-dest="${LATEST_LINK}" \
/var/www/app/ \
"${BACKUP_ROOT}/${TODAY}/"
# Update the "latest" pointer for the next run's --link-dest
rm -f "${LATEST_LINK}"
ln -s "${BACKUP_ROOT}/${TODAY}" "${LATEST_LINK}"
# Disk usage stays low: only changed files consume real space
du -sh "${BACKUP_ROOT}"/*/
4. tar: Portable Archives for Long-Term Archiving
While rsync keeps file trees in sync, tar produces a single portable archive that can be transported, compressed, and kept long-term independently of the target system. For compliance requirements or monthly full archives, a tar archive is often the more practical form, because a single object moves into an object storage system like S3 or onto a tape archive far more easily than thousands of individual files.
The combination tar czf with gzip compression is the standard, though zstd via --use-compress-program=zstd compresses noticeably faster on modern systems while delivering similar or better compression ratios, especially with multiple CPU cores using -T0. For incremental tar archives there is --listed-incremental, which maintains a snapshot file and, on every run, includes only the files that changed since the last archive, saving considerable time for very large datasets that rarely change in full.
#!/usr/bin/env bash
set -euo pipefail
readonly DATE_TAG="$(date +%Y%m%d)"
readonly ARCHIVE_DIR="/srv/backups/archives"
readonly SNAR_FILE="${ARCHIVE_DIR}/app.snar"
mkdir -p "${ARCHIVE_DIR}"
# Full monthly archive with zstd compression (faster than gzip, multi-core)
tar --use-compress-program="zstd -T0 -19" \
-cf "${ARCHIVE_DIR}/app-full-${DATE_TAG}.tar.zst" \
--exclude='./cache' --exclude='./var/log' \
-C /var/www/app .
# Incremental archive: only files changed since last run of this snapshot file
tar --listed-incremental="${SNAR_FILE}" \
-czf "${ARCHIVE_DIR}/app-incr-${DATE_TAG}.tar.gz" \
-C /var/www/app .
# Verify archive integrity without extracting
tar -tzf "${ARCHIVE_DIR}/app-full-${DATE_TAG}.tar.zst" > /dev/null && echo "OK"
# Extract a single file from a large archive without unpacking everything
tar -xzf "${ARCHIVE_DIR}/app-full-${DATE_TAG}.tar.zst" ./app/etc/env.php
5. LVM Snapshots: Consistent Backups Without Downtime
Both rsync and tar share a common problem: if the backup run takes several minutes while the application keeps writing, an inconsistent state ends up in the backup, one where some files were captured before, and others after, a related change. For a database, that can mean a corrupt or unrestorable backup. LVM snapshots solve this problem at the block level: lvcreate --snapshot freezes the state of a logical volume in milliseconds by enabling copy-on-write for all subsequent writes.
The actual dataset remains writable for the application without interruption, while the snapshot delivers an immutable, consistent view of the state at the moment it was created. This snapshot is mounted, backed up with rsync or tar, and then removed again. Important: an LVM snapshot is not a backup in itself, only a consistent point in time from which a backup is taken. If the snapshot is left in place permanently, it grows with every change to the original and, once the copy-on-write space fills up, can put the entire volume group at risk.
#!/usr/bin/env bash
# lvm-snapshot-backup.sh - consistent backup via LVM snapshot, near-zero downtime
set -euo pipefail
readonly VG="vg_data"
readonly LV="lv_mysql"
readonly SNAP_NAME="mysql_backup_snap"
readonly MOUNT_POINT="/mnt/backup-snap"
cleanup() {
mountpoint -q "$MOUNT_POINT" && umount "$MOUNT_POINT"
lvs "/dev/${VG}/${SNAP_NAME}" &>/dev/null && lvremove -f "/dev/${VG}/${SNAP_NAME}"
}
trap cleanup EXIT
# Flush MySQL to disk and briefly lock tables for a consistent snapshot point
mysql -e "FLUSH TABLES WITH READ LOCK; SELECT SLEEP(1);" &
sleep 0.5
# Create a 5 GB copy-on-write snapshot volume
lvcreate --size 5G --snapshot --name "$SNAP_NAME" "/dev/${VG}/${LV}"
mkdir -p "$MOUNT_POINT"
mount -o ro "/dev/${VG}/${SNAP_NAME}" "$MOUNT_POINT"
# Original volume is writable again as soon as the snapshot exists
rsync -a "$MOUNT_POINT/" backup@backup01.mironsoft.de:/srv/backups/mysql-snap/
echo "[OK] Snapshot backup completed, cleanup runs via trap"
6. Btrfs and ZFS Snapshots as an Alternative
Where LVM works at the block level, Btrfs and ZFS offer native snapshot functionality directly in the filesystem, which simplifies handling in many cases. btrfs subvolume snapshot -r /data /data-snapshots/2026-07-12 creates a read-only, consistent state of a subvolume in a fraction of a second, without separate snapshot management like LVM requires. Because Btrfs and ZFS snapshots use copy-on-write at the filesystem level rather than the block level, they are usually more space-efficient with many small changes and can be browsed directly under a path without needing to be mounted first.
ZFS goes a step further with zfs send and zfs receive, which let you replicate snapshots incrementally and efficiently to a remote system, including all metadata such as compression and deduplication. For systems that already run Btrfs or ZFS as the root filesystem, native snapshots are usually the more pragmatic choice over LVM snapshots, because there is no additional copy-on-write space to size manually, and snapshot management is part of the normal filesystem tooling.
#!/usr/bin/env bash
set -euo pipefail
# Btrfs: create a read-only snapshot of a subvolume
btrfs subvolume snapshot -r /data "/data-snapshots/$(date +%Y-%m-%d)"
# List existing snapshots with creation time
btrfs subvolume list -s /data
# ZFS: create a snapshot and replicate it incrementally to a remote host
zfs snapshot tank/app@$(date +%Y-%m-%d)
zfs send -i tank/app@yesterday tank/app@$(date +%Y-%m-%d) | \
ssh backup01.mironsoft.de zfs receive backup-pool/app
# Prune snapshots older than 30 days (btrfs example)
find /data-snapshots -maxdepth 1 -mtime +30 -exec btrfs subvolume delete {} \;
7. Applying the 3-2-1 Rule in Practice Across a Server Fleet
The 3-2-1 rule states: three copies of the data, on two different types of storage media, with one copy kept at a geographically separate location. In practice, on a small server fleet, that means concretely: copy one is the production database itself, copy two is a daily rsync backup to a dedicated backup server in the same data center, and copy three is a weekly encrypted tar archive uploaded to an object storage system at a different provider or in a different region.
It is essential that the backup server has no write access to the production systems, and instead reaches out to the sources itself via SSH under a pull model. That way, a compromised production system cannot simultaneously tamper with or delete the backups, an attack pattern that is regularly seen in ransomware incidents. For the offsite copy, object storage services with immutability options are a good fit, where uploaded objects cannot be deleted for a defined period, even with admin rights, providing additional protection against compromised credentials.
# backup-policy.yaml - documented 3-2-1 policy for the server fleet
# Copy 1: production data itself (not a backup, the source)
copy_1:
location: production database and application servers
medium: local NVMe storage
# Copy 2: on-site, different medium, pull-based via SSH
copy_2:
location: dedicated backup host in the same datacenter
medium: rsync daily snapshot with --link-dest history
retention: 14 daily snapshots
access: pull-only, backup host has read-only SSH key on sources
# Copy 3: off-site, different provider and region
copy_3:
location: object storage, different provider, different region
medium: weekly encrypted tar.zst archive
retention: 12 weekly archives, then monthly for 12 months
immutability: object lock enabled for 30 days
restore_test:
frequency: monthly
scope: full restore of one random backup into an isolated environment
8. Restore Tests: A Backup Is Only Verified Once It Has Been Restored
A backup that has never been restored is not a safety net, it is an unproven assumption. In practice, restores fail surprisingly often on details that a plain backup job never reveals: a forgotten file in the exclude list, an archive that was written but never checked for completeness, or a database dump file that is incomplete because a process was aborted. These failures only surface in a real emergency, when an actual restore is needed, unless you test it regularly beforehand.
A production restore test belongs on the calendar every month, not just after major changes to the backup configuration. The test should run in an isolated environment that does not affect production, such as a separate test server or a temporary container. The key metrics here are the actual restore duration (recovery time objective) and the maximum data loss since the last backup (recovery point objective); both should be documented and checked against real business requirements, not just assumed in theory.
#!/usr/bin/env bash
# monthly-restore-test.sh - verify a backup is actually usable
set -euo pipefail
readonly TEST_DIR="/tmp/restore-test-$(date +%s)"
readonly ARCHIVE="/srv/backups/archives/app-full-$(date +%Y%m%d).tar.zst"
mkdir -p "$TEST_DIR"
echo "[1/4] Extracting archive into isolated test directory..."
tar --use-compress-program="zstd -d" -xf "$ARCHIVE" -C "$TEST_DIR"
echo "[2/4] Restoring database dump into a throwaway database..."
mysql -e "CREATE DATABASE IF NOT EXISTS restore_test;"
zcat /srv/backups/db/latest.sql.gz | mysql restore_test
echo "[3/4] Validating row counts against expected baseline..."
mysql restore_test -e "SELECT COUNT(*) FROM sales_order;" | tail -1
echo "[4/4] Cleaning up test environment..."
mysql -e "DROP DATABASE restore_test;"
rm -rf "$TEST_DIR"
echo "[OK] Restore test passed, log result and RTO/RPO in the runbook"
9. Backup Tools Compared Head to Head
The tools presented here solve different sub-problems and are not mutually exclusive. The following table compares which tool is actually suited for which task, and where typical misuse tends to happen.
| Task | Wrong Choice | Right Tool | Reasoning |
|---|---|---|---|
| Daily delta synchronization | Full tar archive every day | rsync with --link-dest | Only changes consume storage |
| Consistent DB backup under load | rsync directly against live data files | LVM/Btrfs snapshot before backing up | Prevents inconsistent intermediate states |
| Long-term archiving / compliance | Thousands of individual files via rsync | Compressed tar archive | One portable object, easy to move |
| Offsite replication of large datasets | Full re-upload every time | zfs send/receive or incremental rsync | Only the delta is transferred |
| Backup verification | Never-tested restore | Monthly restore test in isolation | Surfaces missing files and RTO/RPO gaps |
The table makes it clear that none of these tools is universally right. Running rsync against a live database without a prior snapshot risks silent inconsistencies. Relying only on full tar archives wastes both storage and time. The most robust strategy combines all three classes of tools along the 3-2-1 rule and closes the loop with regular restore tests.
Mironsoft
Backup concepts, restore tests, and server automation
Backups that are actually restorable when it counts?
We design backup strategies based on the 3-2-1 rule, set up rsync-, tar-, and snapshot-based backups, and establish regular restore tests, so that data loss never becomes an unpleasant surprise.
Backup Audit
Review existing backup jobs for consistency, coverage, and 3-2-1 compliance
Snapshot Integration
Set up LVM or Btrfs snapshots for consistent backups with zero downtime
Restore Runbooks
Documented, tested recovery processes with clear RTO/RPO targets
10. Summary
A robust Linux backup strategy is not built from a single tool, but from a deliberate combination of several. rsync efficiently synchronizes file trees and, with --link-dest, enables a space-efficient daily history. tar produces portable, easily archivable full archives for long-term storage and compliance. LVM, Btrfs, or ZFS snapshots solve the consistency problem by freezing a dataset in milliseconds without interrupting the application. The 3-2-1 rule provides the organizational framework: three copies, two media types, one copy kept geographically separate.
The most important point remains the one most often skipped: a backup that has never been restored is not verified. Monthly restore tests in an isolated environment surface missing files, corrupt archives, and unrealistic RTO/RPO assumptions before real data loss occurs. Anyone who consistently combines these four building blocks, efficient synchronization, consistent snapshots, geographically distributed copies, and regular restore tests, ends up with a backup strategy that genuinely holds up when it matters.
Linux Backup Strategies: The Essentials at a Glance
rsync for Efficiency
Delta transfer sends only what changed. --link-dest creates a space-efficient daily history via hardlinks.
tar for Portability
One archive object for long-term storage, compressed noticeably faster with zstd than with classic gzip.
Snapshots for Consistency
LVM, Btrfs, or ZFS freeze the state in milliseconds, making backups possible without application downtime.
3-2-1 & Restore Test
Three copies, two media types, one offsite copy. A monthly restore test verifies what otherwise stays a mere assumption.