Everyone has backups until they try to restore one. The folder turns out to be empty, the cron job died in March, or the archive sits on the same disk that just failed. restic fixes most of that: it encrypts on your side, stores each piece of data once, and makes restoring a single file as easy as backing up the whole server.
Here's a setup we'd actually trust, on Ubuntu or Debian.
1. Install restic
apt update && apt install -y restic
restic self-update
Distribution packages lag behind; self-update pulls the current release.
2. Pick a place for the repository
The repository must not live on the server you're protecting. Two common choices:
- Another server over SFTP:
sftp:backup@203.0.113.20:/srv/restic/web1 - S3-compatible object storage:
s3:https://s3.example.com/my-bucket/web1
3. Store the credentials
Keep everything in one root-only file so the timer and your shell use the same settings:
cat > /root/.restic-env <<'EOF'
export RESTIC_REPOSITORY="s3:https://s3.example.com/my-bucket/web1"
export RESTIC_PASSWORD_FILE="/root/.restic-pass"
export AWS_ACCESS_KEY_ID="your-key-id"
export AWS_SECRET_ACCESS_KEY="your-secret"
EOF
openssl rand -base64 32 > /root/.restic-pass
chmod 600 /root/.restic-env /root/.restic-pass
Now copy the contents of /root/.restic-pass into your password manager. Without it, the backups can't be decrypted — by you or anyone else.
4. Initialise and run the first backup
source /root/.restic-env
restic init
restic backup /etc /home /root /srv /var/www \
--exclude-caches --exclude '/root/.cache'
restic snapshots
Adjust the paths to where your data actually lives. Docker volumes sit under /var/lib/docker/volumes; application data is often in /srv or /opt.
5. Databases: dump, then back up
Don't back up the raw files of a running database. Dump it just before the backup:
mkdir -p /var/backups/db
sudo -u postgres pg_dump -Fc mydb > /var/backups/db/mydb.dump
Add /var/backups/db to the backup paths. Our PostgreSQL guide has more on dumps.
6. Schedule it with systemd
A timer beats cron here: it logs to the journal, and it catches up if the server was off at run time.
# /etc/systemd/system/restic-backup.service
[Unit]
Description=restic backup
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'source /root/.restic-env && restic backup /etc /home /root /srv /var/www /var/backups/db --exclude-caches && restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune'
# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Daily restic backup
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer
forget --prune keeps 7 daily, 4 weekly and 6 monthly snapshots and deletes the rest. If you have a database dump step, put it in an ExecStartPre= line.
7. Actually restore something
This is the step that turns "we have backups" into a fact. Pull one directory back into a temporary folder and look at it:
source /root/.restic-env
restic restore latest --target /tmp/restore-test --include /etc/nginx
ls -la /tmp/restore-test/etc/nginx
restic check
Do this once now and again every few months. restic check verifies the repository structure; the restore proves the data is really there.
restic and Managed Backups
They don't compete. Managed Backups take a daily restore point of the whole server that you roll back from the dashboard — the fast fix after a broken upgrade. They cost $2/month and are included free with any annual plan. restic gives you file-level, off-site copies in storage you control, which matters when the problem is a deleted file from last Tuesday or you want a copy outside our infrastructure entirely.
If you store sensitive data, pair this with full-disk encryption, or look at the encrypted storage use case for running your own backup target. A Micro plan is enough for most small servers plus their backup jobs.
Comments
No comments yet. Be the first.