On a VPS, backing up your data is your responsibility: it is the other side of root access. BorgBackup is the reference tool for this on Linux. It encrypts data before it leaves the server, stores identical blocks only once, which makes daily backups very light, and lets you restore a single file in seconds.
1. The golden rule: a backup off the server
A backup stored on the same VPS as the data protects you neither from the server being deleted by mistake, nor from a break-in, nor from ransomware that encrypts the whole disk. Apply the 3-2-1 rule: three copies of the data, on two different media, one of them off site.
In practice, you need storage reachable over SSH somewhere other than the server being backed up: a second storage VPS, a server at home, or a Borg-compatible storage service. In this guide, that machine is called backup.example.com.
2. Install Borg
Borg must be installed on both machines, the VPS and the storage server:
apt update && apt install -y borgbackup
On the VPS, create an SSH key dedicated to backups, without a passphrase since it will be used by an automated task:
ssh-keygen -t ed25519 -f /root/.ssh/borg -N "" -C "borg@$(hostname)"
cat /root/.ssh/borg.pub
On the storage server, create a borg user and add the public key to its ~/.ssh/authorized_keys file, restricting it to Borg commands only:
command="borg serve --restrict-to-path /home/borg/repos",restrict ssh-ed25519 AAAA... borg@myvps
This restriction limits the damage if the VPS were compromised: the key cannot open a shell on the storage server.
3. Create the remote repository
Choose a long passphrase and store it in a file readable by root only:
openssl rand -base64 32 > /root/.borg-pass
chmod 600 /root/.borg-pass
export BORG_RSH="ssh -i /root/.ssh/borg"
export BORG_PASSCOMMAND="cat /root/.borg-pass"
borg init --encryption=repokey-blake2 ssh://[email protected]/home/borg/repos/myvps
Export the repository key immediately and keep it, together with the passphrase, somewhere other than the VPS: in a password manager, for example.
borg key export ssh://[email protected]/home/borg/repos/myvps /root/borg-key.txt
cat /root/borg-key.txt # copy it somewhere safe, then delete the file
4. The backup script
The files of a database in use cannot be copied reliably. So you first export the databases to a file, then Borg backs up that export with everything else. Create /root/backup.sh:
#!/bin/bash
set -euo pipefail
export BORG_REPO="ssh://[email protected]/home/borg/repos/myvps"
export BORG_RSH="ssh -i /root/.ssh/borg"
export BORG_PASSCOMMAND="cat /root/.borg-pass"
# 1. consistent database export
mkdir -p /var/backups/sql
mariadb-dump --all-databases --single-transaction --routines --events \
| gzip > /var/backups/sql/all-databases.sql.gz
# 2. backup
borg create --stats --compression zstd,3 --exclude-caches \
--exclude '/var/www/*/wp-content/cache' \
::'{hostname}-{now:%Y-%m-%d_%H%M}' \
/etc /var/www /home /root /var/backups/sql
# 3. retention: 7 daily, 4 weekly, 6 monthly
borg prune --keep-daily 7 --keep-weekly 4 --keep-monthly 6
borg compact
chmod 700 /root/backup.sh
/root/backup.sh
The first run sends everything; later runs only send changed blocks and usually take from a few seconds to a few minutes. Adapt the list of folders to your use: add, for example, the folder of your game servers or your Docker volumes.
mariadb-dump on the host: run the export inside the container with docker exec, then back up the resulting file. See Docker and Docker Compose.5. Automate
One line in /etc/cron.d/ runs the backup every night at 3:30 and keeps a record in a log:
echo '30 3 * * * root /root/backup.sh >> /var/log/borg.log 2>&1' > /etc/cron.d/borg
The script contains all its variables, so it works from cron with no extra configuration. This is the most common mistake with Borg: a command that works by hand but fails at night because the passphrase is not set.
6. Restore
First export the script's three variables in your terminal, then list the available archives:
borg list
Restore a file or folder: borg extract restores into the current folder, recreating the tree. Work in a temporary folder so you do not overwrite anything by mistake:
mkdir -p /tmp/restore && cd /tmp/restore
borg extract ::myvps-2026-09-18_0330 var/www/mysite.com/wp-config.php
Browse an archive like a folder, to find a file without knowing its exact path:
apt install -y python3-pyfuse3
mkdir -p /mnt/borg && borg mount ::myvps-2026-09-18_0330 /mnt/borg
ls /mnt/borg
borg umount /mnt/borg
Restore the databases from the export:
borg extract ::myvps-2026-09-18_0330 var/backups/sql/all-databases.sql.gz
gunzip -c var/backups/sql/all-databases.sql.gz | mariadb
7. Keep checking over time
- Read the log from time to time:
tail -n 30 /var/log/borg.log. A backup that fails silently for weeks is the most common scenario. - Check the integrity of the repository once a month with
borg check. - Test a full restore at least once a quarter, ideally on a test VPS. A backup that has never been restored is only a hypothesis.
To get an alert on failure, combine this script with the monitoring described in monitoring your VPS. And if you host a WordPress site, see also installing WordPress on a VPS.
Frequently asked questions
Where should VPS backups be stored?
Always somewhere other than the VPS itself: a second server, ideally in another data centre, a home server or a storage service reachable over SSH. A backup on the same disk protects you neither from the server being deleted nor from a break-in.
How much space do Borg backups take?
Thanks to deduplication, each new archive only stores the blocks changed since the previous one. With the retention in this guide, i.e. 17 archives, the total space is often barely more than one full compressed backup, for a site whose files change little.
Can I restore a single file without restoring everything?
Yes. borg extract accepts a specific path, and borg mount lets you browse an archive like an ordinary folder to copy only what you need.
Borg or rsync: which should I choose?
rsync copies the state at a given moment: if a file is corrupted or encrypted by ransomware, the next copy overwrites it. Borg keeps a history of encrypted, deduplicated versions, which lets you go back to the state of a precise date. For backups, Borg is the better choice.



