← All writing

Three copies of every Home Assistant backup

Home Assistant 2026.11 landed on November 4, and some of the quieter changes are about backups: you can now point backups at a local internal or USB drive, restores no longer make a temporary copy of the whole backup first, and there's a new sensor for the size of the last successful automatic backup. Good timing, because the weekend before, I'd finally sorted out my own Home Assistant backups.

My Home Assistant runs on a Raspberry Pi 3B+ booting from an SD card. It watches the cameras, sends my phone alerts about the home server and now logs my work mileage. SD cards wear out, and until recently the history database was being written to that same card all day. If the card died, I'd lose more than a weekend. So I set out to make sure every backup exists in more than one place, and that losing the Pi would mean a restore, not a rebuild.

What you need

  • Home Assistant OS (the backup locations and network storage below come from the Supervisor)
  • Somewhere on your network that speaks SMB or NFS: a NAS or a home server (I use an unRaid server)
  • Optionally, an off-site copy: Home Assistant Cloud, or any S3-compatible bucket (I use Cloudflare R2)
  • A password manager for the backup encryption key

Turn on automatic, encrypted backups

Under Settings → System → Backups, I set automatic backups to run every day at 3:30 AM. They're full backups: every add-on and the database, not just the config. Home Assistant encrypts them with a backup key it generates. That key is the one thing you can't recover from the backup itself, so it belongs somewhere other than the system you're protecting. Without it, the backup files are just noise.

Three places, three retention rules

Home Assistant can send each backup to several locations at once, and each location keeps its own number of copies. Mine are:

  • The Pi itself, keeping 3. Fast to restore from if I just broke a config, useless if the card dies.
  • A private share on my home server, keeping 14. I added it in Home Assistant as network storage with the usage set to backup. The share has its own account that only Home Assistant uses, so it isn't open to anything else on my network.
  • Home Assistant Cloud, keeping 1. The provider manages it, and it means the latest backup survives even if the house loses both the Pi and the server.

The first run after I set this up was 33 MB, and it arrived in all three places.

An off-site copy with history

One cloud copy is good; a couple of weeks of them is better, in case something has been quietly wrong for a few days before I notice. My home server already runs a nightly off-site sync to Cloudflare R2 for its own important data, so I added a step that copies the newest Home Assistant backup too and keeps 14 days of history. The idea, simplified:

# Nightly, after Home Assistant's backup has landed on the server share
latest=$(ls -t /mnt/user/<ha-backup-share>/*.tar | head -n 1)
rclone copy "$latest" r2:<your-bucket>/homeassistant/
# Keep two weeks off-site
rclone delete --min-age 14d r2:<your-bucket>/homeassistant/

The backups are already encrypted by Home Assistant, so what sits in the bucket is unreadable without the key.

Get the database off the SD card

The biggest source of SD card writes in Home Assistant is the recorder, which saves the history of every sensor. I moved it to a MariaDB container on the home server, with the connection string kept in secrets.yaml and 90 days of history:

# configuration.yaml
recorder:
  db_url: !secret recorder_db_url
  purge_keep_days: 90

The database gets its own nightly dump and off-site copy. One honest catch: switching databases starts history over. Before I switched, I exported the mileage history I cared about to a CSV so nothing I'd need for a reimbursement form went missing.

Know when it fails

A backup system that fails quietly is worse than none, because you stop worrying about it. Home Assistant's backup integration has an event entity that fires when an automatic backup completes or fails, so I have an automation that sends my phone an alert when one fails. A minimal version looks like this:

alias: "Backup failed"
triggers:
  - trigger: state
    entity_id: event.backup_automatic_backup
conditions:
  - condition: state
    entity_id: event.backup_automatic_backup
    attribute: event_type
    state: failed
actions:
  - action: notify.mobile_app_<your_phone>
    data:
      title: "Home Assistant backup failed"
      message: "{{ state_attr('event.backup_automatic_backup', 'failed_reason') }}"

On the server side, off-site backup failures show up as server notifications, and those already reach my phone through Home Assistant too. I tested that path, so I know a failed sync will actually get my attention.

The new backup-size sensor in 2026.11 is next on my list. A backup that suddenly shrinks is often a backup that's missing something, and an alert on that is cheap to add.

The restore plan

The point of all this is the restore, so I wrote it down while it was fresh: install Home Assistant OS on the new hardware, choose to restore from a backup during onboarding, upload the newest file from the server share (or from R2 if the server is gone too), and enter the backup key.

I'm about to use it for real. The next step is moving Home Assistant off the Pi and onto a small surplus mini PC by restoring the latest backup, which is the best test a backup can get. That move is still in progress.

What I'd tell you before you set this up

  • Keep the key somewhere else. Encrypted backups without the key are just files.
  • Use more than one location, with different retention. A few local copies for "I broke something", more on the network, at least one off-site.
  • Move the history database off an SD card if you're still running on one.
  • Alert on failures, and test the alert once.
  • Write down the restore steps before you need them, and then actually restore once.