Skip to main content

Home Server Backup Restore Drill for Docker and VMs

Home Server Backup Restore Drill: Prove Your Docker and VM Backups Actually Work

Last updated: October 2026

Tested on: Ubuntu 24.04 LTS, Docker Engine , Docker Compose v2, Proxmox VE , 

A backup is not real because a job says “success”.

A backup is real when you can restore it, boot it, log in, see your data, and explain the steps without searching through old browser tabs at midnight.

This is the restore drill I would run on a home server that has both Docker services and virtual machines. It is not glamorous. It does not look impressive on a dashboard. It does something more useful: it proves whether your homelab backups actually work.

If you are running Docker Compose stacks, Proxmox VMs, databases, reverse proxies, monitoring tools, file shares, DNS services or anything else you would miss if the server died, this drill is worth doing.

Backups are only half the system. Restore is the part that tells the truth.


Quick answer: how do you prove a home server backup works?

You prove a home server backup works by restoring it into a separate test location, starting the restored Docker stack or VM, checking that the application opens, verifying real data inside the app, confirming permissions and secrets, measuring how long the restore took, and writing down every missing step.

For Docker, that means testing more than container startup. You need to restore:

  • the compose.yml file;
  • the .env file;
  • bind-mounted folders;
  • named volumes;
  • database dumps or database volumes;
  • reverse proxy configuration;
  • secrets, API keys and passwords;
  • restore notes.

For VMs, that means restoring the backup to a new test VM or isolated environment, booting it safely, checking the operating system, checking services, and making sure it does not collide with the production VM on the same network.

The test is simple:

Could I rebuild the service from this backup without touching the original server?

If the answer is “probably”, you have not tested enough yet.


Who this guide is for

This guide is for small home servers and homelabs where “production” means real personal data, real family services, real documents, real photos, real monitoring, real DNS, real media libraries or real lab notes.

It fits setups like:

  • a Linux server running Docker Compose under /srv/docker;
  • a Proxmox host with a few VMs or LXC containers;
  • a used Dell, HP, Lenovo, mini PC or workstation running home services;
  • a server with Uptime Kuma, Caddy, Jellyfin, Paperless, Gitea, Home Assistant or similar tools;
  • a backup target such as a USB disk, NAS, remote server or Proxmox Backup Server;
  • a setup where backups exist, but nobody has restored one recently.

If you are still building the Docker foundation, read the secure Docker Compose homelab stack guide first. This backup restore drill is the next step after the stack exists.

If you want the broader security path, start with the Start Here page and the Linux Home Server Security Guide.


Table of contents

  1. What this restore drill proves
  2. Backup success is not restore success
  3. Before you start: do not restore over production
  4. The restore drill map
  5. Step 1: Choose a realistic failure scenario
  6. Step 2: Inventory what must be restored
  7. Step 3: Confirm the last usable backup
  8. Step 4: Create an isolated restore target
  9. Step 5: Restore Docker Compose files and configuration
  10. Step 6: Restore Docker application data
  11. Step 7: Restore database data and verify records
  12. Step 8: Restore a VM to a new test ID
  13. Step 9: Boot the restored VM safely
  14. Step 10: Test the restored services like a user
  15. Step 11: Record restore time, data loss and problems
  16. Step 12: Fix the backup plan and repeat the drill
  17. Pass/fail checklist
  18. Common restore failures
  19. Monthly and quarterly schedule
  20. Frequently asked questions

What this restore drill proves

This drill is not just “can I copy files back?”

It proves whether your backup process contains everything needed to recover a working service.

A good home server backup restore drill should prove these things:

  • the backup destination is reachable;
  • the backup files are not empty or corrupt;
  • the encryption key or password is available;
  • Docker Compose files were included;
  • .env files and secrets were not forgotten;
  • application data exists where expected;
  • database dumps can be imported;
  • container permissions still work after restore;
  • reverse proxy configuration can be rebuilt;
  • VM backups can boot;
  • restored VMs do not conflict with production IP addresses;
  • monitoring tells you when something is still broken;
  • you know how long recovery actually takes.

