SSD Nodes Learn Hosting plans →
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-07

Restic backup for VPS: move data comot server

Restic fit send encrypted, deduplicated VPS backups go another server or object storage every night. Learn setup, retention, and restore drill wey prove e work.

Why backup wey dey for the same server no be backup

Restic na free, open source backup tool wey dey send encrypted, deduplicated snapshots of your files go repository for another place: second VPS, machine for house, or S3-compatible object storage. This guide go set am up for Ubuntu 24.04, from installation reach repository over SFTP, first backup, nightly systemd timer, retention policy, and restore drill wey go prove say everything dey work. The destination must be another machine, because copy wey dey for the same server go die together with the server.

A backup/ directory for the box wey e dey back up fit protect you from only one thing: deleting file by mistake. E no go survive failed disk, because e dey on that disk. E no go survive attacker wey get root, because dem go delete the copies first. E no go survive account mistake wey remove the VPS itself. The world's least efficient datacenter dey joke about tarball wey dem name backup_final_v2_REAL wey dey on the same array with the data, and the joke dey work because plenty of us don run exactly that. The rule na make e dey outside the box, and restic na the least painful way to follow am.

Restic for four idea

Repository. Na the place wey restic dey write go. Na directory for restic own format, full of encrypted blobs, and na only restic fit read am. You no dey edit am by hand; you dey communicate with am through restic commands and the -r address.

Snapshot. Na one picture of the files wey you back up for one particular time. Every backup run dey create snapshot, every snapshot fit restore by itself, and each one dey behave like complete copy of your data for that moment.

Deduplication. Restic dey split files into content-defined chunks and upload only the chunks wey repository never see before. The first backup dey upload everything; every run after that dey upload roughly wetin change. Nightly snapshot of 20 GB where 50 MB change go cost about 50 MB, na why keeping dozens of snapshots cheap.

Encryption by default. Restic repository always dey encrypted (AES-256), and every command need repository password. Backup host or storage provider go only ever see encrypted blobs. The hard consequence be say: if you lose the password, the data don go permanently, by design. Keep one copy of the password for somewhere wey no be this server. This matter important enough to come up two more times below.

Install restic for Ubuntu 24.04

sudo apt update && sudo apt install -y restic
restic version

For Ubuntu 24.04, dis one go install restic 0.16.4, while the current upstream release na 0.19.1. The difference dey because LTS (long term support) release dey freeze package versions, and e no matter for here: 0.16.4 fit do everything for dis guide. If you want the newest release because of the speed improvements, download the official single-binary build from the restic project's GitHub releases page, unpack am with bunzip2, then install am to /usr/local/bin/restic; nothing else dey for restic installation.

Server wey dey for another machine over SFTP create the repository

You need destination machine: another small VPS na the usual answer, and any machine wey get SSH server plus free disk space go work. Restic dey speak SFTP (file transfer over SSH), so backup host no need install anything. For this guide, backup host na 10.0.0.12 with user wey dem name restic. No name that user backup: Ubuntu and Debian dey ship reserved system account wey dem call backup (uid 34, e no get login shell) for every installation, so adduser backup go fail and ssh backup@... go land for nologin.

The nightly job go run as root for the server wey you dey back up, so root need key login to the backup host. Create dedicated key without passphrase, because nobody go dey there for 3am to type am, then copy am go:

sudo ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N "" -C "web1-restic"
sudo ssh-copy-id -i /root/.ssh/id_ed25519.pub restic@10.0.0.12
sudo ssh restic@10.0.0.12 true && echo key login works

If SSH keys still new to you, SSH key management basics dey explain the model, permissions, and how to revoke key later.

Next na repository password. Generate strong one inside file wey only root fit read:

openssl rand -base64 32 | sudo tee /root/.restic-password
sudo chmod 600 /root/.restic-password

Now copy that password enter your password manager before you continue. If this VPS crash, repository plus this password fit restore everything; repository without the password no fit restore anything.

Initialise the repository:

sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password init
created restic repository 9f3c2a1b0d at sftp:restic@10.0.0.12:/srv/restic/web1

The alternative destination na S3-compatible object storage. This one make sense when you no want run second machine. Any S3-compatible bucket go work the same way; na only the address and two credential variables go change:

export AWS_ACCESS_KEY_ID=your-key-id
export AWS_SECRET_ACCESS_KEY=your-secret-key
sudo -E restic -r s3:https://s3.example.com/web1-backups --password-file /root/.restic-password init

Everything after init dey identical for both destinations. The rest of this guide show the SFTP address; replace am with your own.

Backup wey get excludes

Back up the data wey you no fit reinstall, no be the whole filesystem. Operating system go come back when you reinstall am; your configuration and data no go. For normal VPS, that one mean /etc, /home, and anywhere wey your applications dey keep state, like /srv or /var/www. Exclude caches, because dem big, dem dey change every day, and dem fit rebuild by themselves:

sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password backup /etc /home /srv --exclude '/home/*/.cache'
Files:        4181 new,     0 changed,     0 unmodified
Added to the repository: 731.204 MiB (312.418 MiB stored)
snapshot 5b8a3f2c saved

The first run go upload everything, so e go take small time. Run the same command again and e go finish within seconds, reporting say some files change and some MiB add, because deduplication only uploads new chunks. List wetin you get:

sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password snapshots

Every snapshot show ID, time, and the paths wey e contain. Na those IDs you go use restore from.

Nightly run with systemd timer

Typing the repository address for every command dey tire, and backup wey you dey run by hand go stop within one month. One script and one timer solve both problems. The script set the two environment variables wey restic dey read, RESTIC_REPOSITORY and RESTIC_PASSWORD_FILE, so every command inside am stay short:

