Datacenter
VPS & Dedicated

VPS Backup Automation: rsync vs Cloud

Disclosure: This post contains affiliate links; we may earn a commission at no extra cost to you.

VPS Backup Automation: rsync vs Cloud

rsync and cloud object storage solve different parts of VPS backup. Rsync efficiently copies a filesystem to another machine and is excellent for fast incremental synchronization. Amazon S3, Backblaze B2, Wasabi, and Cloudflare R2 provide durable object storage with versioning, lifecycle rules, and geographic separation. For a production WordPress VPS, the best design usually uses both ideas: create an application-consistent backup, encrypt and upload it to object storage, and optionally keep an rsync replica for fast recovery.

Mirroring is not the same as backup. If ransomware encrypts files or an administrator deletes uploads, a plain scheduled rsync can faithfully copy the damage and remove the good destination files. A backup needs history, retention, integrity checks, and a tested restore procedure.

Comparison

Approach Best at Main weakness Typical tools
rsync to another server Fast file replication and local restores Destination must be secured and versioned separately rsync, SSH, hard-link snapshots
Object storage Off-site durability, versioning, lifecycle retention Restore and egress can be slower or costlier restic, rclone, Borg adapters, provider CLI
Provider snapshot Rapid whole-server rollback Same-provider and account dependency DigitalOcean, Hetzner, Vultr, AWS snapshots
Managed backup service Low administrative overhead Recurring cost and vendor dependency Jetpack VaultPress, BlogVault, Acronis
[AFFILIATE CTA: Backblaze B2]

Backblaze B2 is a strong off-site target for encrypted VPS backups because it supports an S3-compatible API, versioning/lifecycle controls, and generally straightforward storage pricing. Check current storage, API, and download charges. B2 does not make a backup application-consistent or automatically test restores; pair it with restic or another backup tool.

Why raw rsync can fail

Rsync compares file metadata and content, transferring changed blocks or files. A basic command over SSH might look like this:

rsync -aHAX --numeric-ids --delete \
  /var/www/ backup@backup-host:/srv/backups/web-current/

Options preserve attributes, hard links, ACLs, and extended attributes; support varies by filesystem and permissions. --delete makes the destination match the source, which is useful for a replica and dangerous for a lone backup. A mistaken empty source path or compromised server can remove the destination copy. Test with --dry-run, use explicit paths, and never introduce deletion until versioned snapshots exist.

Rsyncing a live MySQL or MariaDB data directory is unsafe. Files can be captured at different points while writes occur, yielding an inconsistent database. Use mysqldump for smaller databases, MySQL Shell dump utilities where appropriate, or a physical hot-backup tool such as Percona XtraBackup for larger supported deployments. WordPress files and database should correspond closely in time.

An rsync destination reachable with a powerful key is exposed if the source VPS is compromised. Prefer a destination that pulls from the source with read-only access, or a narrowly restricted push account that cannot delete older snapshots. Server-side ZFS/Btrfs snapshots or hard-link rotations can preserve history independently of the source credentials.

Object storage with restic

Restic encrypts, deduplicates, versions, and verifies backups. It supports S3-compatible storage, Backblaze B2, Azure, Google Cloud Storage, and other backends. Unlike a raw sync, each snapshot references historical content while duplicate blocks are stored efficiently.

Install restic from the distribution or official release channel and verify the package/signature according to the project’s documentation. Create a dedicated bucket and credentials limited to that bucket. Initialize once:

export RESTIC_REPOSITORY="s3:s3.us-west-004.backblazeb2.com/example-vps-backups"
export AWS_ACCESS_KEY_ID="REDACTED"
export AWS_SECRET_ACCESS_KEY="REDACTED"
export RESTIC_PASSWORD_FILE="/root/.config/restic/password"
restic init

Do not paste real secrets into shell history, tickets, or source control. Environment variables can be visible to privileged processes; a root-readable systemd environment file or secret manager is preferable. The repository password is required for recovery. Store an offline copy separately from the VPS and bucket account.

Create a database dump and backup:

install -d -m 700 /var/backups/wordpress
mysqldump --single-transaction --quick --routines --triggers \
  --defaults-extra-file=/root/.config/mysql/backup.cnf \
  wordpress > /var/backups/wordpress/wordpress.sql

restic backup /etc /var/www /var/backups/wordpress \
  --exclude-caches --one-file-system