That last point matters more than people think.

“I have backups” is vague.

“I can restore Uptime Kuma from last night’s backup in 18 minutes, and I know the restored database contains yesterday’s monitors” is useful.


Backup success is not restore success

A backup job can succeed while the restore still fails.

Common examples:

  • the script backed up the Compose file but not the data folder;
  • the backup copied a database directory while the database was running and produced inconsistent files;
  • the archive exists, but the encryption password is in the password manager that was inside the failed VM;
  • the VM backup restores, but the restored VM boots with the same IP address as production;
  • the Docker volume exists, but nobody knows which container used it;
  • the reverse proxy config is missing, so the app works locally but not through the normal URL;
  • file ownership changed during restore and the container cannot write to its own data folder;
  • the backup destination was full two months ago and the “success” email was never checked.

This is why a restore drill is different from looking at a green checkmark.

The backup job tells you that something ran. The restore drill tells you whether recovery is possible.


Before you start: do not restore over production

The first rule of a restore drill is simple:

Do not test by restoring over the live service.

That sounds obvious until someone is tired, the folder names look similar, and the backup path is one tab completion away from the production path.

Use a separate restore target:

  • a temporary folder such as /srv/restore-test;
  • a spare Docker host;
  • a test VM;
  • a disconnected lab network;
  • a new Proxmox VM ID;
  • a temporary DNS name;
  • a local-only URL.

For Docker, never restore directly into the live stack folder during a drill:

/srv/docker/app-name/

Use something clearly separate:

/srv/restore-test/app-name/

For Proxmox, do not restore a VM backup over the original VM unless you are really recovering from a failure. During a drill, restore to a new VM ID and keep the network disconnected or isolated until you know what will happen.

A restore drill should not become the outage.


The restore drill map

This is the drill in one view:

1. Choose a failure scenario
   ↓
2. Inventory Docker stacks, VMs, data paths and secrets
   ↓
3. Confirm the newest usable backup
   ↓
4. Restore into an isolated test location
   ↓
5. Restore Docker Compose files and app data
   ↓
6. Restore databases and verify records
   ↓
7. Restore a VM to a new ID
   ↓
8. Boot safely without network conflicts
   ↓
9. Test like a real user
   ↓
10. Record time, data loss and broken steps
   ↓
11. Fix the backup process
   ↓
12. Repeat on a schedule

The goal is not to make the drill complicated.

The goal is to make recovery boring.


Step 1: Choose a realistic failure scenario

Do not start with “restore everything”.

That sounds thorough, but it often becomes too big and never happens.

Start with one realistic scenario:

  • the server SSD died;
  • a Docker volume was deleted;
  • a bad update broke a container;
  • a VM disk was corrupted;
  • a configuration folder was accidentally overwritten;
  • a database was damaged;
  • the reverse proxy configuration was lost;
  • the Proxmox host is fine, but one VM needs to be restored;
  • the whole host is gone and you need to rebuild on different hardware.

For a first drill, I like this scenario:

The home server still exists, but one Docker application and one VM must be restored from backup into a test environment.

That is realistic and small enough to finish.

Write the scenario down:

Restore drill scenario:
The Docker app data folder was deleted and one VM needs to be restored to a new test VM.
No production data may be overwritten.
The restored services must be tested from another machine.

That short note keeps the drill focused.


Step 2: Inventory what must be restored

Before restoring anything, list what the service actually needs.

For Docker services, I use a simple inventory like this:

Item Example Backed up? Restore note
Stack folder /srv/docker/uptime-kuma Yes / No Contains Compose file and data
Compose file compose.yml Yes / No Needed to recreate containers
Environment file .env Yes / No May contain local settings or secrets
Application data ./data Yes / No Must restore before starting container
Named volume app_db_data Yes / No Need volume export or database dump
Database dump app-postgres.sql.gz Yes / No Test import, not just file existence
Reverse proxy route Caddyfile Yes / No Needed for normal URL access
DNS name app.home.arpa Yes / No Document local DNS or hosts entry

