SSD Nodes Learn
How to do am Matt ConnorBy Matt Connor · Updated 2026-07-24

how to use restic for VPS backup

Use restic to send encrypted, deduplicated backups from your VPS to S3 or SFTP. Learn how to set up systemd timers and test your restore drill today.

Why backup for the same server no be real backup

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

backup/ directory for the same box wey you dey back up dey protect you for only one thing: if you accidentally delete file. E no go survive if disk fail, because the file dey that disk. E no go survive attacker wey get root access, because dem go delete the copies first. E no go survive mistake wey make person delete the VPS itself. The world's least efficient datacenter dey joke about tarball wey dem call backup_final_v2_REAL wey dey sit for the same array as the data, and the joke dey make sense because many of us don do exactly that. Rule na say backup must dey outside the box, and restic na the easiest way to follow am.

Restic for four ideas

Repository. Na the place wey restic dey write to. Na directory wey dey use restic format, full of encrypted blobs, and only restic fit read am. No ever try edit am by hand; you must use restic commands and the -r address take talk to am.

Snapshot. Na one picture of your files for one specific time. Every time you run backup, e dey create one snapshot. You fit restore any single snapshot, and each one dey act like complete copy of your data for that exact moment.

Deduplication. Restic dey split files into content-defined chunks, and e only upload the chunks wey repository never see before. The first backup go upload everything; every run after that one, e go only upload wetin change small. If you get nightly snapshot of 20 GB and only 50 MB change, e go only cost about 50 MB, na why e cheap to keep many snapshots.

Encryption by default. Every restic repository dey always encrypted (AES-256), and every command need the repository password. The backup host or the storage provider no go ever see anything except encrypted blobs. The big wahala be say: if you lose the password, the data don go, permanently and by design. Keep one copy of the password for place wey no be this server. This one important well-well, na why e dey appear twice more below.

Install restic on 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, even though current upstream release na 0.19.1. Dis gap dey because LTS (long term support) release dey freeze package versions, but e no matter for here: 0.16.4 fit do everything wey dey dis guide. If you want newest release because of speed improvements, download official single-binary build from restic project GitHub releases page, unpack am with bunzip2, and install am to /usr/local/bin/restic; restic install no get any extra step.

Create the repository on another server over SFTP

You need one destination machine: usually, a second small VPS na the best way, but any box wey get SSH server and extra disk space go work. Restic dey use SFTP (file transfer over SSH), so you no need to install anything for the backup host. For this guide, the backup host na 10.0.0.12 with user name restic. No use backup as user name: Ubuntu and Debian dey carry one reserved system account wey dem dey call backup (uid 34, no login shell) for every install, 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 one dedicated key wey no get passphrase, because no human go dey there for 3am to type am, then copy am over:

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 na new thing for you, SSH key management basics go explain how the model, the permissions, and how to revoke key work.

Next, the repository password. Generate one strong password inside one file wey only root fit open:

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 die, the repository plus this password go bring everything back; the repository without the password no go bring anything back.

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 other option na S3-compatible object storage, which na the right choice if you no want run second machine. Any S3-compatible bucket go work the same way; 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 na the same for both destinations. The rest of this guide dey show SFTP address; use your own address instead.

The first backup, with excludes

Back up only the data wey you no fit reinstall, no back up the whole filesystem. Operating system dey come back when you reinstall; your configuration and your data no dey come back. For typical VPS, that one mean /etc, /home, and any place wey your applications dey keep state, like /srv or /var/www. No include caches, because dem big, dem dey change every day, and dem dey rebuild demself:

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 time. Run the same command again and e go finish in seconds, e go show say only few files change and few MiB add, because deduplication dey only upload 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 dey show ID, time, and the paths wey e contain. Na those IDs you go use for restore.

Nightly runs with a systemd timer

