Analysis
How to Restore Home Assistant YAML Without Losing Live Changes
A Home Assistant YAML restore can be perfectly valid and still erase newer automations. The safe procedure is to treat the live file and the repository copy as two competing states: compare their contents, preserve both, build the intended result forward from live, validate it, and only then restart.

I caught this on September 12, 2026 while adding a local Qwen3 assistant. The AI configuration worked. The more useful lesson was that a restore tool can be technically correct and still restore the wrong point in time.
In this article
Why a configuration snapshot may not be authoritative
My Home Assistant role describes its own model plainly: Home Assistant is the source of truth; the repository is a read-only mirror plus disaster recovery. The routine synchronization runs from live /config into home-assistant/config. It does not continuously push Git back into the house.
That distinction is easy to forget because the repository also contains a separate restore.yml. The restore playbook accepts one relative filename, checks that it exists in the snapshot, copies the complete file to /config with Ansible’s backup option enabled, and can restart Home Assistant afterward.
The tool was doing exactly what its name promised. The dangerous assumption was mine: I had not proved that the snapshot was newer than the live file.
Start by proving that the two files represent the same intent
| File | Repository snapshot | Live Home Assistant | What a blind restore would do |
|---|---|---|---|
configuration.yaml |
Still contained an http: block |
HTTP settings had moved to the UI-backed .storage/http state on August 10 |
Resurrect an obsolete configuration block |
scripts.yaml |
826 lines | 1,038 lines | Replace the live file and lose roughly 212 lines |
Neither problem was a YAML syntax error. The old files could be perfectly valid YAML and still be the wrong files for the current system. That is why validation belongs after the content comparison, not instead of it.
Compare the files without hiding YAML indentation
My Windows snapshot used CRLF and the live file used LF. GNU diff can ignore the trailing carriage return without ignoring indentation. This is a text comparison, not a YAML parser or a check of what Home Assistant has loaded.
Export a fresh copy of the live file using your existing authorized access. Save the following as compare-ha-yaml.sh on a private workstation with Bash and GNU diff, then run bash compare-ha-yaml.sh live.yaml candidate.yaml. The first argument is the live copy; the second is the proposed replacement. Paths with spaces must be quoted. Neither source file is modified.
#!/usr/bin/env bash
set -eu
if [ "$#" -ne 2 ] || [ ! -f "$1" ] || [ ! -f "$2" ]; then
printf 'Usage: bash compare-ha-yaml.sh LIVE_COPY CANDIDATE\n' >&2
exit 2
fi
umask 077
review_dir=$(mktemp -d)
status=0
diff --strip-trailing-cr -u -- "$1" "$2" > "$review_dir/changes.diff" || status=$?
printf 'Private comparison: %s/changes.diff\n' "$review_dir"
case "$status" in
0) printf 'No differences after CRLF normalization.\n' ;;
1) printf 'Differences found. Review every hunk before proceeding.\n' ;;
*) printf 'Comparison failed; do not treat the report as complete.\n' >&2 ;;
esac
exit "$status"
Exit 1 means different files, not a failed comparison; exit 2 or another error means stop and investigate. In the report, minus lines belong to the live copy and plus lines to the candidate. Do not add -w to hide whitespace: that can conceal a meaningful indentation change.
The report can contain passwords and other configuration secrets. Keep it out of public tickets, shared terminal logs, and Git. The temporary directory is intentionally retained for review; remove that exact directory through your normal file-management process when finished. Re-export before applying if anybody has edited Home Assistant since you captured the live copy.
Build the desired file forward from live state
If live contains changes you want, start with that copy and add the intended change. Do not choose the repository just because its history is cleaner. Review the resulting candidate against the same live baseline, including referenced files and integrations.
My original transfer used sudo tee over SSH. That writes directly to the destination and can leave a truncated file if interrupted; two successful transfers also do not form one atomic change. I would not reuse those commands as a general deployment recipe.
Before replacing a file, preserve its current contents and verify that live still matches the reviewed baseline. Pause competing edits. A same-filesystem atomic replacement can prevent readers seeing a partially copied file, but it does not make several files atomic or prevent another writer from overwriting the result. Preserve the required ownership and permissions, and use a deployment method appropriate to your installation.
Create the rollback artifact before the write
The live files were copied to timestamped rollback names before the write: configuration.yaml.bak-20260912-220058 and scripts.yaml.bak-20260912-220058. Those local copies are excluded from the repository snapshot because they can contain old plaintext configuration and would create a second secret-handling problem.
A timestamped file beside the live configuration is useful for a small immediate rollback. It is not a complete Home Assistant backup. It omits UI-managed state, integration credentials, add-on data, media, and everything else outside those two files.
Home Assistant’s official backup documentation describes full and partial encrypted backups and recommends keeping another copy outside the Home Assistant device. That is the recovery path for a failed system or migration. My Git snapshot has a narrower job: inspectable YAML history and a controlled one-file recovery source.
ha core check is necessary, but it cannot detect stale intent
For my Home Assistant OS installation, after writing both candidates and before restarting, I ran:
ha core check
Run this in a terminal that provides the Home Assistant OS CLI. It checks the installed configuration, not an arbitrary candidate on your workstation. If validation fails, do not restart: correct the candidate or restore the pre-write files, then check again. This command is not a generic Docker-host command.
The check passed. Home Assistant’s official Operating System documentation says the CLI check validates YAML, configuration structure, and additional configuration elements before a restart. I then restarted Core and verified the new Ollama entities and availability path.
That success proves the candidate was acceptable to Home Assistant. A clean check says nothing about stale repository state or whether every existing script still behaves the same way. The line-count and content diff answered a different question from the configuration validator.
A safe Home Assistant YAML restore sequence
- Pull the live target. Do not assume the repository won the most recent edit.
- Compare content after normalizing only known transport noise. On this workstation that meant CRLF versus LF.
- Explain every meaningful difference. A block can be valid, old, and dangerous at the same time.
- Build the candidate from the authoritative side. For this change, that was live Home Assistant plus the reviewed additions.
- Recheck the live baseline. Stop if it changed after review; merging against an old copy can erase another edit.
- Create a recoverable pre-write checkpoint. Know the exact file and command needed to reverse the change.
- Validate before restarting. Run
ha core check; do not use the restart as the syntax test. - Verify the feature and its neighbors. I checked the Ollama entities, availability gate, and script path rather than accepting “Core restarted” as the finish line.
- Refresh the snapshot afterward. Disaster recovery should capture the new known-good state, not preserve the near-miss forever.
Do not automate stale state into authority
I could declare the repository authoritative and force every Home Assistant edit through Git. That would make drift easier to reason about, but it would ignore the way this installation actually changes. Some settings live in the UI and .storage. Scripts can be edited in Home Assistant. Integrations migrate configuration between YAML and UI-backed state. A workflow that pretends those paths do not exist will eventually overwrite one of them.
The better improvement is to make direction explicit. Routine jobs may pull a sanitized snapshot. Restore jobs are exceptional, name one file, preserve the destination, and require a fresh comparison. If I later automate that comparison, it should fail closed when the live hash differs from the reviewed base.
Keep the recovery paths separate
Git is useful for reviewing YAML changes. A saved copy of one file supports an immediate reversal. A full Home Assistant backup covers a different failure: losing the installation and its UI-managed state. Keep an off-device backup and its recovery information as well as the narrow pre-write checkpoint.
What the example changed
The official Home Assistant documentation supports the current behavior of configuration validation and built-in backups. Product-specific claims about my snapshot and restore path come from the repository source and change record.