For VMs, use a second inventory:

Item Example Backed up? Restore note
VM ID 101 Yes / No Restore drill should use a new ID
VM name debian-docker-01 Yes / No Rename restored test VM clearly
Backup archive vzdump-qemu-101-... Yes / No Confirm date and storage
Network vmbr0 Yes / No Disconnect or isolate before boot
Static IP 192.168.1.50 Yes / No Avoid conflict with production VM
Services SSH, Docker, DNS, app Yes / No Verify after boot
Credentials Password manager / SSH key Yes / No Must be accessible during disaster

This inventory is where many restore problems are found before the restore even starts.

If you cannot describe what needs to be restored, you do not have a recovery plan yet.


Step 3: Confirm the last usable backup

Now find the backup you plan to use.

Do not simply pick the newest file and trust it.

Check:

  • backup date and time;
  • backup size;
  • backup destination;
  • backup log;
  • whether the backup completed or only started;
  • whether the backup is encrypted;
  • whether you have the password or key;
  • whether the backup includes both config and data;
  • whether database dumps are present if required.

Example:

ls -lh /mnt/backup/homeserver/docker/
ls -lh /mnt/backup/homeserver/vms/

For a Docker stack backup, I want to see something like this:

compose.yml
.env
RESTORE.md
data/
database-dump.sql.gz
backup-log.txt

For a Proxmox VM backup, I want to see the VM archive and know which VM it belongs to.

Write down the backup age:

Backup used for drill:
Service: Uptime Kuma
Backup timestamp: 2026-08-16 02:00
Restore started: 2026-08-16 10:14
Potential data loss: about 8 hours

This is your practical RPO.

RPO means recovery point objective. In normal language: how much data could you lose?

If the last good backup is from 8 hours ago, you might lose up to 8 hours of changes.


Step 4: Create an isolated restore target

Create a restore test folder:

sudo mkdir -p /srv/restore-test
sudo chown -R "$USER:$USER" /srv/restore-test
cd /srv/restore-test

For a Docker app, create a folder named after the app:

mkdir -p uptime-kuma-restore
cd uptime-kuma-restore

Do not use the production folder.

Good:

/srv/restore-test/uptime-kuma-restore/

Bad during a drill:

/srv/docker/uptime-kuma/

If you are restoring on the same Docker host, also avoid publishing the same ports or using the same reverse proxy names as production. A restore drill does not need to be reachable from the internet.

For VM testing, create a new VM ID range for drills.

Example:

Production VM IDs: 100-199
Restore test VM IDs: 900-999

That simple habit avoids confusion.


Step 5: Restore Docker Compose files and configuration

Restore the Compose files and configuration first.

Example using rsync:

rsync -aAX --info=progress2 \
  /mnt/backup/homeserver/docker/uptime-kuma/ \
  /srv/restore-test/uptime-kuma-restore/

Then inspect what was restored:

cd /srv/restore-test/uptime-kuma-restore
ls -la

You want to see the files that define the service:

compose.yml
.env
data/
RESTORE.md

If .env is missing, do not ignore it.

A missing .env file might mean:

  • the backup intentionally excluded secrets;
  • the backup script forgot hidden files;
  • the restore needs values from a password manager;
  • the stack will start with wrong defaults;
  • the service will fail in a way that looks unrelated.

Check the Compose file before starting anything:

docker compose -f compose.yml config

If the restored stack would publish the same ports as production, edit it for the drill.

For example, change this:

ports:
  - "3001:3001"

to something temporary:

ports:
  - "127.0.0.1:13001:3001"

Or better, test behind a temporary reverse proxy route on a private network.

The point is to avoid accidentally exposing or conflicting with the live service.


Step 6: Restore Docker application data

Docker restore testing depends on how the data is stored.

