If your VPS is reinstalled, hacked or has a disk problem, or you delete something by mistake, a backup is the only way to get your data back. Our Cloud VPS plans don't include backups unless you add the VPS backups add-on, so it's up to you to keep copies of anything important. This guide sets up restic, a free, open-source backup tool, to make encrypted, versioned backups of your VPS to storage somewhere else, every night.

It works on every operating system we offer: Ubuntu 22.04, 24.04 and 26.04, Debian 12 and 13, AlmaLinux 8, 9 and 10, and Rocky Linux 9 and 10.

Our VPS backups add-on

You can add backups to your VPS with Upgrade/Downgrade in the left menu of your VPS's management page (Services → My Services → Manage). Once it's added, click Login To Panel on the same page to see and restore your backups. No Cloud VPS plan includes backups by default.

A restic backup works well alongside the add-on, or on its own. It keeps a copy of your files with a storage provider you choose, keeps weeks or months of history, and lets you restore a single file or folder.

Before you start

  • SSH access as root or as a user with sudo rights. Everything in this guide runs as root, so if you log in as another user, run sudo -i first.
  • Somewhere to store your backups that isn't this VPS. Either S3-compatible object storage, such as Backblaze B2, Wasabi, Cloudflare R2 or Amazon S3, with a bucket and an access key (key ID and secret key) that can read and write it, or another server you can reach over SSH (SFTP) with enough free space, ideally in a different location.
  • A password manager or other safe place, away from this VPS, to keep your backup password and storage keys.

Step 1: Install restic

Ubuntu/Debian

apt update
apt install -y restic
restic version

AlmaLinux/Rocky (restic comes from the EPEL repository)

dnf install -y epel-release
dnf install -y restic
restic version

Ubuntu 22.04: the packaged version is very old (0.12), so install the official build instead of using apt install restic. Find the latest version number on the restic releases page (0.19.1 when this guide was written) and run:

apt install -y curl bzip2
VER=0.19.1
curl -fL -o restic.bz2 https://github.com/restic/restic/releases/download/v${VER}/restic_${VER}_linux_amd64.bz2
bunzip2 restic.bz2
install -m 755 restic /usr/local/bin/restic
rm restic
restic version

Step 2: Create your backup password

install -d -m 700 /etc/restic
openssl rand -base64 32 > /etc/restic/password
chmod 600 /etc/restic/password
cat /etc/restic/password

Save this password in your password manager now. restic encrypts your backups with it. If you lose it, your backups can't be opened by anyone, including us. Keeping it only on the VPS isn't enough: if you lose the VPS, you lose the password too.

Step 3: Add your storage details

Create the settings file:

nano /etc/restic/restic.env

Option A: S3-compatible storage

RESTIC_REPOSITORY=s3:https://S3_ENDPOINT/BUCKET_NAME/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
AWS_ACCESS_KEY_ID=YOUR_KEY_ID
AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY

Replace S3_ENDPOINT with the S3 endpoint your provider shows in its dashboard, BUCKET_NAME with your bucket, and vps1 with a name for this server. Keep the AWS_ names even if your provider isn't Amazon. If your provider tells you to set a region, add a line such as AWS_DEFAULT_REGION=us-east-1 with their region. For Backblaze B2, use its S3-compatible endpoint and keys, which restic recommends over B2's own connection method.

Option B: another server over SFTP

RESTIC_REPOSITORY=sftp:backupuser@backup.example.co.nz:/srv/restic/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic

Make sure backupuser can write to /srv/restic on the other server. restic must log in without a password, so create an SSH key for root (skip the first command if root already has one), copy it across, then log in once to accept the server's host key:

ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519
ssh-copy-id backupuser@backup.example.co.nz
ssh backupuser@backup.example.co.nz exit

If the other server uses a different SSH port, write the repository like this: sftp://backupuser@backup.example.co.nz:2222//srv/restic/vps1

Save the file, then make it readable only by root:

chmod 600 /etc/restic/restic.env

Whenever you run restic by hand, load the settings into your session first:

set -a; . /etc/restic/restic.env; set +a

Step 4: Create the repository

This sets up the encrypted backup store at your storage location:

restic init

Step 5: Decide what to back up

Back up: /etc (your settings), /home, /root, /var/www (websites), /opt and /srv (apps and their data), Docker volumes in /var/lib/docker/volumes, and dumps of your databases (Step 6 makes these).

Leave out: /proc, /sys, /dev, /run and /tmp; the operating system itself, which you can reinstall; the rest of /var/lib/docker, as images can be downloaded again; caches; your swap file; and live database folders such as /var/lib/mysql and /var/lib/postgresql. A copy of a database's files taken while it's running may not restore, so back up a dump instead.

Create a list of things to skip:

