Skip to main content

Backup Server Sync Automation Strategy

If you operate two servers (production + backup server), syncing backups between them is a core automation workflow. The safest pattern is to generate artifacts on the primary, verify them, then copy them to the backup server with logs and integrity checks.

Quick Summary
  • Primary creates artifacts (files + DB) and verifies integrity.
  • Sync artifacts to the backup server using rsync or rclone.
  • Use locks to prevent overlap.
  • Verify remote copy (checksums or listings).
  • Alert on failures.

Push vs pull

Two safe models:

ModelHow it worksWhen to use
Pushprimary connects to backup server and copies artifactssimplest; single source of truth
Pullbackup server connects to primary and pulls artifactsreduces risk if primary is compromised

Artifact boundaries

Sync artifacts, not live directories.

Good artifacts:

  • wp-files-YYYY-MM-DD.tar.zst
  • wp-db-YYYY-MM-DD.sql.zst
  • backup logs

Avoid syncing:

  • live /var/www/html directly over the network
  • database directories (/var/lib/mysql)

Push example (rsync over SSH)

push-backups-to-backup-server.sh
rsync -az \
-e 'ssh -i ~/.ssh/wp-backup -o StrictHostKeyChecking=accept-new' \
--info=stats2,progress2 \
/backups/ \
backup@backup-host:/srv/wp-backups/site-a/
warning

Avoid --delete until you are fully confident. Deletion on the backup server can propagate local mistakes.

Verification options

Option A: listing verification

verify-backup-server-listing.sh
ssh -i ~/.ssh/wp-backup backup@backup-host 'ls -lah /srv/wp-backups/site-a | sed -n "1,80p"'

Option B: checksum verification

checksum-verify-remote-copy.sh
cd /backups
sha256sum wp-files-* wp-db-* > /tmp/backups.sha256

scp -i ~/.ssh/wp-backup /tmp/backups.sha256 backup@backup-host:/tmp/backups.sha256
ssh -i ~/.ssh/wp-backup backup@backup-host 'cd /srv/wp-backups/site-a && sha256sum -c /tmp/backups.sha256'

If backups run on a schedule, prevent overlapping transfers.

sync-with-flock.sh
flock -n /var/lock/backup-sync.lock \
rsync -az -e 'ssh -i ~/.ssh/wp-backup' /backups/ backup@backup-host:/srv/wp-backups/site-a/

Retry strategy

Network transfers fail. Build retries with backoff in the wrapper script.

retry-wrapper-example.sh
#!/usr/bin/env bash
set -euo pipefail

attempt=1
max=5

while true; do
if rsync -az -e 'ssh -i ~/.ssh/wp-backup' /backups/ backup@backup-host:/srv/wp-backups/site-a/; then
exit 0
fi

if [ "$attempt" -ge "$max" ]; then
exit 1
fi

sleep "$((attempt * 30))"
attempt="$((attempt + 1))"
done

Monitoring hooks

Treat "sync success" as a signal you can alert on.

  • systemd OnFailure
  • cron mail
  • webhook ping

See:

  • opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/alert-on-failed-backup-jobs.mdx

Next steps

  • Offsite redundancy design: opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/offsite--local-redundancy.mdx