Backups & Disaster Recovery
A backup is a second copy of your data that you can restore from if the original is lost. Disasters happen: a disk dies, a bad command wipes a database, ransomware encrypts your files, or a whole datacentre catches fire. Backups are the difference between “we lost an hour” and “we lost the company.” This page shows you a practical, tested backup strategy on Ubuntu, because a backup you have never restored is just a hope, not a plan.
Why backups are a security topic
Backups protect the availability of your data, which is one of the three pillars of security (alongside confidentiality and integrity). Ransomware (malware that encrypts your files and demands payment) is now one of the most common attacks, and the only reliable cure is restoring from a clean, offline backup. So backups are not just an ops chore; they are a core security control.
The 3-2-1 rule
The 3-2-1 rule is the industry-standard baseline for backups. It is simple to remember and hard to beat:
- 3 copies of your data (the live one plus two backups).
- 2 different types of media or storage (for example, a local disk and cloud object storage).
- 1 copy offsite (in a different physical location from your server).
The offsite copy is the part most people skip, and it is the most important. If your backup lives on the same server as the data, a single disk failure, fire, or a compromised root account destroys both at once.
Gotcha: A backup that an attacker can delete is not a real backup. If your server’s credentials can erase the cloud copy, ransomware can too. Use immutable or versioned storage (for example, S3 Object Lock or
resticwith append-only repos) so backups cannot be silently deleted.
RPO and RTO: how much can you lose, how fast must you recover
Two terms drive every backup decision. Define them with your team before you build anything.
| Term | Full name | Question it answers | Example target |
|---|---|---|---|
| RPO | Recovery Point Objective | How much data can I afford to lose? | ”At most 1 hour of changes” |
| RTO | Recovery Time Objective | How long can I be down while I recover? | ”Back online within 2 hours” |
A 15-minute RPO means you must back up at least every 15 minutes. A 2-hour RTO means your restore process must be fast and rehearsed. Tighter targets cost more money and effort, so pick numbers that match the real business need, not the most paranoid one.
What to back up
Do not back up only “the database” and call it done. A working recovery needs everything required to rebuild the service.
| What | Where on Ubuntu | Notes |
|---|---|---|
| Databases | pg_dump, mysqldump, or replicas | See your DB backup page |
| App data / uploads | e.g. /var/www, /srv | User-generated files |
| Server config | /etc (nginx, systemd, ufw, postgresql) | Lets you rebuild fast |
| Secrets & certs | /etc/letsencrypt, env files, vault keys | Encrypt these copies |
| Cron jobs & timers | /etc/cron.d, systemd timers | Easy to forget |
Security tip: Backups of secrets and TLS private keys are still secrets. Always encrypt backups at rest, and restrict who can read the backup storage.
Automating backups with restic
restic is a modern, free backup tool that does encryption, deduplication (storing repeated data only once), and snapshots out of the box. It can write directly to cloud storage, which gives you the offsite copy automatically.
Install it:
sudo apt update
sudo apt install -y restic
restic version
Output:
restic 0.16.4 compiled with go1.22 on linux/amd64
Initialise an encrypted repository (here in a local backup disk; point the path at cloud storage for offsite):
export RESTIC_REPOSITORY=/mnt/backup/restic-repo
export RESTIC_PASSWORD='use-a-long-random-passphrase'
restic init
Output:
created restic repository 8f2c1a4e9b at /mnt/backup/restic-repo
Please note that knowledge of your password is required to access the repository.
Run a backup of your important directories:
restic backup /etc /var/www /srv
Output:
Files: 1843 new, 0 changed, 0 unmodified
Added to the repository: 214.512 MiB (61.203 MiB stored)
snapshot a1b2c3d4 saved
Schedule it with a systemd timer
A systemd timer is the modern Ubuntu way to run a job on a schedule (more reliable than cron for this). Create the service:
# /etc/systemd/system/restic-backup.service
[Unit]
Description=Daily restic backup
[Service]
Type=oneshot
Environment=RESTIC_REPOSITORY=/mnt/backup/restic-repo
EnvironmentFile=/etc/restic/password.env
ExecStart=/usr/bin/restic backup /etc /var/www /srv
ExecStartPost=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --prune
# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run restic backup daily
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
Store the password file with tight permissions, then enable the timer:
sudo mkdir -p /etc/restic
echo "RESTIC_PASSWORD=use-a-long-random-passphrase" | sudo tee /etc/restic/password.env
sudo chmod 600 /etc/restic/password.env
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer
Output:
NEXT LEFT UNIT ACTIVATES
Tue 2026-06-16 02:30:00 UTC 9h left restic-backup.timer restic-backup.service
The forget --prune step enforces a retention policy (how long you keep old backups), so storage does not grow forever.
Testing your restores
This is the rule everyone breaks and the one that matters most: an untested backup is not a backup. Schedule a real restore drill at least monthly. Restore into a throwaway directory or a spare server and confirm the data is actually usable.
mkdir -p /tmp/restore-test
restic restore latest --target /tmp/restore-test
ls /tmp/restore-test/etc/nginx/sites-available
Output:
default myapp.conf
Check repository integrity regularly so silent corruption is caught early:
restic check
Output:
no errors were found
For databases, a restore test means loading the dump into a scratch database and running a query, not just confirming the file exists. Tie this into your database backup procedures.
Best Practices
- Follow 3-2-1: three copies, two media types, one offsite. The offsite copy is non-negotiable.
- Encrypt every backup at rest, especially anything containing secrets or TLS private keys.
- Use immutable or versioned backup storage so ransomware and bad scripts cannot delete your history.
- Automate backups with a systemd timer and a retention policy so they happen even when you forget.
- Define explicit RPO and RTO targets and verify your tooling actually meets them.
- Test restores on a schedule (monthly at minimum) and run
restic checkto catch corruption. - Document the full recovery steps so anyone on the team can run them under pressure.