Making backups boring before you trust anything important
This is the boring lesson that lets you relax. Once backups run on their own and you've seen a restore actually work, you can hand your server real things, photos, passwords, documents, without that nagging feeling.
Here's the mindset that matters most: a single drive is not a backup. If your data only exists on the server, then a dead disk, a bad update, or a fat-fingered down -v takes it with no undo. A backup is a second copy, somewhere else, that you can actually restore from.
What you're actually backing up
Because you kept every app in its own folder under ~/apps, with its compose file and its data folder together, "back up my server" mostly means "copy those folders". That's the whole payoff of setting things up tidily. Three things go in a backup:
- The compose files. Tiny, but they're the recipe to rebuild every app.
- The data folders and volumes. The actual contents, settings, photos, files.
- Databases, done properly. If an app runs a database, copying its files while it's live can give you a corrupt copy. Use the app's own backup or export where it offers one, or stop the container briefly before copying. Many small apps just use plain files and don't need this, but it's the one gotcha worth knowing.
The simplest real setup: a drive and a nightly copy
Plug an external USB drive into the server. On a server OS it won't mount itself, so this one-time dance introduces two commands: lsblk lists the drives the machine can see (your USB drive will show up with a name like sda1), and mount attaches it to a folder so you can use it.
lsblk # find the drive, e.g. sda1
sudo mkdir -p /mnt/backup
sudo mount /dev/sda1 /mnt/backup # attach it at /mnt/backupA plain mount only lasts until the next reboot, and a backup that quietly dies at the first power cut is exactly the trap we're here to avoid. So make it permanent while you're at it. Ask the drive for its ID and type:
sudo blkid /dev/sda1Copy the UUID and TYPE values it prints, then sudo nano /etc/fstab (the file Linux reads at boot to know what to mount where) and add one line at the bottom:
UUID=paste-your-uuid-here /mnt/backup ext4 defaults,nofail 0 2Swap ext4 for whatever TYPE blkid showed, and keep nofail: it means the server still boots normally if the drive is ever unplugged. Save, run sudo mount -a, and silence means it worked. Ubuntu's fstab guide goes deeper if your drive is unusual.
The copy itself is one command. rsync mirrors a folder and, after the first run, only copies what changed:
rsync -a ~/apps/ /mnt/backup/apps/Run it once and check the files landed. Then make the server do it every night instead of you: crontab -e opens your schedule file, and this line runs the same command at 3am daily.
0 3 * * * mountpoint -q /mnt/backup && rsync -a /home/yourname/apps/ /mnt/backup/apps/Those five fields are minute, hour, day, month, weekday; crontab.guru decodes any schedule you can dream up. Three deliberate choices in that line: full paths (cron doesn't know what ~ means as reliably as you do), the mountpoint check, which skips the copy entirely if the drive somehow isn't attached rather than dumping files onto the wrong disk, and no --delete flag, so if you fat-finger something away at home, the backup still has last night's copy instead of faithfully deleting it too.
This setup has one honest limit: it keeps exactly one copy, last night's state. If something corrupts quietly and you only notice next week, the backup has the corrupted version too. That's what restic (command line) and Duplicati (web UI) solve: versioned snapshots, so you can step back to any point, plus encryption and cloud targets. Start with the rsync line tonight; graduate to one of these when the data starts mattering.
What a restore actually looks like
Until you've done a restore, you only believe you have backups. Prove yours works on a throwaway app, it takes two minutes. Pick any app with a data folder, run your rsync line, then simulate the disaster:
cd ~/apps/the-app
docker compose down
mv data data-broken # "lose" the data
cp -r /mnt/backup/apps/the-app/data . # pull it back from the backup
docker compose up -dOpen the app. If your stuff is there, your backup is real, and you now know the restore moves by heart. Delete data-broken and sleep better. Plenty of people discover their backups were broken on the exact day they needed them; you just checked on a calm Tuesday instead.
The 3-2-1 idea
The rule people repeat, and it's a good one: three copies of anything you care about, on two different kinds of storage, with one of them off-site. In home terms that's often the live copy on your server, a backup on an external drive, and a copy in cheap cloud storage or at a relative's house. You don't need all three on day one, but a backup that sits in the same box as the original won't save you from a fire or a theft.
Common questions
How often should I back up?
Nightly and automated is the sweet spot for home data. The cron line above does exactly that. Anything you'd genuinely cry about losing between backups (a day of new photos, say) is a sign to back up more often or sync that data separately.
Do I need to back up the containers or images?
No. Images are redownloaded from the internet in seconds, and containers are rebuilt from your compose files. The compose files and the data folders are everything; that's why they live together under ~/apps.
Where should backups go?
An external drive is the right first step. The upgrade path is an off-site copy, cheap cloud storage through restic or Duplicati, or a drive that lives at a relative's place, because a fire or a burglary takes the server and the drive next to it together.
With backups running and tested, the guard rail is up. Now you can host the good stuff. And the natural next want is reaching it when you're out, so let's talk about getting to your apps, starting at home.