The problem: the backup everyone postpones
Backing up a VPS is the task everyone puts off, because it returns nothing until the day it returns everything. Provider snapshots are convenient, but they copy the whole machine to the same provider in the same place: they protect against your own mistakes, not against losing the account or an incident on the infrastructure. And a snapshot will not give you back one file that was overwritten this morning.
The reference open-source answer is restic: end-to-end encryption, deduplication, incremental snapshots, and support for virtually every object store. Its only weakness is ergonomic — it is a command-line tool. Adopting it in practice means writing your own scripts, cron entries, retention policy, periodic pruning and monitoring. Many people stop after the first script, and nobody notices when it quietly stops running.
What Backrest adds on top of restic
- A web interface to create repositories, run backups and browse snapshots as a file tree.
- Cron-style scheduling per plan, with retention policies (keep N daily, weekly, monthly) defined in the browser.
- Automatic repository maintenance: scheduled
pruneto reclaim space andcheckto catch corruption before you need the backup. - Granular restore — a single file or folder — with no full restore and no downtime.
- Hooks on start, success and failure: notify ntfy, Discord, Slack or any webhook, or run a shell command.
- Multiple repositories and multiple plans side by side from a single instance.
- A single Go binary, under 100 MB RAM, no database — restic ships inside the image.
Requirements before you install
Backrest is lightweight, but a few hardware and software prerequisites are worth checking before deploying. On the server side, 512 MB RAM is the functional minimum — enough for a machine dedicated to backups; if the VPS also runs other active services, 1 GB is more comfortable. The version of restic bundled in the Backrest Docker image is kept current by design, but if you manage restic independently, make sure you are on restic ≥ 0.16.0: older versions do not handle certain JSON retention policies and may silently ignore --keep-* rules.
Backrest exposes its UI on port 9898 (TCP). That port must be open in your VPS firewall (ufw allow 9898/tcp or equivalent), but should not be publicly reachable without authentication: on first start, restrict it by source IP while you create your admin account. Finally, the Backrest data directory — /var/lib/backrest in the ServOrbit recipe — requires write access for the containerised process: a Docker volume accidentally mounted read-only will silently fail to save configuration changes.
Architecture: one container, and your data stays yours
Backrest is a single Go binary that bundles restic. It runs in one container with no database and no external cache: its configuration lives in a JSON file and its state in a data directory. That is the opposite of enterprise backup stacks, and it is what makes it a sensible fit for a modest VPS.
The direction of the encryption is what matters. restic encrypts every snapshot locally, on your server, before a single byte leaves it: the destination only ever receives opaque blocks. The repository password is the key, and you alone hold it — which means the storage can be a cheap, untrusted provider without any confidentiality problem, but also that losing that password makes the backups permanently unreadable. That is the explicit trade-off of any client-side encryption.
In the ServOrbit recipe, the host's /home, /root and /etc are mounted read-only under /host inside the container. Backrest can therefore back up the server's data and configuration while being structurally unable to modify them.
Choosing a storage backend
Scroll the table
| Backend | value |
|---|---|
| Backblaze B2 | Recommended for getting started. ~$0.006/GB/month, no ingress fees, free egress to Cloudflare CDN. Create a private bucket, generate an application key with access restricted to that bucket, and paste both into Backrest. restic's deduplication means your actual cost will be well below the raw volume. |
| S3 AWS or MinIO | Right fit for infrastructure already in the AWS ecosystem, or for self-hosting object storage on a second VPS (MinIO). Same S3 interface — Backrest parameters are identical, only the endpoint URL changes. AWS Glacier Instant Retrieval costs even less but adds latency to restores. |
| SFTP to a second VPS | No external subscription needed if you have a second server. Set up SSH key access (passwordless, rights limited to the destination directory), then use the `sftp:user@host:/path` backend in Backrest. Ideal for cross-replication between two ServOrbit VPS instances in different datacentres. |
Deploy Backrest and protect a VPS in 6 steps
Logging in for the first time
When you first open the URL, Backrest displays its initial setup screen: you choose an instance ID (permanent), then create your own username and password yourself. Open this address immediately.
Restoring a file or directory
Restoring in Backrest works at two levels depending on the granularity you need.
From the web interface: open the Snapshots tab of your plan, select a snapshot by date, navigate the file tree and click Restore for any file or folder. Backrest triggers a restore to the destination path you specify — for example /tmp/restore-test/ to avoid overwriting the live file.
From the restic CLI (useful for large or scripted restores): enter the container with docker exec -it backrest sh, then run restic -r <your-repo-url> restore latest --target /tmp/restore/. To restore a specific path rather than the whole snapshot, add --include /host/home/user/project — restic only restores that subtree. After a restore, validate the source snapshot's integrity with restic check --read-data-subset=5%: this option checks a random sample of data blobs (not just metadata) without having to download everything.
Troubleshooting common issues
Silent cron failure. If the plan never triggers despite a correct schedule, confirm the Backrest container is running (docker ps) and that its internal clock is synchronised with the host (pass --env TZ=Europe/Paris or your timezone equivalent when creating the container). A clock offset can let the trigger window pass with no error logged.
wrong password or no key found error. This error appears when the password you enter does not match the key stored in the repository. It can also mean the repository was initialised a first time with a different password — each restic repository has only one active key set. Check that you have not got a trailing space or invisible character in a copy-pasted password. If you have lost the password, the repository is permanently unreadable — that is the price of client-side encryption.
Insufficient storage space on the backend. Backrest shows a repository is full error or similar when the bucket quota is reached. Enable automatic prune in your plan to prevent old snapshots from accumulating beyond the retention policy. On Backblaze B2, you can also configure a lifecycle rule on the bucket to automatically delete objects flagged by restic as deleted (restic forget only removes blobs after a subsequent prune).
Backrest no longer responds on port 9898. First confirm the container is running (docker ps), then that the port is bound (ss -tlnp | grep 9898). If the container is in a restarting state, check the logs with docker logs backrest --tail 50 — a corrupted JSON configuration file is the most common cause after an abrupt shutdown.
Tip: the 3-2-1 rule starts by leaving the server
The most common mistake is sending backups to a disk on the same server, or a volume at the same provider. That protects against accidental deletion, not against losing the machine or the account. Aim for at least one destination outside the VPS host: Backblaze B2 or Wasabi cost a few euros a month for tens of gigabytes, and thanks to restic's deduplication, months of daily retention stay far smaller than you would expect.