sudo nano /usr/local/bin/restic-backup.sh
#!/usr/bin/env bash
set -euo pipefail
export RESTIC_REPOSITORY='sftp:restic@10.0.0.12:/srv/restic/web1'
export RESTIC_PASSWORD_FILE=/root/.restic-password

restic backup /etc /home /srv --exclude '/home/*/.cache'
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check
sudo chmod 700 /usr/local/bin/restic-backup.sh

The forget and check lines dey explained for the next two sections. Now, make we set the schedule: one oneshot service wey go run the script, and one timer wey go trigger am for 03:00 every night. Timer better pass cron line for here because the run dey log to the journal, and Persistent=true go run missed backup as soon as server come back online after downtime.

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

[Service]
Type=oneshot
ExecStart=/usr/local/bin/restic-backup.sh
# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run the nightly restic backup

[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target

Enable the timer, then run the service once by hand and monitor how e dey work:

sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
sudo systemctl start restic-backup.service
sudo journalctl -u restic-backup.service -f

systemctl list-timers show when the next run go trigger. You fit also generate the two unit files instead of typing dem:

ToolGenerate the backup service and timer

The full pattern behind these two files, including calendar syntax and the hardening directives wey service fit carry, dey for running program as systemd service for VPS.

Backup na rumor until you restore am

Treat that sentence like commandment. Backup job wey run green every night only prove say job run; e no prove say your data go come back. Two checks fit close this gap.

First, restic check, wey the script already dey run every night. E verify the repository structure and the index, so silent corruption for the backup host go dey caught the next night instead of restore day. Once every month, run the deeper version, wey download and cryptographically verify random tenth of the actual data:

sudo -i
export RESTIC_REPOSITORY='sftp:restic@10.0.0.12:/srv/restic/web1'
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic check --read-data-subset=10%

Because the subset dey random every time, monthly runs go gradually cover the whole repository without ever paying for full download.

Second, the restore drill. Still inside the root shell from above, restore one real directory from the latest snapshot go scratch location, then compare am against the live files:

restic restore latest --target /srv/restore-drill --include /etc/ssh
diff -r /etc/ssh /srv/restore-drill/etc/ssh

diff printing nothing mean say every byte come back identical. Na only this evidence count. Delete /srv/restore-drill afterwards. Do this drill every month, and once or twice every year do the full version: restore the entire latest snapshot onto scratch VPS and check say your application actually start from there. The day wey you need this to work under pressure, you want am to be routine wey you don already do.

Retention: make we forget then prune

If policy no dey, snapshots go dey pile up forever and repository go continue to grow. The script's forget line dey apply policy every night: --keep-daily 7 dey keep one snapshot for each day of the last seven days, --keep-weekly 4 one for each week across four weeks, and --keep-monthly 6 one for each month across six months. Anything wey no rule protect, dem go forget am.

forget by itself only dey remove snapshot records; the data chunks still dey inside repository until something delete dem. Na --prune dey do that: e dey find chunks wey no remaining snapshot reference dey point to and delete dem. Na for that time disk space actually return. Prune dey do real repository work, so for large repository some people dey run forget every night and --prune every week; for normal VPS sizes, every night dey okay.

Databases: make dump first, then back up the dump

Restic dey copy files as e dey read dem, while database dey write to im files continuously. If e capture live database file while write still dey happen, restore fit give corrupt database, because the copy mix pages from before and after the write. The standard fix be this: make database engine produce consistent export to a file, then make restic back up that file.

For PostgreSQL, add one dump line for top of restic-backup.sh, before the restic backup command, and include the dump directory for the backup paths:

mkdir -p /var/backups/db
sudo -u postgres pg_dump myapp | gzip > /var/backups/db/myapp.sql.gz

mysqldump dey do the same work for MariaDB and MySQL. For complete example of the whole pattern, the Nextcloud backup section turn on maintenance mode, dump Postgres, and copy the files as one consistent set. Na exactly that set restic suppose carry commot from the server every night. SQLite na the same idea, but with smaller approach: the Vaultwarden guide stop the container for some seconds to take cold copy of db.sqlite3, and na that archive restic ship commot from the server.

FAQ

Restic backup dem dey encrypted?

Yes, always. Restic repository every time dey encrypted with AES-256. No unencrypted mode dey, and every command need repository password. Machine or provider wey dey store the repository only dey hold encrypted blobs, so if backup host get breached, e no go expose your files. The trade-off clear: without the password, nobody fit recover the data. So store one copy away from the server.

Restic dey do incremental backups?

Every restic snapshot dey behave like full backup, but e dey use incremental storage. Restic dey split files into chunks and upload only chunks wey repository never store before. So nightly run dey transfer roughly wetin change that day. Unlike traditional incremental schemes, no chain dey to replay. Any snapshot fit restore directly, and deleting old snapshot no dey break newer one.

How I go restore files from restic backup?

Run restic snapshots to find the snapshot ID. Then run restic restore <id> --target /some/empty/dir to restore am, and add --include /path if you want restore only part of am. latest fit work instead of ID. Restic go recreate the original directory structure under the target, so restoring /etc/ssh go land for /some/empty/dir/etc/ssh. Practice this before you need am, because backup wey you never test na only rumor.

How often I suppose run restic backup?

Nightly na sensible minimum for server, and deduplication make am cheap. Each run only upload chunks wey change since the previous one. Data wey dey change fast, or data wey losing even one day go cause serious problem, fit run every few hours with the same timer pattern. Frequency na only one part. Also run restic check regularly and do restore drill every month, because schedule without verification na false comfort.

Wetin go happen if I lose my restic repository password?

The backups no fit recover again. Restic encryption get no back door and no reset, so the password dey important as the backups themselves. Keep one copy for your password manager and another durable location wey no be the backed-up server. While you still get access, restic key add fit register second password for the same repository, so you get spare one.