To dey type repository address for every command dey tire person, and if you dey run backup manually, you go stop to do am within one month. You fit solve both problems with one script and one timer. The script go set the two environment variables wey restic dey read, RESTIC_REPOSITORY and RESTIC_PASSWORD_FILE, so every command inside the script go 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 for the schedule: one oneshot service wey go run the script, and one timer wey go fire am for 03:00 every night. Timer better pass cron line for here because the run logs go dey inside journal, and Persistent=true go run any backup wey dem miss as soon as the server come back up 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 to see 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 go show you when the next run go fire. You fit also generate the pair of unit files instead of to type dem:

ToolGenerate the backup service and timer

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

Backup na rumor until you restore am

Treat that sentence like commandment. If backup job dey run green every night, e only show say job run; e no prove say your data go come back. Two checks dey close that gap.

First, restic check, wey the script already dey run nightly. E dey verify repository structure and index, so if silent corruption dey happen for backup host, you go catch am next night instead of on restore day. Once every month, run the deeper version, wey go download and cryptographically verify random 10% 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 na random every time, monthly runs go cover the whole repository without you to pay for full download.

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

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

If diff no print anything, e mean say every byte come back identical, and na only that evidence dey count. Delete /srv/restore-drill after you finish. Do this drill monthly, and once or twice every year, do the full version: restore the entire latest snapshot onto one scratch VPS and check if your application actually start from am. The day you need this to work under pressure, you want make e be routine wey you don already do.

Retention: forget plus prune

If you no set policy, snapshots go dey pile up forever and repository go just dey grow. The script forget line dey apply policy every night: --keep-daily 7 dey keep one snapshot for every day for the last seven days, --keep-weekly 4 dey keep one for every week for four weeks, and --keep-monthly 6 dey keep one for every month for six months. Anything wey no get protection from rule, the system go forget am.

forget for its own only dey remove snapshot records; the data chunks go still dey inside repository until something delete dem. Na wetin --prune dey do: e dey find chunks wey no get snapshot references again and e dey delete dem, na when dem dey delete dem na when disk space go really free. Prune dey do real work for repository, so for big repository, some people dey run forget every night and --prune every week; for normal VPS size, nightly dey work fine.

Databases: dump first, then back up the dump

Restic dey copy files as e dey read dem, but database dey write to im files continuously. If you capture live database file mid-write, e go restore as corrupt database, because the copy go mix pages from before and after the write. The standard fix na: make the database engine produce one consistent export to a file, then make restic back up that file.

For PostgreSQL, add one dump line to the 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 one worked example of the whole pattern, the Nextcloud backup section dey turn on maintenance mode, dump Postgres, and copy the files as one consistent set, exactly the set restic suppose carry off the box each night. SQLite na the same idea but with smaller hammer: the Vaultwarden guide dey stop the container for a few seconds to take one cold copy of db.sqlite3, and na that archive restic dey ship off the server.

FAQ

Restic backups dey encrypted?

Yes, dem always dey encrypted. Every restic repository dey use AES-256 encryption. No unencrypted mode for here, and every command go ask for the repository password. The machine or provider wey dey store the repository only dey hold encrypted blobs, so if dem hack the backup host, your files no go dey safe for dem. The deal na simple: without the password, nobody fit recover the data, so keep one copy far away from the server.

Restic dey do incremental backups?

Every restic snapshot dey behave like full backup, but e no dey use much storage because e dey do incremental. Restic dey split files into chunks and e go upload only the chunks wey the repository no don see before, so nightly run go only transfer wetin change for that day. Unlike old incremental ways, no chain wey you need to replay: any snapshot fit restore directly and if you delete old snapshot, e no go ever spoil newer one.

How I go restore files from a 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 wan restore only part of am. latest fit work instead of ID. Restic dey recreate the original directory structure inside the target, so if you restore /etc/ssh, e go land for /some/empty/dir/etc/ssh. Try am before you really need am, because backup wey you never test na just rumor.

How many times I suppose run restic backup?

Nightly na the best minimum for server, and deduplication make e cheap: every run go only upload the chunks wey change since the last one. For data wey dey change fast, or data wey go hurt if you lose even one day, you fit run am every few hours with the same timer pattern. Frequency easy part; you must also run restic check regularly and do one restore drill every month, because schedule wey no get verification na false comfort.

Wetin go happen if I lose my restic repository password?

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