The most expensive lesson you can learn with Home Assistant usually doesn’t come from a hardware failure — it comes from discovering, mid-emergency, that a backup you assumed was good isn’t actually restorable. A backup strategy needs to be deliberate, not an afterthought bolted on after a scare.
This post covers a strategy worth running: the retention numbers, a realistic test cadence, and the gaps most setups still leave open.
What you’re protecting against
Three failure modes, roughly in order of how often they happen:
- You broke something. Most common by far. A bad YAML edit, a wrong service call in a script, a late-night automation tweak that turns out to have been wrong. You want to be able to roll back to “this morning” without thinking about it.
- HA broke something. Less common but real — an integration update changes behavior, a core release deprecates a YAML pattern you were relying on, a database migration goes sideways. You want to be able to roll back to “before the update.”
- The hardware failed. Rare, but SD cards die, NVMe drives die, power supplies die. You want to be able to rebuild on new hardware in under an hour rather than starting from zero.
The strategy has three tiers, one per failure mode. Each tier is independent — losing one doesn’t break the others.
Tier 1: HA’s built-in snapshots, every day
HA’s built-in backup mechanism (Settings → System → Backups) creates a .tar.gz snapshot containing the config, the database, the secrets, and any installed add-on data. The system can be restored from a snapshot in about 5 minutes if it’s still booting; longer if you have to set up a fresh OS first.
Set up an automation that creates a snapshot every morning and keeps a rolling week’s worth:
automation:
- id: 'daily_backup'
alias: 'Daily HA Backup'
triggers:
- trigger: time
at: "04:00:00"
actions:
- action: backup.create_automatic
- delay: "00:05:00"
- action: notify.mobile_app_your_phone
data:
title: "HA Backup"
message: "Daily snapshot created"
data:
tag: ha-backup
backup.create_automatic is HA’s automation-managed backup action. It applies the retention policy configured under Settings → System → Backups → Configure → Automatic backups — set that to “keep last 7” and every day creates a new snapshot while the eighth-oldest one falls off automatically.
These snapshots live on the HA host’s internal storage. They cover failure mode 1 (you broke something) — within seconds you have access to “what HA looked like yesterday morning” and can restore from there.
Tier 2: Off-host pulls to the NAS, every week
The Tier 1 snapshots are on the same machine as the HA install. If the HA host’s drive fails, those backups go with it. Tier 2 fixes that by pulling them somewhere else — a NAS, a second server, anything with its own storage.
A weekly pull job on a schedule is enough. As an example, a small script that runs rsync against the HA snapshot directory once a week and pulls anything new to bulk storage, with a 12-week retention so you always have the last three months of weekly snapshots even after Tier 1’s rolling window drops them:
#!/usr/bin/env bash
# example: ha-backup-sync.sh
SRC="ha:/config/backups/"
DST="/mnt/user/backups/homeassistant/"
# Pull new snapshots
rsync -av --include='*.tar' --exclude='*' "$SRC" "$DST"
# Trim anything older than 12 weeks
find "$DST" -name '*.tar' -mtime +84 -delete
The ha: host alias would live in ~/.ssh/config, pointing at the HA host with a key that has read-only access to /config/backups/. Schedule the script with cron or whatever job runner your NAS supports.
This tier covers failure mode 2 (HA itself broke something) and gives you a longer history than a seven-day rolling Tier 1 — useful if the breakage happens but isn’t noticed for a couple of weeks.
Tier 3: A cold, offline copy
The first two tiers are both on hot storage that’s always online. If something goes badly wrong with the network — ransomware, a fire, a really bad cascading failure — they could go together. Tier 3 is a cold copy, kept offline and ideally off-site.
Once a month, copy the Tier 2 backup directory to a USB drive and disconnect it. Rotating two physical drives works well: one is always disconnected while the other takes the next copy, so there’s never a moment where both are plugged in. Store the disconnected drive somewhere fire-safe — a fireproof box or safe, or better, a different physical location entirely.
Keep this step manual on purpose. The manual step is the protection — if something can encrypt or wipe backups over the network, it can’t reach a drive that isn’t plugged in. A calendar reminder on the first of the month is enough to keep it from slipping; the swap itself takes a couple of minutes plus however long the copy takes.
The actual retention policy
Putting all three tiers together:
| Tier | Source | Frequency | Retention | Storage |
|---|---|---|---|---|
| 1 | HA snapshot.create | Daily | 7 days | HA host internal |
| 2 | rsync to bulk storage | Weekly | 12 weeks | NAS / second server |
| 3 | USB cold copy | Monthly | Last 2 months | Offline, off-site |
The “last 2 months” on Tier 3 comes from rotating two drives — at any given moment one drive holds last month’s copy and one holds the month before. Each monthly copy overwrites the older drive.
The test cadence (don’t skip this)
A backup you’ve never restored isn’t a backup. The single most valuable habit in any backup strategy is a regular restore drill — quarterly is a reasonable cadence to start with.
The drill itself is simple:
- Spin up a fresh Home Assistant VM just for testing, separate from production
- Restore the most recent Tier 2 snapshot to that VM
- Boot it, confirm it loads the config, check that a few entities show their last-known state
- Tear the VM down
This catches three things that aren’t visible from “the snapshot file exists”:
- Snapshot corruption. A snapshot can be incomplete because HA was mid-write to the database when the backup ran — the file is there but the restore fails partway through. Exercising the restore path is the only way to catch this before it matters.
- Compatibility drift. If production is running a newer HA core than the snapshot, will it restore cleanly? Usually, but breaking changes happen. A drill catches “this snapshot is too old to restore directly” before it’s an emergency.
- Process drift. The restore steps change between HA versions. Running the drill keeps the process familiar, so the first time you do a real restore isn’t also the first time you’ve seen the restore screen.
A real example: cleaning up backup bloat
In September 2026, a check turned up 20 accumulated backups totalling 4.63 GiB on the HA VM. I deleted the 14 oldest, kept the newest 6, and freed 2.76 GiB — then grew the HA VM’s virtual disk from 32 GiB to 64 GiB so retention has more headroom before it needs pruning again. Worth checking your own backup directory occasionally; automatic retention policies don’t always account for how much space snapshots actually take once add-on data and the database grow.
A few practices worth adopting regardless of what your own incident history looks like:
- Name backups deliberately. Auto-generated daily backups already have a clear timestamp. Anything created manually should get a name describing why (
pre-update-2026-04-22, etc.), so the list in the restore UI is never ambiguous. - Never restore directly to production for a non-emergency rollback. Restore to a test VM first, confirm the state is what’s wanted, then either copy specific files back or do a full restore.
- Keep configs in git, separately from the snapshot. Automations, scripts, packages, and
configuration.yamlliving in a git repo means the config can be rebuilt even if every snapshot is lost — the database history would go, but everything else would survive. It also meansgit diffshows exactly what changed today andgit checkoutrolls it back in seconds, which does most of the heavy lifting for the “you broke something” failure mode. The snapshot ends up being mostly insurance for “and the database too.”
Holes worth checking for
Two gaps that are common even in otherwise solid setups:
Off-site cloud backup. A cold local copy is offline, but it’s still in the same building. If the building itself is lost, so is the backup. A small cloud storage bucket holding encrypted Tier 2 snapshots closes that gap for a few dollars a month.
Automated restore testing. A manual quarterly drill is a good start, but it’s easy to let slip. A script that spins up the test VM, restores the most recent snapshot, exercises a few HA service calls to confirm it’s alive, and tears down turns the drill into something that can run on its own schedule — weekly instead of quarterly, with no reminder needed.
If you’re starting from no backups
A reasonable order to tackle this in:
- Today: turn on HA’s built-in automatic backups with a 7-day retention. This is one toggle. Don’t put it off.
- This week: set up an
rsync(or equivalent) pull from the HA host to wherever your bulk storage lives. Schedule it weekly. - This month: do your first restore drill. Do it on a test VM, not production. Confirm it actually works.
- This quarter: figure out an off-host storage strategy (USB rotation, cloud, both) for the case where your home network is compromised.
The temptation when starting is to build the whole stack at once. Don’t. Get Tier 1 working first; live with it for a week; then add Tier 2; live with it for a week; then add Tier 3. Each tier independently is dramatically better than no backups, and the incremental approach keeps you from getting overwhelmed and skipping the whole thing.
The goal isn’t to have the world’s most elaborate backup system. The goal is to be able to sleep through a botched YAML edit and fix it tomorrow morning with a five-minute restore.
Related guides: How I deploy HA config changes · Monitoring the smart home with Uptime Kuma · Node-RED to native HA YAML