nano /etc/restic/excludes.txt
/home/*/.cache
/root/.cache
node_modules

A pattern without a leading / matches anywhere, so node_modules skips every folder with that name. You can reinstall them with npm install. Remove that line if you'd rather back them up.

Step 6: Create the backup script

The script dumps your databases to /var/backups/db, backs everything up, removes old snapshots and checks the backup. Create it:

nano /usr/local/sbin/restic-backup.sh

Paste in the following. Delete the database lines you don't need, for example the PostgreSQL line if you only use MariaDB.

#!/bin/bash
set -euo pipefail
cd /
set -a; . /etc/restic/restic.env; set +a

# 1. Dump databases
mkdir -p /var/backups/db
chmod 700 /var/backups/db
# MariaDB 10.5 or newer. For MySQL or older MariaDB, use mysqldump instead of mariadb-dump.
mariadb-dump --all-databases --single-transaction --routines --events | gzip > /var/backups/db/mysql.sql.gz
# PostgreSQL
runuser -u postgres -- pg_dumpall | gzip > /var/backups/db/postgresql.sql.gz

# 2. Back up these folders (any that don't exist are skipped)
FOLDERS=(/etc /home /root /var/www /opt /srv /var/lib/docker/volumes /var/backups/db)
EXISTING=()
for f in "${FOLDERS[@]}"; do
  if [ -e "$f" ]; then EXISTING+=("$f"); fi
done
restic backup --exclude-caches --exclude-file /etc/restic/excludes.txt "${EXISTING[@]}"

# 3. Keep 7 daily, 4 weekly and 6 monthly snapshots, and delete the rest
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

# 4. Check the backup, reading a random 5% of the stored data
restic check --read-data-subset=5%

The last line downloads a little of your backup each night to make sure it can be read. If your storage provider charges for downloads, you can lower the percentage.

Save the script and make it executable:

chmod 700 /usr/local/sbin/restic-backup.sh

A few notes on databases:

  • On Ubuntu and Debian, root can usually run mariadb-dump without a password. If you get an "Access denied" error, create /root/.my.cnf with the lines [client], user=root and password=YOUR_DB_PASSWORD, then run chmod 600 /root/.my.cnf.
  • pg_dumpall dumps every PostgreSQL database. To dump just one, use runuser -u postgres -- pg_dump -Fc DBNAME > /var/backups/db/DBNAME.dump instead.
  • If a database runs in a Docker container, dump it with docker exec and the database's own dump command, rather than relying on the copy of its volume.

Step 7: Run your first backup

/usr/local/sbin/restic-backup.sh

The first backup uploads everything, so it can take a while. Later backups only upload what's changed, so they're much quicker. If you're worried about your SSH session dropping, run it inside screen or tmux. When it's finished, list your snapshots:

set -a; . /etc/restic/restic.env; set +a
restic snapshots

Step 8: Run it every night

A systemd timer is the best way to schedule it. Create the service:

nano /etc/systemd/system/restic-backup.service
[Unit]
Description=restic backup
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/restic-backup.sh
Nice=10
IOSchedulingClass=idle

Then the timer:

nano /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run restic backup every night

[Timer]
OnCalendar=*-*-* 02:30:00
RandomizedDelaySec=30m
Persistent=true

[Install]
WantedBy=timers.target

Turn it on and check when it will next run:

systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer

The time uses your server's time zone, which you can check with timedatectl. To see how the last backup went, run journalctl -u restic-backup.service.

Prefer cron? Use this instead of the timer, not as well. Create /etc/cron.d/restic-backup containing:

30 2 * * * root /usr/local/sbin/restic-backup.sh >> /var/log/restic-backup.log 2>&1

Step 9: Test a restore

Check you can actually get your files back, now and every few months. This restores your SSH settings into a test folder:

set -a; . /etc/restic/restic.env; set +a
restic restore latest --target /root/restore-test --include /etc/ssh
ls -la /root/restore-test/etc/ssh

To get a file back, restore it to a test folder like this, then copy it into place. Don't restore with --target / unless you really mean to overwrite your live files. Delete the test folder when you've finished: rm -rf /root/restore-test

You can also browse your backups like normal folders. In one SSH session, run:

mkdir -p /mnt/restic
restic mount /mnt/restic

In a second session, look in /mnt/restic/snapshots/latest/ and copy out what you need. Press Ctrl+C in the first session to unmount. This needs FUSE support. If it doesn't work, use restic restore instead.

If you lose the whole VPS, install restic on the new server, recreate /etc/restic/password and /etc/restic/restic.env from your password manager, then use restic snapshots and restic restore as above. Restoring a database dump replaces the data already in that database, so take care.

What about rclone?

rclone copies and syncs files to almost any cloud storage service, and it's handy for keeping a plain copy of a folder in the cloud. A sync isn't a backup on its own, though: if files are deleted or damaged on your server, the next sync copies that too, and there's no history to go back to. Use it alongside restic, not instead of it.

Keeping it up to date

If you installed restic from your operating system's packages, it updates with the rest of your system. If you installed the official build, update it with restic self-update.

Troubleshooting

  • "Is there a repository at the following location?": you haven't loaded the settings (run the set -a line), the RESTIC_REPOSITORY address is wrong, or you haven't run restic init yet.
  • "wrong password or no key found": the password in /etc/restic/password isn't the one the repository was created with.
  • "repository is already locked": another restic command is running, perhaps the nightly backup. Wait for it to finish. If you're sure nothing else is running, run restic unlock.
  • Access denied or 403 errors with S3 storage: check your key can read and write the bucket, and that the endpoint, bucket name and region are right.
  • The backup service shows as failed: run journalctl -u restic-backup.service. "Access denied" or "command not found" on a database line means the dump failed, see Step 6. Exit code 3 means restic couldn't read some files, but the rest of the snapshot was saved.

Related guides

Need help?

Our Cloud VPS plans are self-managed, so you're responsible for installing, securing and maintaining the software on your server. If something on our side isn't working, such as the network, or your VPS won't boot, open a support ticket. New to your VPS? Start with our Cloud VPS Getting Started Guide. For more on restic itself, see the restic documentation.

Was this answer helpful? 0 Users Found This Useful (0 Votes)