A Backup Plan for Every Ubuntu VPS
Hardware fails, ransomware strikes, and the rm -rf finger slip is inevitable. An automated, encrypted, off-site backup system turns those events from disasters into minor inconveniences. This guide sets up reliable daily backups on Ubuntu 22.04 LTS and Ubuntu 24.04 LTS using restic, with notes on rsnapshot and database dumps.
What to Back Up
A typical production server needs three categories of data protected:
- Application data -
/var/www,/opt/app, user uploads, configuration in/etc. - Databases - MySQL/MariaDB, PostgreSQL, Redis persistence files.
- Secrets and keys - SSH host keys, TLS certificates, GPG keys - back these up encrypted separately.
Do not back up /proc, /sys, /dev, or /tmp. Also exclude /var/cache and container layers.
The 3-2-1 Rule
Three copies of your data, on two different media, with one copy off-site. For a VPS this usually means: primary disk, local snapshots, and encrypted remote object storage (S3, B2, or a second VPS).
Install Restic
Restic is a modern, deduplicating, encrypted backup tool written in Go. Install the latest version:
apt update
apt install -y restic
restic version
On Ubuntu 22.04, the apt package may lag; update with restic self-update once installed.
Initialize a Repository
Pick a remote backend. For S3-compatible storage:
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export RESTIC_REPOSITORY="s3:https://s3.example.com/backup-bucket"
export RESTIC_PASSWORD_FILE="/root/.restic-password"
echo "a-strong-repository-password" > /root/.restic-password
chmod 600 /root/.restic-password
restic init
The repository password encrypts everything client-side. Store it somewhere outside the server - if the VPS dies you will need it to restore.
Run a First Backup
restic backup /etc /home /var/www /opt/app \
--exclude '/var/www/*/cache' \
--exclude-caches \
--tag daily
Verify the snapshot list:
restic snapshots
restic check
check validates repository integrity. Run it weekly.
Automate with Cron
Create /usr/local/bin/backup.sh:
#!/bin/bash
set -euo pipefail
export RESTIC_REPOSITORY="s3:https://s3.example.com/backup-bucket"
export RESTIC_PASSWORD_FILE="/root/.restic-password"
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
restic backup /etc /home /var/www /opt/app \
--exclude-caches --tag daily
restic forget --prune \
--keep-daily 7 --keep-weekly 4 --keep-monthly 12
curl -fsS --retry 3 https://hc-ping.com/your-uuid > /dev/null
Make it executable and schedule via cron:
chmod 700 /usr/local/bin/backup.sh
echo "15 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1" \
> /etc/cron.d/restic-backup
For a deeper look at scheduling patterns, see our cron jobs guide.
Database Dumps
Never back up live database files directly - they may be mid-write. Dump first, then include the dump in the restic run:
# MySQL / MariaDB
mysqldump --single-transaction --quick --all-databases \
| gzip > /var/backups/mysql/$(date +%F).sql.gz
# PostgreSQL
sudo -u postgres pg_dumpall | gzip > /var/backups/postgres/$(date +%F).sql.gz
Run these before restic backup in the same script, and include /var/backups in the backup paths.
Snapshot Retention
Restic's forget --prune policy removes old snapshots based on a retention plan:
| Flag | Meaning |
|---|---|
--keep-daily 7 | Keep last 7 daily snapshots |
--keep-weekly 4 | Keep last 4 weekly snapshots |
--keep-monthly 12 | Keep last 12 monthly snapshots |
--keep-yearly 3 | Keep last 3 yearly snapshots |
Test the Restore
Backups that are never restored are not backups. Schedule quarterly fire drills:
mkdir /tmp/restore-test
restic restore latest --target /tmp/restore-test --include /etc/nginx
ls /tmp/restore-test/etc/nginx
rm -rf /tmp/restore-test
Alternative: rsnapshot for Local Snapshots
For simple local-disk snapshots using hardlinks:
apt install -y rsnapshot
# Edit /etc/rsnapshot.conf (use tabs, not spaces)
rsnapshot configtest
rsnapshot daily
rsnapshot is ideal for on-VPS backups you can restore quickly - pair it with restic for off-site copies.
Monitoring Backup Health
A silent broken backup is the worst kind. Combine these three signals:
- Heartbeat ping from the cron script (shown above).
- Alert on missing restic snapshots (
restic snapshots --json | jq). - Weekly
restic check --read-data-subset=5%verifies random data chunks.
Running production Ubuntu servers? MassiveGRID's Cloud VPS includes NVMe storage and integrates cleanly with our managed Backup Services for encrypted off-site retention. For enterprise disaster recovery with RPO/RTO guarantees, contact our team.
Published by MassiveGRID - cloud hosting with managed backup and disaster recovery across four global regions.