Version Control HA Config with GitHub, Not Snapshots

You can secure your Home Assistant config by pushing your YAML files to a private GitHub repo on a daily schedule. This gives your smart home version control. You can see what changed between the last working state and the broken one, roll back a single file in seconds, and rebuild a fresh HA install from a repo clone. It is faster and far more useful than the built-in snapshot backup for config-level problems.
Key Takeaways
- A Git-backed config gives you diffs, single-file rollbacks, and a clean rebuild path that snapshots cannot.
- The
.gitignoreis the critical step:secrets.yaml,.storage/, and the history database must never be committed. - HA OS users get a one-click backup with the Git Exporter add-on; Docker users wire up a cron script.
- A scoped fine-grained GitHub token limits the damage if the token ever leaks.
- Run Git for fast config recovery and snapshots for hardware failure; the two strategies cover every case.
Why Version Control Your Home Assistant Config?
Home Assistant ships with a built-in backup system. It creates full .tar snapshots of the whole install: add-ons, database, media, and all. Those snapshots are vital for full-system recovery. If a drive fails or you move to new hardware, a snapshot gets you back to where you were. But they have real drawbacks when all you need to do is fix a broken config.
A full HA snapshot can run from 1 GB to 10 GB, depending on how much media and database history you have built up. Restoring one means downloading that archive, uploading it through the HA web UI, and waiting through a full restore cycle. If the problem was one changed line in automations.yaml, that is a sledgehammer. You cannot open a snapshot file and read a diff. You cannot restore just one file. You cannot easily answer the question “what changed since this stopped working?”
A Git-backed config repo solves all of these problems. Every automatic commit captures a diff of your whole config directory. When your motion-triggered lights stop working after a late-night edit, git log shows every change from the last 24 hours. git diff HEAD~1 shows the exact lines modified. git checkout HEAD~1 -- automations.yaml restores only that file to its prior state. You are back up in seconds without touching your running system.
This is the GitOps idea applied to the smart home: your home’s behavior should be fully reproducible from a single Git repo on a fresh HA install. The database, media files, and add-on data are throwaway state. Your YAML config is the source of truth.
The two approaches work well together. Use Git for fast, file-level config recovery. Use HA’s snapshot backup (or the Backup integration) for full-system recovery when hardware fails.
What to Include (and Exclude) in the Backup
Getting the .gitignore right is the most important security step in this setup. Committing the wrong file to a GitHub repo, even a private one, can expose passwords, auth tokens, and device MAC addresses.
Files to track in Git:
configuration.yaml: the root config fileautomations.yaml,scripts.yaml,scenes.yaml,groups.yaml: all hand-edited automation filesui-lovelace.yaml: if you use YAML mode for your dashboard rather than the GUI editorcustom_components/: any custom integrations you installed by handthemes/: custom dashboard themeswww/: custom frontend files (images, cards). Use Git LFS if this folder holds large binaries.
Files to exclude from Git (security-critical):
secrets.yaml: holds every password, API key, and token your config references with!secret. Never commit it..storage/: HA’s internal storage directory with auth tokens, user credentials, and device registriesknown_devices.yaml: MAC addresses of every tracked device, a privacy leakhome-assistant_v2.db: the SQLite history database. It is large, binary, and full of personal location and sensor data..cloud/: Nabu Casa credentials
Here is a complete .gitignore file you can copy directly into your HA config directory:
# Sensitive credentials - never commit these
secrets.yaml
known_devices.yaml
# HA internal state storage (tokens, user accounts, device reg)
.storage/
.cloud/
# Database and logs
home-assistant_v2.db
home-assistant_v2.db-shm
home-assistant_v2.db-wal
*.log
OZW_Log.txt
# Backup archives
*.tar
backups/
# Add-on and supervisor state (HA OS only)
deps/
tts/
.uuid
.HA_VERSION
# Python cache
__pycache__/
*.pyc
# Editor junk
.DS_Store
Thumbs.dbHandling secrets.yaml correctly: HA’s !secret syntax lets you swap any sensitive value in your config files for a named reference. For example, api_key: !secret my_weather_api_key in configuration.yaml reads the real key from secrets.yaml at runtime. So your committed config files stay clean, readable, and shareable. The secrets file never needs to leave your local machine. Keep an encrypted copy of secrets.yaml in a password manager such as Bitwarden
or 1Password, and restore it by hand when rebuilding on new hardware.
If you want a more automated path, Bitwarden Secrets Manager
ships a CLI that can build secrets.yaml from a vault at deploy time. This is the most robust option if you run several HA instances or want a fully automated restore pipeline.
Setting Up the GitHub Private Repository
Start by creating a new private repository on GitHub. Log in, click the “+” menu in the top right, and select “New repository.” Name it something clear like homeassistant-config, set it to Private, and leave it empty. Do not add a README, because you will push an existing directory.
Next, generate a Personal Access Token (PAT) for the backup process to authenticate with. Go to GitHub → Settings → Developer Settings → Personal Access Tokens. In 2026, prefer Fine-grained personal access tokens over classic tokens, since they can be scoped to a single repo. Set these permissions on the token:
- Repository access: Only the
homeassistant-configrepository - Permissions: Contents, Read and Write
This follows the principle of least privilege. A token that can only write to one repo does little damage if it ever leaks. Do not generate a classic token with repo scope across all repositories.
Copy the token right away, since GitHub shows it only once. Store it in your password manager next to your secrets.yaml backup.
Now add the token to HA’s secrets system so your config files can reference it without hardcoding it. Open HA’s Settings → System → Edit Secrets and add a line:
github_token: ghp_yourTokenHereThen reference it in your configuration.yaml as !secret github_token wherever needed.
The Home Assistant Git Exporter Add-on
If you run Home Assistant OS or Home Assistant Supervised, the easiest path is the Git Exporter add-on in the HA Add-on Store . Search for “Git Exporter” in the add-on store and install it.
The add-on configuration is straightforward. In its settings panel, provide:
repository: "https://github.com/USERNAME/homeassistant-config.git"
branch: "main"
username: "your-github-username"
password: "ghp_yourTokenHere"
commit_name: "Home Assistant"
commit_email: "ha@yourdomain.com"
time: "03:00"The time field schedules the daily backup run. Setting it to 03:00 means the commit happens at 3 AM local time, well outside your active hours. The add-on stages all tracked files, creates a commit with a timestamp message, and pushes to GitHub. On first run, it also sets up the repo and handles the initial commit.
After saving the config, click Start and then Open Web UI to trigger a manual run. Check your GitHub repo within a minute. You should see your first commit appear with your config files listed. If the push fails, check the add-on logs for auth errors. The most common cause is a malformed token.
Manual Git Setup for Home Assistant Container Users
If you run HA as a plain Docker container, without the HA OS supervisor layer, you do not have the add-on store. This setup needs SSH access to the Docker host and a few manual steps.
SSH into the host machine and go to your HA config directory. It is usually mounted at something like /home/user/.homeassistant/, or wherever you mapped it in your docker-compose.yml:
cd /home/user/.homeassistant/Set up the Git repo, add your remote, and create the .gitignore file from the template above:
git init
git remote add origin https://github.com/USERNAME/homeassistant-config.git
git branch -M mainCreate and populate .gitignore, then make your initial commit:
git add -A
git commit -m "Initial config backup"
git push -u origin mainWhen prompted for auth, use your GitHub username and the PAT token as the password. To skip the prompt on every push, set up the credential helper:
git config credential.helper storeThis stores the credentials in a plaintext file at ~/.git-credentials. On a private server that is fine. On a shared machine, use an SSH deploy key instead.
Now create the backup script. Save this as /home/user/backup_ha_config.sh:
#!/bin/bash
HA_CONFIG_DIR="/home/user/.homeassistant"
LOG_TAG="ha-git-backup"
cd "$HA_CONFIG_DIR" || { logger -t "$LOG_TAG" "ERROR: Cannot cd to $HA_CONFIG_DIR"; exit 1; }
# Stage all changes
git add -A
# Only commit if there are staged changes
if git diff --cached --quiet; then
logger -t "$LOG_TAG" "No changes to commit."
exit 0
fi
COMMIT_MSG="Auto backup $(date '+%Y-%m-%d %H:%M:%S')"
git commit -m "$COMMIT_MSG"
if git push origin main; then
logger -t "$LOG_TAG" "Successfully pushed: $COMMIT_MSG"
else
logger -t "$LOG_TAG" "ERROR: Push failed"
exit 1
fiMake the script executable and set up cron to run it nightly:
chmod +x /home/user/backup_ha_config.sh
crontab -eAdd this line to the crontab, which runs the script at 3 AM every night and appends output to a log file:
0 3 * * * /home/user/backup_ha_config.sh >> /var/log/ha_backup.log 2>&1You can also trigger the backup on demand from within HA itself. Add the shell_command integration to configuration.yaml:
shell_command:
backup_config: "/home/user/backup_ha_config.sh"Then create a script or button helper in HA that calls shell_command.backup_config. This gives you a “Backup Now” button in the UI to press before any big config change.
Handling Large Files with Git LFS
If your www/ or custom_components/ directories hold large binary files, such as compiled JavaScript bundles for custom Lovelace cards, font files, or large images, standard Git will struggle. GitHub has a 100 MB hard limit per file and starts warning above 50 MB.
Git Large File Storage (LFS) solves this. It swaps large files in the repo for small pointers and stores the real file content on a separate LFS server. Install it on your host and set up tracking for large binary types:
git lfs install
git lfs track "*.woff2"
git lfs track "*.js.map"
git lfs track "www/**/*.png"
git add .gitattributesNote that GitHub’s free tier includes 1 GB of LFS storage and 1 GB of monthly bandwidth. For most HA configs this is plenty, but keep it in mind if your www/ folder is unusually large.
Self-Hosted Alternative: Gitea
If you want zero cloud dependency, you can replace GitHub with a self-hosted Gitea instance on your local network or a private VPS. Gitea is a lightweight, open-source Git server written in Go. It offers a GitHub-compatible API and web interface.
The setup is the same as the GitHub workflow above. Replace the remote URL with your Gitea instance:
git remote add origin https://gitea.yourdomain.com/USERNAME/homeassistant-config.gitGitea personal access tokens work just like GitHub PATs. For home lab users with a self-hosted server, Gitea is the ideal pick: no data ever leaves your network, there are no rate limits, and you keep full control over the backup server itself.
Restoring from a GitHub Backup
A backup is only as good as its restore process. Run through this at least once on a spare device or VM before you need it for real.
Scenario 1: Restoring a single broken file after a bad edit.
You changed something in automations.yaml and HA is throwing errors. Find the last good commit and restore just that file:
git log --oneline automations.yaml
# Find the commit hash before things broke, e.g. a3f7c12
git checkout a3f7c12 -- automations.yamlThis restores automations.yaml to its state at that commit without touching anything else. Then go to HA’s Developer Tools → YAML → Check Configuration to validate it before you restart.
Scenario 2: Full disaster recovery on a fresh HA OS installation.
- Install HA OS on the new machine and complete the onboarding wizard minimally.
- Enable the SSH add-on from the Add-on Store (it may be in the “Advanced” section).
- SSH in and clone your repository:
cd /config
git clone https://github.com/USERNAME/homeassistant-config.git .- Recreate
secrets.yamlfrom your password manager backup. This file is not in Git, so you must restore it by hand. - Run the HA config check via Developer Tools, then restart Home Assistant.
Your whole config, automations, scripts, scenes, dashboards, and custom components, is restored in minutes. What is not restored is your history database (sensor logs, entity history) and any add-on data. Those come from the full snapshot backup. That is why running both strategies in parallel is the safest approach.
Secrets Management Best Practices
The most dangerous mistake in this workflow is committing secrets.yaml by accident. It can happen a few ways: a misplaced wildcard in .gitignore, a git add -A that picks up a new file, a copy of secrets.yaml under a slightly different name. The fallout is severe. GitHub scans all public repos for leaked credentials, but private repos get no such protection.
Add a pre-commit hook to catch leaks before they happen. Install git-secrets and register your token patterns:
git secrets --install
git secrets --register-aws # catches AWS-format keys
git secrets --add 'ghp_[0-9a-zA-Z]{36}' # catches GitHub PATsYou can also use trufflehog to scan your whole commit history for leaked credentials. Run it once after the initial setup to confirm nothing sensitive slipped through.
For token rotation: if a GitHub PAT is ever committed by accident, revoke it right away in GitHub → Settings → Developer Settings → Personal Access Tokens, generate a new token, and update your HA secrets editor and password manager. Do this before anything else. A revoked token is harmless. An active token in a repo, even a private one, is a live risk.
Finally, apply the two-person rule to your secrets backup. Make sure at least one other trusted person, a family member or a close colleague, has a secure copy of your secrets.yaml or knows how to get it from your password manager. If you are incapacitated and your smart home needs to be restored or handed over, a secrets file locked behind a forgotten master password defeats the whole backup strategy.
Putting It All Together
The full setup takes about 30 minutes for HA OS users with the Git Exporter add-on, or an hour for Docker container users wiring up the manual git workflow. Once running, it works silently in the background. Every morning you have a fresh commit in your private repo that captures what your home automation config looked like the night before.
Paired with HA’s native snapshot backup for full-system recovery, this two-tier strategy covers every failure case. A broken automation is fixed with a git checkout in seconds. A dead drive is recovered from a snapshot in minutes. Your config is documented, diff-able, and version-controlled: the same discipline that makes production software reliable, now applied to your home.
Botmonster Tech