DEV Community

overnight.host
overnight.host

Posted on

How to set up automated, off-site backups for your VPS with restic

A backup that lives on the same machine as your data isn't a backup — it's a copy waiting to disappear with the disk. If you run anything on a VPS that you'd be unhappy to lose (a database, a game world, a self-hosted app), you want backups that run on a schedule, leave the server, and can actually be restored. Here's a clean, honest setup using restic, which is free, open-source, encrypted by default, and deduplicates so repeated backups stay small.

1. Install restic

On Debian/Ubuntu:

sudo apt update && sudo apt install -y restic
Enter fullscreen mode Exit fullscreen mode

On AlmaLinux/Rocky:

sudo dnf install -y epel-release && sudo dnf install -y restic
Enter fullscreen mode Exit fullscreen mode

2. Pick an off-site destination

The whole point is "not on this server." Good options: an S3-compatible object store, a second VPS in another region, or an SFTP target. restic encrypts everything client-side before it leaves the box, so the destination never sees your plaintext.

export RESTIC_REPOSITORY="sftp:backup@backup-host:/srv/restic/myvps"
export RESTIC_PASSWORD="a-long-random-passphrase-you-store-safely"
restic init
Enter fullscreen mode Exit fullscreen mode

Keep that passphrase somewhere safe and separate. Without it, the repository is unrecoverable — which is exactly what protects you if the backup host is ever compromised.

3. Back up the things that matter

Don't back up the whole root filesystem — you'll just restore the OS. Back up your data:

restic backup /var/lib/mysql /var/www /etc /home --exclude-caches
Enter fullscreen mode Exit fullscreen mode

For databases, dump first so you get a consistent snapshot rather than copying live files:

mysqldump --single-transaction --all-databases > /root/db-$(date +%F).sql
restic backup /root/db-*.sql
Enter fullscreen mode Exit fullscreen mode

4. Automate it with a timer

Drop this into /usr/local/sbin/backup.sh, make it executable, and let cron run it nightly:

#!/bin/bash
set -euo pipefail
export RESTIC_REPOSITORY="sftp:backup@backup-host:/srv/restic/myvps"
export RESTIC_PASSWORD_FILE="/root/.restic-pass"
mysqldump --single-transaction --all-databases > /root/db.sql
restic backup /var/www /etc /root/db.sql --exclude-caches
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
Enter fullscreen mode Exit fullscreen mode
chmod 700 /usr/local/sbin/backup.sh
echo "15 3 * * * root /usr/local/sbin/backup.sh >> /var/log/backup.log 2>&1" | sudo tee /etc/cron.d/restic-backup
Enter fullscreen mode Exit fullscreen mode

The forget --prune line is the part people skip — it keeps a sensible retention window so the repository doesn't grow forever.

5. Test the restore (this is the real step)

An untested backup is a hope, not a plan. Once a month, prove it works:

restic snapshots
restic restore latest --target /tmp/restore-test --include /etc
Enter fullscreen mode Exit fullscreen mode

If the files come back, you have a backup. If they don't, you found out on a Tuesday instead of during a disaster.

A note on where this runs

restic is region-agnostic — it works the same whether your VPS is in the EU or the US, and the encrypted-before-it-leaves design means you stay in control of your data wherever the backup target lives. If you're spinning up a box for this, overnight.host runs KVM VPS with full root and honest specs (SSD, NAT IPv4 disclosed up front), hosted in your region — so you can point your off-site backups at a second region without overthinking it.

Top comments (0)