There are two common patterns:

  • bind mounts, where data lives in a visible host folder;
  • named volumes, where Docker manages the storage location.

Restore bind-mounted data

Bind mounts are easy to understand because the files live in a normal folder.

Example Compose snippet:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    volumes:
      - ./data:/app/data

In that case, the application data should be inside:

/srv/restore-test/uptime-kuma-restore/data/

Check ownership:

ls -la
ls -la data

Then start the restored test stack:

docker compose -f compose.yml up -d
docker compose -f compose.yml ps
docker compose -f compose.yml logs --tail=100

If the container starts and immediately fails, check permissions first.

Permission problems after restore are boring, common and easy to mistake for application bugs.

Restore a named Docker volume

Named volumes are clean for some services, but you need a restore method.

Example volume:

volumes:
  app_data:

services:
  app:
    image: example/app
    volumes:
      - app_data:/data

If the backup is a tar archive of the volume, restore it to a new test volume:

docker volume create restore_app_data

docker run --rm \
  -v restore_app_data:/volume \
  -v /mnt/backup/homeserver/docker:/backup:ro \
  alpine sh -c "cd /volume && tar xzf /backup/app_data.tar.gz"

Then make the test Compose file use the restored test volume:

volumes:
  app_data:
    external: true
    name: restore_app_data

Start the test stack:

docker compose -f compose.yml up -d
docker compose -f compose.yml ps

The exact commands will depend on how you back up named volumes. The important part is that the drill restores to a new volume, not the production volume.

Do not confuse images with application data

A Docker image can be pulled again.

Your data usually cannot.

For most homelab services, the valuable part is not the container image. It is the data mounted into the container.

That means a restore drill should focus on:

  • data folders;
  • named volumes;
  • database dumps;
  • config files;
  • secrets;
  • service-specific export files.

If your backup only contains images, it is probably not enough.


Step 7: Restore database data and verify records

Databases deserve special attention.

Copying a live database data directory is not always the same as having a clean database backup. For important services, I prefer a database dump as part of the backup routine, or a backup tool that understands the database.

For PostgreSQL, a simple dump might look like this:

docker exec -t app-db pg_dump -U app app | gzip > app-postgres.sql.gz

A test restore might look like this:

gunzip -c app-postgres.sql.gz | docker exec -i restored-db psql -U app app

For MariaDB or MySQL, a dump might look like this:

docker exec app-db mariadb-dump -u app -p app | gzip > app-mariadb.sql.gz

Adjust database names, usernames and commands for your application.

After restoring the database, do not stop at “import completed”.

Open the application and verify real data:

  • Can you log in?
  • Are users present?
  • Are records present?
  • Are uploaded files present?
  • Are timestamps realistic?
  • Do background jobs start?
  • Does the application write new data?

For example, if this is Uptime Kuma, check that monitors exist, notification settings are present, and the status page is still there.

If this is Paperless, check documents, tags, correspondents and the ability to open files.

If this is Gitea, check repositories, issues, users and SSH/HTTP access.

If this is Home Assistant, check integrations, dashboards and automations.

A database restore that imports but leaves the app unusable is not a successful restore.


Step 8: Restore a VM to a new test ID

Now test a VM backup.

This section uses Proxmox-style examples because it is common in homelabs, but the same principle applies to other virtualization platforms.

During a drill, restore to a new VM ID.

Example:

Original VM ID: 101
Restore test VM ID: 901

Never restore over the original VM just to test a backup.

Example Proxmox restore command:

qmrestore /mnt/backup/dump/vzdump-qemu-101-2026_08_16-02_00_00.vma.zst 901 --storage local-lvm

Adjust the file name and storage for your environment.

If you are restoring a container instead of a VM, the command pattern is different:

pct restore 901 /mnt/backup/dump/vzdump-lxc-101-2026_08_16-02_00_00.tar.zst --storage local-lvm

You can also do this from the Proxmox web interface, which is often safer if you are not sure about the command-line options.

After the restore, rename the test VM clearly.

Example:

