- hass.windy.lan is a physical x88 Pro box (HAOS bare-metal, machine: green, CPE x88pro20, virtualization empty) — not PVE VM 180 (verified live 2026-08-18) - Record CSG v1.3.2 (934f58c, W1N-118) deploy in maintenance runbook verify section and hosts live-tree section (backups now include w1n118)
17 KiB
Runbook: Home Assistant maintenance (hass.windy.lan)
Target: hass.windy.lan (physical x88 Pro box, HAOS machine: green)
Upstream: HAOS 18.1 / Core 2026.8.1 / Supervisor 2026.07.5 (verified 2026-08-14)
This runbook covers routine Home Assistant maintenance through the ha
supervisor CLI. All commands are wrapped by a single script
scripts/ha-maintenance.sh; the sections below
document the exact commands it runs, for manual/agent use.
Purpose
Run routine Home Assistant maintenance on hass.windy.lan (health snapshot,
config validation, log inspection, updates, and recovery) through the ha
supervisor CLI.
Scope
Applies to hass.windy.lan only (HAOS, machine: green). Covers both
read-only checks and gated mutating operations; the "Command families
intentionally NOT scripted" table below lists what is deliberately out of
scope.
Ownership
- Owner: personal ops (Windy)
- Last reviewed: 2026-08-17
- Related systems: hass.windy.lan (HAOS,
machine: green)
Safety
- Prefer read-only checks first; the health snapshot mutates nothing.
- Every mutating mode (update / restart / rebuild / rollback / reboot /
backup / restore / add-on lifecycle) refuses to run without
--yes. --restoreoverwrites the current installation;--rollback-os,--reboot, and--rebuild-coreare disruptive. Run them only from a planned recovery with the backup verified.- Never commit
SUPERVISOR_TOKENor a long-livedHA_TOKEN; read entity state via Supervisor (SUPERVISOR_TOKENaftersudo -n -i). - The
--restart-corewrapper exits 1 silently on ssh failure — treat an empty/exit-1 result as failure and confirm withha core info. - If live state conflicts with a documented expectation,
STOPand report; do not improvise command families outside this script.
Access pattern
ha authenticates to the Supervisor with SUPERVISOR_TOKEN. Interactive SSH
login works because ~hassio/.zprofile runs exec sudo -i; the root login
environment carries the token. Non-interactive use must be:
ssh -o BatchMode=yes hassio@hass.windy.lan 'sudo -n -i ha <cmd>'
Running ha as hassio directly (or sudo -n without -i) returns
unauthorized: missing or invalid API token.
MOTD: every sudo -n -i login prints the SSH & Web Terminal MOTD banner.
The script runs its whole procedure in one remote login (sudo -n -i bash -s)
so the banner appears once, then strips it with awk up to the
System is ready! Use browser or app to configure. line.
Restart wrapper (verified 2026-08-14, W1N-107):
./ha-maintenance.sh --restart-core --yes exited 1 with no output in <1s
and did not restart Core. The wrapper pipes a remote script through
ssh … 2>/dev/null | awk …; with set -uo pipefail, an ssh failure is
silent and the pipeline returns empty/exit 1 before any remote command
runs. That is not a MOTD-strip artifact after a successful restart.
The working restart was
ssh -o BatchMode=yes hassio@hass.windy.lan 'sudo -n -i ha core restart'
(~131s, Command completed successfully.). Treat empty/exit 1 as
failure; confirm with elapsed time and ha core info.
Script usage
cd runbooks/scripts
./ha-maintenance.sh # read-only health snapshot
./ha-maintenance.sh --check-config # validate core configuration
./ha-maintenance.sh --logs core 2500 # tail core logs (use 2500 after a restart)
./ha-maintenance.sh --logs supervisor # tail supervisor logs (default 100)
./ha-maintenance.sh --logs host 50 # tail host journald logs
./ha-maintenance.sh --logs apps:<slug> # tail an add-on log
# Mutating — refuse to run without --yes:
./ha-maintenance.sh --update --yes # refresh + update core(--backup)/supervisor/os
./ha-maintenance.sh --restart-core --yes # restart Core
./ha-maintenance.sh --restart-core --safe-mode --yes # restart Core in safe mode
./ha-maintenance.sh --rebuild-core --yes # rebuild Core image (after options change)
./ha-maintenance.sh --rollback-os --yes # boot previous OS slot (A/B rollback)
./ha-maintenance.sh --reboot --yes # reboot the HAOS host
./ha-maintenance.sh --backup [NAME] --yes # full backup (optionally named)
./ha-maintenance.sh --restore <slug> --yes # restore a backup (DESTRUCTIVE)
./ha-maintenance.sh --app restart core_mosquitto --yes # add-on lifecycle
--appaction is one ofstart|stop|restart|update; needs an add-on slug.HA_HOST/HA_SSH_USERoverride the defaults (hass.windy.lan/hassio).--restoreoverwrites the current installation — run only from a planned recovery, with the backup verified.
Command reference (verified 2026-08-14)
All verified against the live host. MOTD prepends each command's output; strip
with the awk pattern above or read the last block.
Routine / read-only
| Purpose | Command |
|---|---|
| General overview | ha info |
| Core version/status | ha core info (this CLI build has no state: field; success is a normal info dump) |
| Core config validation | ha core check |
| Core stats | ha core stats |
| Supervisor status | ha supervisor info (incl. add-on list) |
| Supervisor stats | ha supervisor stats |
| OS status | ha os info (boot slots A/B) |
| Host status | ha host info (disk free/total, kernel) |
| Network | ha network info (supervisor_internet) |
| Hardware | ha hardware info |
| Pending updates | ha available-updates |
| Reload stores/versions | ha refresh-updates |
| Job manager | ha jobs info |
| Resolution center | ha resolution info |
| Core logs | ha core logs -n 100 (-f follow, -b boot id). Default 100 misses setup; use -n 2500 after a custom-component restart. /config/home-assistant.log may be missing — ha core logs is the source of truth. |
| Supervisor logs | ha supervisor logs -n 100 |
| Host journald logs | ha host logs -n 100 |
| Add-on logs | ha apps logs <slug> -n 100 |
| Add-on list | ha supervisor info → addons: (started/stopped/error) |
| Security integrity | ha security integrity |
Mutating (require --yes)
| Purpose | Command |
|---|---|
| Update core (with partial backup) | ha core update --backup |
| Update supervisor | ha supervisor update |
| Update OS | ha os update |
| Update add-on | ha apps update <slug> |
| Restart core | ha core restart / ha core restart --safe-mode |
| Rebuild core | ha core rebuild |
| OS rollback | ha os boot-slot other |
| Reboot host | ha host reboot |
| Full backup | ha backups new [--name NAME] |
| Restore backup | ha backups restore <slug> |
| Add-on start/stop/restart | ha apps start|stop|restart <slug> |
Procedure
1. Health snapshot (read-only)
./ha-maintenance.sh
Review: supervisor healthy: true/supported: true; core/OS update_available;
add-on states (any state: error?); resolution info issues; disk free.
2. Validate config after any configuration.yaml change
./ha-maintenance.sh --check-config
Expect Command completed successfully. before a Core restart.
ha core check / a YAML reload is not enough after copying Python
custom-component files — restart Core.
3. Inspect logs
./ha-maintenance.sh --logs core 2500 # after a Core restart / custom-component copy
./ha-maintenance.sh --logs supervisor
./ha-maintenance.sh --logs apps:core_mosquitto
Default --logs core (100 lines) is too short to catch coordinator pickle /
setup errors. /config/home-assistant.log may be absent while
ha core logs still has history.
4. Apply updates (mutating)
./ha-maintenance.sh --update --yes
Runs refresh-updates → core update --backup (partial backup first) →
supervisor update → os update, then re-prints pending updates. Prefer the
web UI (Settings → System → Updates) for a human-supervised pass.
5. Recovery operations (mutating, only when needed)
./ha-maintenance.sh --restart-core --safe-mode --yes # start Core without custom integrations
./ha-maintenance.sh --rollback-os --yes # OS update broke boot? go back one slot
./ha-maintenance.sh --restore <slug> --yes # full restore; overwrites current install
OS update policy: HAOS uses two boot slots (A/B); ha os info shows which slot
booted. After a bad OS update, ha os boot-slot other boots the previous slot.
6. Backup before major changes
./ha-maintenance.sh --backup pre-migration --yes # named backup
7. Install or update a custom component (manual zip)
Home Assistant loads custom integrations from
/config/custom_components/<domain>/ (on this HAOS host /config ≡
/homeassistant). Official lookup:
<config>/custom_components/<domain> then built-in
homeassistant/components/<domain>
(Integration file structure).
A folder named after the domain, with at least manifest.json and
__init__.py, is enough. Restart Core after copying — ha core check
and a YAML reload do not pick up new Python packages.
This host's live trees are file copies, not git clones. Do not
git pull inside custom_components/.
Official plugin paths (CSG)
windyboy/china_southern_power_grid_stat README: HACS or 手动下载安装.
This host uses the zip path. Do not HACS-update this integration here.
HACS still tracks upstream CubicPill/china_southern_power_grid_stat
v1.2.0 and would overwrite the fork. Releases have no uploaded zip
assets — use GitHub Source code (zip) / zipball of the tag.
Worked SSH example (tag, backup, rsync, __pycache__, restart):
hosts/hass.windy.lan.md § Manual
custom-component install.
Procedure
- Backup the live tree off
custom_components/. HA scans every directory undercustom_components/whosemanifest.jsondomainmatches. A*.bak-*folder next to the live tree makes Core import the backup (No module named '...bak-YYYYMMDD-...', W1N-106). CSG backups:/homeassistant/.csg-backups/. - Copy only the inner
custom_components/<domain>/tree, not the repo root and not an extra nested folder. - Wipe
__pycache__as root.rsync --deleteashassiocannot unlink Core-owned.pyc(permission denied, exit 23); stalecpython-314bytecode can keep the old coordinator in memory until restart. Then restart:
ssh -o BatchMode=yes hassio@hass.windy.lan \
'sudo -n -i rm -rf /homeassistant/custom_components/<domain>/__pycache__ \
/homeassistant/custom_components/<domain>/*/__pycache__ &&
sudo -n -i ha core restart'
- Wait 1–2 min, then
ha core info(this CLI build has nostate:field; success is a normal info dump). Confirmmanifest.jsonversionmatches the tag. - Read enough Core logs. Default
ha core logsis too short to catch setup. Use-n 2500(or--logs core 2500) and look forSetting up <domain>plus the first coordinator errors. - First poll can time out. If last-month sensors have numbers but
this-month stay
unknown/unavailable, reload the config entry (UI: integration → Reload). Supervisor:
# entry id from .storage/core.config_entries (CSG: 01KGCQDSZCF523A9X6SV3BZ1B9)
ssh -o BatchMode=yes hassio@hass.windy.lan \
'sudo -n -i python3 -c "
import os, urllib.request
req = urllib.request.Request(
\"http://supervisor/core/api/config/config_entries/entry/<ENTRY_ID>/reload\",
method=\"POST\",
headers={\"Authorization\": \"Bearer \" + os.environ[\"SUPERVISOR_TOKEN\"]},
)
print(urllib.request.urlopen(req, timeout=60).status)
"'
- Do not edit the dashboard or
templates/csg_sensors.yamlfor an install. Entity IDs did not change across v1.3.0/v1.3.1/v1.3.2. Template| float(0)turns nativeunavailableinto fake zeros; that is a follow-up, not part of the zip install.
Verify (CSG, after v1.3.2 / W1N-118)
| Check | Expect |
|---|---|
manifest.json version |
1.3.2 |
ha core logs after this restart |
Setting up china_southern_power_grid_stat; no cannot pickle 'mappingproxy' |
| Config entry | state: loaded |
sensor.0800041935246530_balance |
numeric (may be 0.0) |
sensor.0800041935246530_this_month_total_usage |
numeric after reload if first poll timed out |
Native *_total_cost / current_ladder |
may stay unknown (CSG marketing calendar SQL error); dashboard uses W1N-114 csg_* ladder/cost templates |
monetary + total_increasing warnings on this-month/year cost sensors
are a remaining plugin issue, not an install failure.
There is no long-lived HA_TOKEN in the agent environment. Read entity
states via Supervisor (SUPERVISOR_TOKEN after sudo -n -i) at
http://supervisor/core/api/states/<entity_id>.
Command families intentionally NOT scripted
These exist in ha but are either rare, dangerous, or better done in the web
UI; documented here so nothing is a surprise. Use ha <family> --help on the
host for exact syntax.
| Family | Notes |
|---|---|
ha audio |
Audio device management; peripheral. |
ha authentication |
auth list/reset/cache; user password ops — do in web UI. auth list is local-terminal only. |
ha cli |
Internal CLI backend info/update; self-maintained. |
ha dns |
Internal DNS server; only relevant if Supervisor DNS add-on in use. |
ha docker |
Host Docker backend info/options/registries; HAOS-managed. |
ha mounts |
Network storage (NFS/CIFS) mounts — configure in Settings → System → Storage. |
ha multicast / ha observer |
Internal services; self-maintained. |
ha network scan/update/vlan |
WiFi AP scan & interface config — prefer web UI networking. |
ha host disks/options/shutdown/reload |
Disk ops / host options; shutdown is equivalent to --reboot but off. |
ha os datadisk list/move/wipe |
Data-disk migration; wipe is local-terminal only and erases all data. |
ha os import |
Import config from USB stick. |
ha os boards / os config |
Board / OS settings. |
ha core options / supervisor options |
Core/OS config options (e.g. --duplicate-log-file); changes need ha core rebuild + restart. |
ha backups freeze/thaw/remove/options |
Freeze/thaw for external backup tools; removal is destructive. |
ha jobs options/reset |
Job-manager tuning. |
ha resolution check/healthcheck/issue/suggestion |
Resolution center management; healthcheck runs fixups. |
ha store add/delete/repair |
Repository management — add repos in web UI app store. |
ha security info/options |
Security backend options. |
Docs vs actual CLI discrepancies
The official HAOS common-tasks docs
also mention ha host update, which does not exist in this CLI
(2026-08-14). Docs' ha backups list is not a subcommand either:
ha backups --help lists freeze/info/new/options/reload/remove/restore/thaw;
extra positional args (list, nonsense, ...) are ignored and the default
list still prints with exit 0. The list command is plain ha backups.
Per-backup: ha backups info <slug> (slug required). Trust the server CLI
(ha <cmd> --help) over the docs.
This CLI's ha core info also has no state: field (verified 2026-08-14).
Wait for a successful info dump after restart, not a state: running line.
Known issues on hass.windy.lan (2026-08-14)
2026-08-13 snapshot items were resolved same day (W1N-70/71/72/73/74/75/76):
OTBR and the duplicate SSH add-on uninstalled, resolution-center empty,
full backup pre-maintenance-20260813 (slug 411a4ba5). Remaining:
- Bluetooth hci0 instability (RTL8821CS):
bluetooth_auto_recoverypower-reset times out every ~2 min; kernelhci0 hardware error. No BLE entities exist, so no user impact. HAOS image shipsx88-bt-hci-recoveryworkaround units. host inforeportsdisk_life_time: 10(boot eMMC ~10% life left) — monitor on each snapshot; plan disk replacement / data-disk migration.- Home PPPoE IPv4 to CSG is blackholed (
curl -4to218.19.148.218:443times out).end1IPv6 works (curl -6 https://95598.csg.cn→ HTTP 200). Entryip_family: ipv4still matches the stored option; first post-restart poll can still time out — reload the config entry rather than reinstalling. - WSL HTTP proxy: LAN
hass.windy.lan:8123through Mihomo returns empty502. Bypass proxy or add.windy.lantoNO_PROXYbefore debugging UI/API from the workstation (hosts/hass.windy.lan.md § HTTP proxy gotcha). - No long-lived HA token in the agent environment. Read entity
states via Supervisor (
SUPERVISOR_TOKENaftersudo -n -i) athttp://supervisor/core/api/states/..., not a committedHA_TOKEN.
Pass criteria
- Health snapshot completes; supervisor
healthy/supported: true - Mutating modes refuse to run without
--yes(incl.--restore,--app) --check-configreturns success- Update / rollback / restore / reboot confirmed only after explicit
--yes - Custom-component zip install: live
manifest.jsonversion matches the tag; backups not undercustom_components/; Core restarted; logs showSetting up <domain>without import / pickle errors - Update the Verified line on hosts/hass.windy.lan.md