diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 9f103e9..01de06c 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -49,14 +49,14 @@ jobs:
run: bash tests/self_check.sh
addon-lint:
- name: Add-on Lint
+ name: App Lint
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- - name: Home Assistant Add-on Lint
+ - name: Home Assistant App Lint
uses: frenck/action-addon-linter@f995494fd84fae6310d23617e66d0e37de4f14eb # v2.21.0
with:
path: ./gitops_backup
@@ -69,7 +69,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- - name: Build add-on image
+ - name: Build app image
run: |
docker build \
--build-arg BUILD_FROM=ghcr.io/home-assistant/amd64-base:3.21 \
diff --git a/README.md b/README.md
index 35ade6b..3d90af2 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# HA GitOps โ Home Assistant Add-on
+# HA GitOps โ Home Assistant App
**PR-gated GitHub backup for your Home Assistant config.** Nothing force-pushes,
every change is a reviewable pull request, and CI validates your config against
@@ -10,10 +10,10 @@ pinned Home Assistant versions *before* it can merge.
[](https://github.com/askb/ha-gitops/releases)
[](LICENSE)
-## Why another config-backup add-on?
+## Why another config-backup app?
Most config-sync tools upload your files straight onto a branch โ some even
-force-push. That gives you a *copy*, not *control*. This add-on treats your
+force-push. That gives you a *copy*, not *control*. This app treats your
config like production infrastructure:
| | Direct-push sync tools | GitOps Config Backup |
@@ -30,7 +30,7 @@ config like production infrastructure:
flowchart LR
subgraph HA["๐ Home Assistant box"]
CFG[("/config")]
- ADDON["GitOps Backup add-on
two-way sync, every run:
โฌ pull merged โ โฌ push drift"]
+ ADDON["GitOps Backup app
two-way sync, every run:
โฌ pull merged โ โฌ push drift"]
CFG -- "โ local edits
(UI, HA upgrades)" --> ADDON
ADDON -- "โค merged changes
applied to /config" --> CFG
end
@@ -68,8 +68,8 @@ flowchart LR
```
**The loop, numbered:** โ you edit via the HA UI (or an upgrade changes files) โ
-โก the add-on turns that drift into a PR โ or you open a config PR yourself โ
-โข CI gates it, you merge โ โฃ the add-on's next run pulls merged `main` โ
+โก the app turns that drift into a PR โ or you open a config PR yourself โ
+โข CI gates it, you merge โ โฃ the app's next run pulls merged `main` โ
โค and applies it to `/config`. Both directions go through the same run:
it **pulls first, then pushes drift**, so box and repo converge on `main`.
@@ -82,16 +82,16 @@ it **pulls first, then pushes drift**, so box and repo converge on `main`.
a `stable` early-warning leg) **+ a smoke boot** โ the pinned HA Core
container starts with your config and must answer HTTP with no
`Invalid config` โ upgrade breakage surfaces in CI, not on your Pi.
-3. **You merge** (from your phone, if you like). The next add-on run rebases the
+3. **You merge** (from your phone, if you like). The next app run rebases the
merged state back onto the box.
## Install
-1. Add this repository to your Add-on store (badge above), install
+1. Add this repository to your App store (badge above), install
**GitOps Config Backup**.
2. Create a GitHub repo (private recommended) and a fine-grained PAT with
*Contents: read/write* and *Pull requests: read/write* on it.
-3. Configure the add-on:
+3. Configure the app:
```yaml
github_repo: you/your-ha-config
@@ -116,7 +116,7 @@ the initial import; every run after that only ever opens PRs.
## Status sensor (optional)
-The add-on writes `.gitops_backup_status` (`status:detail:extra`) to your config
+The app writes `.gitops_backup_status` (`status:detail:extra`) to your config
dir. Expose it in HA:
```yaml
@@ -146,23 +146,23 @@ ssh root@ 'ha core restart'
| `base_branch` | `main` | Branch PRs target |
| `branch_prefix` | `auto-backup` | Prefix for backup branches |
| `interval_hours` | `24` | Hours between runs (1โ168) |
-| `run_at_start` | `false` | Also run when the add-on starts |
+| `run_at_start` | `false` | Also run when the app starts |
| `dry_run` | `false` | Log what would change; push nothing |
| `commit_name` / `commit_email` | see config | Commit author |
| `signoff` | `true` | Add `Signed-off-by` (DCO) to commits |
## Security notes
-- The token lives in the add-on options (Supervisor-encrypted), never in git.
+- The token lives in the app options (Supervisor-encrypted), never in git.
- The seeded `.gitignore` excludes `secrets.yaml`, `.storage/`, `.cloud/`,
- databases, logs, and the add-on's own status/log files (committing status
+ databases, logs, and the app's own status/log files (committing status
files creates a PR-per-day feedback loop โ learned the hard way).
- CI validates with **stub** secrets; your real `secrets.yaml` never leaves the box.
-- Nothing in this add-on ever force-pushes or writes to your base branch after
+- Nothing in this app ever force-pushes or writes to your base branch after
the initial bootstrap import.
- **This is change tracking, not disaster recovery** โ pair it with HA's
- native encrypted backups + the Google Drive Backup add-on for full system
- state (`secrets.yaml`, `.storage/`, databases, add-ons). See the add-on
+ native encrypted backups + the Google Drive Backup app for full system
+ state (`secrets.yaml`, `.storage/`, databases, apps). See the app
DOCS for the full "what is backed up where" table and where secrets belong.
## License
diff --git a/gitops_backup/CHANGELOG.md b/gitops_backup/CHANGELOG.md
index d73ae9c..fb96a40 100644
--- a/gitops_backup/CHANGELOG.md
+++ b/gitops_backup/CHANGELOG.md
@@ -3,17 +3,17 @@
## 0.3.0
- Feature: `apply_after_pull` โ after a merged PR is pulled into `/config`, the
- add-on now applies it to the running Home Assistant instead of leaving files
+ app now applies it to the running Home Assistant instead of leaving files
on disk unloaded. Default `reload` calls `homeassistant.reload_all` (no
restart); `restart` restarts HA (for `configuration.yaml` integration or
`custom_components/` changes); `off` keeps the previous behaviour. Only fires
when the sync actually advanced `HEAD`, never in `dry_run`. Requires the
- add-on's Home Assistant API access (now enabled via `homeassistant_api`).
+ app's Home Assistant API access (now enabled via `homeassistant_api`).
## 0.2.1
- Security: the never-commit guarantee (secrets, credentials, `.storage/`,
- addon runtime files) now holds for **migrated** repos too, not just fresh
+ app runtime files) now holds for **migrated** repos too, not just fresh
ones. Patterns are enforced via `.git/info/exclude` on every run, and any
secret a prior run already committed is untracked (the removal flows out
through the next backup PR). Previously a repo that arrived with its own
@@ -21,18 +21,18 @@
## 0.2.0
-- Docs: make the two-pillar backup model explicit โ config repo (this add-on)
+- Docs: make the two-pillar backup model explicit โ config repo (this app)
+ encrypted HA full backup (e.g. Google Drive Backup) = 100% restorable;
neither alone is enough. Sharpened the "what is backed up where" table
(names exactly what `.storage/` holds and what lives outside `/config`).
- Security: seed `.gitignore` now also excludes `*.token` / `.google.token`
so OAuth tokens (e.g. Google Calendar) never land in the repo.
-- First bootstrap now logs a disaster-recovery warning: this add-on versions
+- First bootstrap now logs a disaster-recovery warning: this app versions
declarative config only; run HA full backups for a complete restore.
## 0.1.1
-- Fix: keep the addon's own runtime files (`.gitops_backup_status`,
+- Fix: keep the app's own runtime files (`.gitops_backup_status`,
`gitops_backup.log`) out of backups when migrating a repo that already has a
`.gitignore` โ they were previously swept into backup PRs and risked a
status-file PR feedback loop. Now excluded via `.git/info/exclude` on every
diff --git a/gitops_backup/DOCS.md b/gitops_backup/DOCS.md
index 31f14a1..27d12d9 100644
--- a/gitops_backup/DOCS.md
+++ b/gitops_backup/DOCS.md
@@ -13,14 +13,14 @@ PR-gated GitHub backup for your Home Assistant config.
### 1. Create the repository
github.com โ **+** โ **New repository** โ name it (e.g. `my-ha-config`) โ
-**Private** โ Create. Don't add a README โ the add-on bootstraps the content.
+**Private** โ Create. Don't add a README โ the app bootstraps the content.
### 2. Create the token
1. github.com โ your avatar โ **Settings** โ **Developer settings** โ
**Personal access tokens** โ **Fine-grained tokens** โ **Generate new token**
2. **Token name**: `ha-gitops` ยท **Expiration**: 1 year (set a calendar
- reminder โ the add-on status will show `error` when it expires)
+ reminder โ the app status will show `error` when it expires)
3. **Repository access**: *Only select repositories* โ pick the repo from step 1
4. **Permissions โ Repository permissions**:
- **Contents**: Read and write
@@ -31,9 +31,9 @@ github.com โ **+** โ **New repository** โ name it (e.g. `my-ha-config`)
> The token can only touch that single repo. Even if it leaked, your other
> repos and account are untouchable โ that's why fine-grained beats classic PATs.
-### 3. Configure the add-on
+### 3. Configure the app
-Settings โ Add-ons โ GitOps Config Backup โ **Configuration**:
+Settings โ Apps โ GitOps Config Backup โ **Configuration**:
```yaml
github_repo: yourname/my-ha-config
@@ -41,11 +41,11 @@ github_token: github_pat_XXXXXXXX
dry_run: true # first run: log only, push nothing
```
-Start the add-on, then check `gitops_backup.log` in your config folder to see
+Start the app, then check `gitops_backup.log` in your config folder to see
what *would* be committed. Happy? Set `dry_run: false` and restart. The first
real run pushes the initial import; every run after that only opens PRs.
-The token is stored in the add-on options by the Supervisor โ it never goes
+The token is stored in the app options by the Supervisor โ it never goes
into git, and the seeded `.gitignore` keeps `secrets.yaml` and other sensitive
files out of the repo entirely.
@@ -59,30 +59,30 @@ repo โ Settings โ Branches โ require the *HA Config Validation* and
## What is backed up where (best practice)
-This add-on is **change tracking for your config**, not disaster recovery.
+This app is **change tracking for your config**, not disaster recovery.
Run both layers:
-| Data | This add-on (GitHub) | HA Backup + Google Drive |
+| Data | This app (GitHub) | HA Backup + Google Drive |
|------|----------------------|--------------------------|
| Config YAML (automations, dashboards, โฆ) | โ
versioned, reviewable diffs | โ
inside the archive |
| `secrets.yaml` | โ **never** (gitignored) | โ
inside the **encrypted** archive |
| `.storage/` โ UI-added **integrations**, **logins/tokens**, **device/entity/area registries**, **UI (Lovelace) dashboards**, helpers | โ never (holds secrets) | โ
**most restore-critical item** |
| Credentials: `*.token`, `.google.token`, `*.key`, `*.pem`, `.cloud/` | โ never | โ
|
| Databases, history, logs | โ never | โ
(recorder DB, if selected) |
-| Add-on configs/data, TLS certs (`/ssl`) โ live **outside** `/config` | โ add-on can't see them | โ
|
+| App configs/data, TLS certs (`/ssl`) โ live **outside** `/config` | โ app can't see them | โ
|
| Media, camera recordings | โ | usually excluded โ external drive |
> **The 100% guarantee: config repo + encrypted full backup. Neither alone is
> enough.** Restore from the git repo *only* and you'd get your YAML back but
> have to re-do by hand every UI-added integration, all logins/tokens, device
-> and entity names, UI dashboards, `secrets.yaml`, and every add-on โ because
+> and entity names, UI dashboards, `secrets.yaml`, and every app โ because
> those live in `.storage/`, `secrets.yaml`, or outside `/config`. That's why a
> full backup (Pillar 2) is mandatory, not optional.
**Recommended stack:**
```text
-GitHub (this add-on) โ config changes: who/what/when, PR review, CI gate
+GitHub (this app) โ config changes: who/what/when, PR review, CI gate
HA auto backup (daily) โ full system state, encrypted, on the box
โโ Google Drive Backup โ off-site copies of those archives
Password manager โ the three keys to the kingdom (below)
@@ -96,13 +96,13 @@ Password manager โ the three keys to the kingdom (below)
- Store in your **password manager** (never in the repo, never in a README):
1. the HA **backup encryption password** โ without it your off-site backups
are unrestorable,
- 2. the **GitHub PAT** for this add-on,
+ 2. the **GitHub PAT** for this app,
3. your HA admin credentials.
- CI validates PRs with **stub** secrets (step 4) โ real values never leave
the box.
**Disaster recovery order:** reinstall HAOS โ restore the encrypted HA backup
-(brings back `secrets.yaml`, `.storage`, add-ons) โ your config repo is then
+(brings back `secrets.yaml`, `.storage`, apps) โ your config repo is then
already live on the box and git history simply resumes.
## Options
@@ -114,7 +114,7 @@ already live on the box and git history simply resumes.
| `base_branch` | `main` | Branch PRs target |
| `branch_prefix` | `auto-backup` | Prefix for backup branches |
| `interval_hours` | `24` | Hours between runs (1โ168) |
-| `run_at_start` | `false` | Also run when the add-on starts |
+| `run_at_start` | `false` | Also run when the app starts |
| `dry_run` | `false` | Log what would change; push nothing |
| `commit_name` / `commit_email` | see defaults | Commit author identity |
| `signoff` | `true` | Add `Signed-off-by` (DCO) to commits |
@@ -124,7 +124,7 @@ already live on the box and git history simply resumes.
Everything in your config folder **except** the seeded `.gitignore` exclusions:
`secrets.yaml`, `.storage/`, `.cloud/`, databases, logs, `*.token`,
-`.google.token`, `known_devices.yaml`, `ip_bans.yaml`, and the add-on's own
+`.google.token`, `known_devices.yaml`, `ip_bans.yaml`, and the app's own
status/log files.
## Status in Home Assistant
diff --git a/gitops_backup/rootfs/app/gitops_backup.sh b/gitops_backup/rootfs/app/gitops_backup.sh
index 23d39d0..8597350 100755
--- a/gitops_backup/rootfs/app/gitops_backup.sh
+++ b/gitops_backup/rootfs/app/gitops_backup.sh
@@ -107,7 +107,7 @@ OZW_Log.txt
.uuid
.ha_run.lock
-# This addon's runtime metadata (committing it creates a PR feedback loop)
+# This app's runtime metadata (committing it creates a PR feedback loop)
.gitops_backup_status
gitops_backup.log
@@ -121,7 +121,7 @@ EOF
}
never_commit_patterns() {
- # Secrets, credentials, and the addon's own runtime metadata โ must never be
+ # Secrets, credentials, and the app's own runtime metadata โ must never be
# committed. Shared by the exclude writer and the untracker.
cat <<'EOF'
secrets.yaml
@@ -139,7 +139,7 @@ EOF
write_secret_excludes() {
# Write the never-commit patterns to .git/info/exclude (git's local,
- # un-shared ignore) so secrets/credentials + addon metadata stay out of
+ # un-shared ignore) so secrets/credentials + app metadata stay out of
# backups even when migrating a repo that already has its own .gitignore
# (seed_gitignore only writes one for a fresh repo). Called before the stash
# so untracked secrets are never swept in. Idempotent: replace our block.
@@ -177,7 +177,7 @@ bootstrap_if_needed() {
# Returns 0 if bootstrap ran (caller should stop), 1 if repo already exists
if [ -d .git ]; then return 1; fi
log "No git repo in ${CONFIG_DIR} โ bootstrapping"
- log "โ This add-on versions DECLARATIVE config only. It does NOT back up secrets.yaml, .storage/ (UI-configured integrations, logins, device/entity registries, dashboards), the database, or add-on data โ those are excluded on purpose. For a 100% restore you MUST also run HA full backups (e.g. the Google Drive Backup add-on). See this add-on's DOCS โ 'What is backed up where'."
+ log "โ This app versions DECLARATIVE config only. It does NOT back up secrets.yaml, .storage/ (UI-configured integrations, logins, device/entity registries, dashboards), the database, or app data โ those are excluded on purpose. For a 100% restore you MUST also run HA full backups (e.g. the Google Drive Backup app). See this app's DOCS โ 'What is backed up where'."
if [ "$DRY_RUN" = "true" ]; then
seed_gitignore
log "DRY RUN: would git init, commit initial import, push to ${BASE_BRANCH}"
@@ -295,7 +295,7 @@ main() {
local pr_url
if pr_url=$(create_pull_request "$branch_name" \
"chore: auto backup $(date '+%Y-%m-%d %H:%M')" \
- "Automated Home Assistant config backup โ ${changed_count} changed file(s). Opened by the GitOps Config Backup addon; review and merge.") \
+ "Automated Home Assistant config backup โ ${changed_count} changed file(s). Opened by the GitOps Config Backup app; review and merge.") \
&& [ -n "$pr_url" ]; then
write_status success pr_created "$pr_url"
log "โ
Backup complete โ PR opened: ${pr_url}"
diff --git a/gitops_backup/translations/en.yaml b/gitops_backup/translations/en.yaml
index c027398..9fab040 100644
--- a/gitops_backup/translations/en.yaml
+++ b/gitops_backup/translations/en.yaml
@@ -21,7 +21,7 @@ configuration:
description: Hours between backup runs.
run_at_start:
name: Run at start
- description: Also run a backup when the add-on starts.
+ description: Also run a backup when the app starts.
dry_run:
name: Dry run
description: Log what would change without pushing anything.
diff --git a/tests/self_check.sh b/tests/self_check.sh
index 98edb76..4986015 100755
--- a/tests/self_check.sh
+++ b/tests/self_check.sh
@@ -62,14 +62,14 @@ git -c safe.bareRepository=all -C "$TMP/origin.git" branch | grep -q "auto-backu
status | grep -q "warning:branch_pushed" || { echo "FAIL: drift status = $(status)"; exit 1; }
git -C "$TMP/config" branch --show-current | grep -q "^main$" || { echo "FAIL: not back on main"; exit 1; }
-# 4. Migration case: repo already had its own .gitignore lacking the addon's
-# entries, and was never excluded. The addon's own status file + log AND any
+# 4. Migration case: repo already had its own .gitignore lacking the app's
+# entries, and was never excluded. The app's own status file + log AND any
# secrets/credentials must be kept out of the backup โ even an already-
# committed secret must be untracked (regression test for seed_gitignore
# skip-when-.gitignore-exists + secret-leak on migrated repos).
sleep 1 # ensure a distinct auto-backup/ branch name
rm -f "$TMP/config/.git/info/exclude" # never-excluded repo
-printf 'secrets.yaml\n' > "$TMP/config/.gitignore" # user ignore, no addon/token entries
+printf 'secrets.yaml\n' > "$TMP/config/.gitignore" # user ignore, no app/token entries
HOME="$TMP" git -C "$TMP/config" add .gitignore
HOME="$TMP" git -C "$TMP/config" commit -q -m "user gitignore"
echo "success:no_changes:" > "$TMP/config/.gitops_backup_status"
@@ -84,7 +84,7 @@ newbranch=$(git -c safe.bareRepository=all -C "$TMP/origin.git" branch \
| grep -o 'auto-backup/[^ ]*' | tail -1)
tree=$(git -c safe.bareRepository=all -C "$TMP/origin.git" ls-tree -r --name-only "$newbranch")
if echo "$tree" | grep -qE '^\.gitops_backup_status$|^gitops_backup\.log$'; then
- echo "FAIL: addon runtime files committed to backup branch"; exit 1
+ echo "FAIL: app runtime files committed to backup branch"; exit 1
fi
if echo "$tree" | grep -qE '^\.google\.token$|^leaked\.key$|^secrets\.yaml$'; then
echo "FAIL: a secret/credential was committed to the backup branch"; exit 1