restore-test-debian-docker-901

I like obvious names. They prevent stupid mistakes.


Step 9: Boot the restored VM safely

Do not immediately boot a restored VM onto the same live network as the original.

Why?

Because the restored VM may have:

  • the same hostname;
  • the same static IP address;
  • the same SSH host keys;
  • the same application secrets;
  • the same scheduled jobs;
  • the same DNS registration;
  • the same backup jobs;
  • the same monitoring agents.

That can create a mess.

Safer options:

  • disconnect the virtual NIC before first boot;
  • attach the VM to an isolated test bridge;
  • use a test VLAN;
  • boot with no network, then change the IP;
  • disable scheduled jobs before connecting it to a network;
  • use the Proxmox console for initial checks.

After boot, check the basics from the console:

hostname
ip addr
df -h
systemctl --failed
journalctl -p err -n 50

If the VM is a Docker host, check Docker:

docker ps
docker compose ls

If it runs system services, check them:

systemctl status ssh
systemctl status docker

Only connect the restored VM to a real network after you understand what it will do.


Step 10: Test the restored services like a user

A restore is not complete when the container says “running” or the VM says “started”.

Test like a user.

For a Docker web application:

  • open the restored URL;
  • log in;
  • check old data;
  • create a test item;
  • upload a test file if the app supports uploads;
  • check background jobs;
  • check logs;
  • check reverse proxy routing;
  • check whether the app can write to its data folder.

For a restored VM:

  • boot successfully;
  • log in through console or SSH;
  • check disk space;
  • check failed services;
  • check application data;
  • check network settings;
  • check firewall rules;
  • check scheduled jobs;
  • check whether monitoring sees it.

For a reverse proxy:

  • confirm the route exists;
  • check TLS or internal TLS;
  • check upstream service name and port;
  • check that the app is not accidentally published directly;
  • check logs for repeated failures.

If you use Uptime Kuma, add a temporary monitor for the restored service.

This is a useful test because it checks the service from the outside, not just from the server itself.

For a monitoring-focused setup, see Uptime Kuma for Home Servers.


Step 11: Record restore time, data loss and problems

Now write down what happened.

This does not need to be fancy.

Create a simple file:

nano RESTORE-DRILL-2026-08-16.md

Use this template:

# Restore drill notes

Date:
Tester:
Scenario:

## Backup used

Service:
Backup location:
Backup timestamp:
Backup size:
Encrypted: yes/no
Password/key available: yes/no

## Restore target

Host:
Folder:
VM ID:
Network:

## Results

Restore started:
Restore finished:
Total restore time:
Backup age:
Estimated data loss:

## What worked

-

## What failed

-

## Manual fixes required

-

## Missing from backup

-

## Changes to make

-

## Next drill date

-

This gives you two practical measurements.

RTO: how long recovery took

RTO means recovery time objective.

In normal language: how long until the service is usable again?

Example:

Restore started: 10:14
Service usable: 10:47
RTO observed: 33 minutes

RPO: how much data you could lose

RPO means recovery point objective.

In normal language: how old was the backup?

Example:

Backup timestamp: 02:00
Failure simulated: 10:14
Potential data loss: 8 hours 14 minutes

These two numbers are more useful than a vague feeling that “backups are fine”.


Step 12: Fix the backup plan and repeat the drill

The best part of a restore drill is not when everything works.

The best part is when something fails in a safe test and you fix it before a real disaster.

Common fixes after a drill:

  • include hidden files such as .env;
  • add database dumps instead of only copying data folders;
  • document named volumes;
  • back up reverse proxy configuration;
  • store encryption keys outside the server;
  • write a real RESTORE.md file;
  • add backup job monitoring;
  • add off-site or offline backup copies;
  • stop backing up temporary cache folders;
  • fix file ownership after restore;
  • change VM restore procedure to avoid IP conflicts;
  • test a different service next time.

After fixing the process, schedule the next restore drill.

Not “sometime”.

A real date.

