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 -ifirst. - 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-dumpwithout a password. If you get an "Access denied" error, create/root/.my.cnfwith the lines[client],user=rootandpassword=YOUR_DB_PASSWORD, then runchmod 600 /root/.my.cnf. pg_dumpalldumps every PostgreSQL database. To dump just one, userunuser -u postgres -- pg_dump -Fc DBNAME > /var/backups/db/DBNAME.dumpinstead.- If a database runs in a Docker container, dump it with
docker execand 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 -aline), theRESTIC_REPOSITORYaddress is wrong, or you haven't runrestic inityet. - "wrong password or no key found": the password in
/etc/restic/passwordisn'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
- Set up SSH keys to log in to your VPS securely
- Keep commands running after you disconnect with screen and tmux
- Install Docker Engine and Docker Compose on your VPS
- Reinstall your VPS with a different operating system
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.