For very active databases, coordinate locking, binary logs, or physical backups with a database administrator. --single-transaction provides a consistent snapshot for transactional InnoDB tables but does not make non-transactional tables magically consistent. Avoid putting the database password on the command line.

After a successful backup, apply retention:

restic forget --keep-daily 14 --keep-weekly 8 \
  --keep-monthly 12 --prune

Pruning can be bandwidth- and resource-intensive. Schedule it less frequently than backups and monitor completion. Retention must reflect business needs, privacy obligations, and storage budget.

Object-storage safeguards

Enable bucket versioning where useful and consider object lock or immutability. Amazon S3 Object Lock, Backblaze B2 Object Lock, and comparable features can prevent deletion during a retention period. They also can lock in storage costs and complicate legitimate data-erasure requests. Test policy on a non-production bucket first.

Use separate cloud credentials and MFA on the storage account. A credential stored on the VPS should access only one bucket and should not be able to alter account security. Where the backup tool requires deletion for pruning, immutable retention can conflict with cleanup. One solution uses a limited writer for frequent backups and an independent retention design; another accepts that pruning occurs only after object locks expire.

Lifecycle policies can transition old S3 objects to colder tiers. Glacier-class storage lowers monthly cost but introduces retrieval delay and fees. A two-day archival retrieval is unacceptable for a four-hour RTO. Keep recent backups in immediately retrievable storage and archive older compliance copies.

Cloudflare R2 advertises no egress fees to the internet under its model, while requests and storage are billed. Wasabi uses a different pricing model that may include minimum storage duration. Amazon S3 has broad ecosystem integration but a complex cost structure. Backblaze B2 is often economical, but downloads and transactions still need review. Calculate with actual backup size, daily change rate, retention, request count, and quarterly restore tests.

Automate with systemd

Systemd timers provide logging, randomized delay, dependency control, and missed-run handling. Create a root-owned script such as /usr/local/sbin/backup-wordpress with mode 700. It should use set -euo pipefail, create the dump, run the backup, report status, and delete temporary plaintext dumps only after a confirmed upload. Avoid logging secrets.

A service can use hardening directives and an environment file readable only by root. A timer might run nightly with Persistent=true, causing a missed job to run after reboot. Do not copy an untested unit from the internet into production; path permissions and network dependencies differ.

Cron is acceptable for simple systems, but redirecting output to an unattended mailbox is not monitoring. Send success age, duration, bytes added, and failures to an external system such as Uptime Kuma, Healthchecks.io, Better Uptime, Datadog, or Prometheus/Alertmanager. The alert channel must not depend solely on the failed VPS.

Prevent overlapping jobs with flock or systemd’s service state. Add timeouts so a hung upload does not block every future run. Limit bandwidth if backup traffic competes with production requests.

Restore testing

List snapshots and periodically run integrity checks:

restic snapshots
restic check --read-data-subset=5%

Partial checks reduce routine bandwidth but do not replace occasional full verification. To test recovery, provision an isolated VPS, install compatible web and database software, restore to a temporary directory, import the database, update environment-specific settings, and test WordPress login, media, forms, cron, and checkout.

Document DNS, firewall rules, TLS, PHP extensions, service versions, scheduled jobs, and external APIs. Backing up /var/www alone will not reproduce an undocumented Nginx/PHP-FPM stack. Infrastructure-as-code using Ansible, Terraform, cloud-init, or another configuration tool can rebuild the operating environment while the backup restores mutable data.

Measure the test. Record time to acquire credentials, retrieve data, rebuild the server, switch DNS, and validate the application. If the RTO is four hours and the first rehearsal takes nine, change the design—perhaps by retaining a warm standby, recent provider snapshot, or closer regional copy.

A balanced production design

Use provider snapshots before risky upgrades for rapid rollback, but do not treat them as the only copy. Run nightly encrypted restic backups of system configuration, WordPress files, and a consistent database dump to object storage. Increase database frequency for active stores. Keep 14 daily, eight weekly, and 12 monthly points as a starting example, adjusted for policy.

Optionally rsync uploads and configuration to a second server for faster recovery, with destination-side snapshots that source credentials cannot erase. Monitor every job, run monthly sample restores and quarterly full disaster-recovery exercises, and rotate credentials when administrators leave.

Rsync is superb transport; cloud storage is durable destination infrastructure. Neither alone supplies consistency, history, encryption, monitoring, and recovery proof. The automation is complete only when a clean server can be restored within the promised time.