Next restore drill:
2026-11-15
Target:
Restore one Docker app and one Proxmox VM.

The goal is not to become paranoid.

The goal is to stop relying on hope.


Example Docker restore drill: Uptime Kuma

Here is a small example using Uptime Kuma because it is a good test service. It has real data, a web UI and monitoring configuration, but it is usually small enough to restore quickly.

Production folder:

/srv/docker/uptime-kuma/

Backup folder:

/mnt/backup/homeserver/docker/uptime-kuma/

Restore test folder:

/srv/restore-test/uptime-kuma-restore/

Restore:

sudo mkdir -p /srv/restore-test/uptime-kuma-restore
sudo chown -R "$USER:$USER" /srv/restore-test/uptime-kuma-restore

rsync -aAX --info=progress2 \
  /mnt/backup/homeserver/docker/uptime-kuma/ \
  /srv/restore-test/uptime-kuma-restore/

Inspect:

cd /srv/restore-test/uptime-kuma-restore
ls -la
docker compose -f compose.yml config

Start:

docker compose -f compose.yml up -d
docker compose -f compose.yml ps
docker compose -f compose.yml logs --tail=100

Verify:

  • Can you open the Uptime Kuma UI?
  • Can you log in?
  • Are monitors present?
  • Are notification settings present?
  • Are status pages present?
  • Can you create a temporary monitor?
  • Does the container restart cleanly?

Restart test:

docker compose -f compose.yml restart
docker compose -f compose.yml ps

Stop and clean up after the drill:

docker compose -f compose.yml down

Only delete the restore folder after you have written the drill notes.


Example VM restore drill: Proxmox VM

Here is a basic Proxmox-style VM restore drill.

Scenario:

Original VM ID: 101
Restore test VM ID: 901
Backup archive: /mnt/backup/dump/vzdump-qemu-101-2026_08_16-02_00_00.vma.zst

Restore to a new VM ID:

qmrestore /mnt/backup/dump/vzdump-qemu-101-2026_08_16-02_00_00.vma.zst 901 --storage local-lvm

Before booting, check the restored VM configuration in the Proxmox GUI.

Pay attention to:

  • network adapter;
  • bridge;
  • disk location;
  • boot order;
  • memory;
  • CPU;
  • guest agent;
  • description or notes.

Rename it clearly:

restore-test-vm-901

Boot it safely using console access first.

Inside the restored VM, check:

hostname
ip addr
df -h
systemctl --failed
journalctl -p err -n 50

If this VM runs Docker:

docker ps
docker compose ls

If it has a static IP, change it before connecting to the production LAN.

If it runs scheduled jobs, disable anything that might write to production systems, send emails, sync files, update DNS or run backups under the same identity as the real VM.

The restored VM should prove that the backup boots and the data is usable.

It should not become a second production server by accident.


Pass/fail checklist for the restore drill

Use this checklist at the end.

Check Pass condition Result
Backup found Backup file or folder exists and has the expected timestamp Pass / Fail
Backup readable Archive can be listed, mounted or copied Pass / Fail
Encryption key available Password or key is accessible without the failed server Pass / Fail
Compose file restored docker compose config works Pass / Fail
Environment restored .env or replacement values are available Pass / Fail
Docker data restored Bind mounts or volumes contain expected files Pass / Fail
Database restored Application shows real records after restore Pass / Fail
Container starts Service stays running after restart Pass / Fail
Application login works Valid user can log in Pass / Fail
Write test works Application can create or update test data Pass / Fail
VM restores VM backup restores to a new ID Pass / Fail
VM boots OS reaches login prompt without critical errors Pass / Fail
No network conflict Restored VM does not collide with production IP or hostname Pass / Fail
Restore notes complete Steps, timings and fixes are documented Pass / Fail

If everything passes, good.

If something fails, even better: you found the problem on a normal day instead of during a real failure.


Common restore failures I would expect

Hidden files were not backed up

This is common with .env files.

A backup command that misses hidden files can restore a stack that looks complete but fails because variables are missing.

Database files were copied while the database was running

Some apps survive this. Some do not.

For important databases, use proper database dumps or a backup method designed for that database.

The backup has data but no restore instructions

This is the classic “future me will remember” mistake.

Future you will not remember. Write RESTORE.md.

The restored VM boots with the same IP

This can break DNS, confuse clients and make troubleshooting painful.

Boot restored VMs isolated first.

Secrets are only stored on the failed server

If the encryption key, SSH key or password manager is only available inside the system that died, the backup may be useless.

The backup destination is always mounted read-write

A permanently connected backup can be damaged by mistakes, malware or ransomware.

For important data, keep at least one copy offline, off-site or otherwise protected from the main server.

Nobody noticed backups stopped running

Backups need monitoring.

At minimum, a failed backup should produce an alert you actually see.

A quiet failure is the worst kind.


Monthly and quarterly backup restore schedule

For a small homelab, I would keep the schedule simple.

Monthly quick check

  • Check backup job logs.
  • Confirm newest backup timestamp.
  • Check backup destination free space.
  • List one archive or backup folder.
  • Open the restore notes.
  • Confirm the encryption key is still accessible.

Example commands:

df -h
ls -lh /mnt/backup/homeserver/
tail -n 100 /var/log/homeserver-backup.log

Quarterly restore drill

  • Restore one Docker service.
  • Restore one database dump or volume.
  • Restore one VM or LXC container to a new ID.
  • Measure restore time.
  • Record data loss window.
  • Fix one thing that failed or annoyed you.

Yearly disaster drill

  • Pretend the main server died.
  • Restore to different hardware or a fresh VM host.
  • Use only documented steps.
  • Check whether you can recover without the original server.
  • Update the whole recovery plan.

Do not make the schedule so ambitious that you ignore it.

A small restore test that actually happens beats a perfect disaster recovery plan that nobody runs.


Where this fits in the homelab security stack

This restore drill sits after the basic security work.

The order I would use is:

  1. Harden SSH.
  2. Configure UFW.
  3. Understand Docker published ports.
  4. Build a clean Docker Compose stack.
  5. Set up monitoring.
  6. Back up Docker data and VM backups.
  7. Run this restore drill.

Related guides:

Update the Docker Compose starter stack URL above if you used a different final slug.


Frequently asked questions

How often should I test home server backups?

For a small home server, test at least one restore every quarter. Do a quick monthly backup check, then a deeper restore drill every few months. If the server stores important documents, photos, password vaults or business data, test more often.

Is checking that backup files exist enough?

No. A file existing only proves that a file exists. It does not prove that the archive is readable, the password works, the data is complete, the database imports, the VM boots or the application is usable.

Should I restore Docker containers or Docker data?

Usually, restore the Compose file and the data. Containers are normally recreated from images. The important part is persistent data: bind mounts, named volumes, database dumps, configuration files and secrets.

Should I back up Docker named volumes or use bind mounts?

Both can work. Bind mounts are easier to see and copy because the data lives in normal host folders. Named volumes are cleaner for some Docker workflows, but you need a clear export and restore method. The important thing is not the storage style; it is whether you can restore it.

Can I test a restore on the same server?

Yes, if you use a clearly separate folder, separate ports, separate Docker volume names and do not overwrite production data. For VMs, restore to a new VM ID and isolate the network before booting.

What is the most common Docker restore mistake?

Restoring the Compose file but not the data. The stack starts, but it behaves like a fresh install because the bind mount, named volume or database dump was missing.

What is the most common VM restore mistake?

Booting the restored VM on the same network as production without changing the IP address or hostname. That can create conflicts and confusing symptoms.

Do I need Proxmox Backup Server?

No, but it can be useful if you run Proxmox seriously. A small homelab can also use Proxmox VE backups to local storage, NAS or external disks. The restore drill matters regardless of the backup tool.

What should I monitor after a backup restore?

Monitor whether the restored service is reachable, whether the application can write data, whether logs show errors, whether disks are filling, whether scheduled jobs run, and whether users can access the service through the normal path.

What is a successful restore drill?

A successful restore drill proves that you can recover a service into a test environment, access real data, measure restore time, identify the data loss window and document the process well enough to repeat it later.


Official references


Final thoughts

A backup restore drill is not exciting.

That is exactly why it is valuable.

The exciting version of backup testing is discovering during a real failure that your archive is corrupt, your .env file was never copied, your database dump is empty, your VM boots with the wrong IP, and the only person who knew the encryption password is you from six months ago.

I prefer the boring version.

Pick one Docker service. Restore it. Log in. Check the data. Pick one VM. Restore it to a new ID. Boot it safely. Write down the time. Fix the gaps.

That is how a home server backup becomes more than a green checkmark.

A backup is a file. A restore drill is proof.

Written by MS. MS is a Linux homelab and cybersecurity enthusiast who documents practical experiments with home servers, Docker, firewalls, backups, monitoring, honeypots and old hardware. The guides on IT Random Stuff are based on hands-on testing, real configurations and lessons learned from running Linux systems at home.

Comments

Popular posts from this blog

OpenCanary Honeypot on Ubuntu: 2026 Home Lab Setup Guide

I first wrote about OpenCanary years ago, and that old version badly needed an update. The tool is still useful, but the way I would deploy it in a home lab today is different: newer Ubuntu versions, Python 3, Docker as an option, cleaner logging, and no copy-pasted example credentials that look like something someone might actually reuse. This guide is the updated version: how I would set up an OpenCanary honeypot on Ubuntu in 2026 for a small home network or homelab. The goal is not to trap random people on the internet. The goal is to create a quiet internal warning system: a fake service that should never be touched, so any connection to it deserves attention. Important: this is a defensive security guide. Run OpenCanary only on systems and networks you own or have permission to monitor. Do not expose a honeypot to the public internet unless you understand the logging, legal, abuse and maintenance implications. If you are building a Linux home server security setup fro...

Lenovo ThinkPad X250 on Linux: Tweaks, Undervolting, Battery Life and 2026 Update

I wanted a cheap, small, serviceable Linux laptop. Something light enough to carry, easy enough to repair, and inexpensive enough that upgrades would still make sense. The Lenovo ThinkPad X250 was a good candidate because it has a 12.5-inch form factor, a proper ThinkPad keyboard, SSD upgrade options, replaceable parts, Ethernet, docking support and generally good Linux compatibility. I found one on eBay for around 130€ : an Intel Core i5-5300U model with 8GB RAM , a 128GB SSD , two batteries and an HD screen with a small bruise. The plan was simple: clean it, repaste it, upgrade the SSD, install Linux Mint, undervolt it and see how useful it could still be. This post started as my original 2019 notes about tweaking the Lenovo X250 in Linux. I have now updated it with a 2026 perspective, cleaner instructions, better internal links and a more realistic look at whether this old ThinkPad is still worth using. Related posts: Linux Home Server Security Checklist Docker Secu...

Reverse Proxy for Home Servers: Caddy vs Nginx vs Traefik

Most home servers do not start with a reverse proxy. They start with one service on one port. Then another one appears. Then Uptime Kuma is on :3001 , a dashboard is on :8080 , something else wants :9443 , and before long the router has more port forwards than I am comfortable admitting. That is the point where a reverse proxy stops being a nice extra and becomes part of the basic plumbing. A reverse proxy gives you one clean front door for web services on a home server. It listens on normal web ports, handles HTTPS, receives requests for names like uptime.example.com or photos.example.com , and forwards each request to the right container or local service behind the scenes. Last updated: June 2026 This is not an enterprise load-balancer guide. It is a practical homelab comparison of Caddy , Nginx Proxy Manager and Traefik for Linux home servers, Docker hosts, old workstations, mini PCs and self-hosted services that should be reachable without exposing chaos. If you are ...