feat(ha): cutover ken to 31.7 HAOS, archive legacy container instance

instances.yaml pointed "ken" at the piha container (homeassistant5), a
pre-migration instance that never actually stopped running — it kept
firing automations in parallel with the real home instance (HAOS on a
dedicated RPi4, 192.168.31.7), causing duplicate triggers on shared
buttons/scenes. Repoint ken to the real instance (api adapter),
demote the container to ken-legacy (archived, import-only, never a
deploy target), and log the incident in DESIGN.md.
This commit is contained in:
oskar 2026-07-22 16:17:18 +02:00
parent b2379e3275
commit 77d55caf07
5 changed files with 112 additions and 14 deletions

View file

@ -4,6 +4,33 @@ Centralny tracker tech-długu i znanych usterek. Wpisy ze sesji — dodawaj z da
--- ---
## Cutover HA "ken": kontener piha to legacy, prawdziwy dom to RPi4/HAOS (2026-07-22)
**Data**: 2026-07-22
**Źródło**: recon — dwie instancje HA równolegle sterowały domem (kontener
`homeassistant5` na piha + RPi4 HAOS 192.168.31.7), patrz
`services/home-assistant/DESIGN.md` sekcja "Incident log". `instances.yaml`
naprawiony w tej samej sesji: `ken` = 192.168.31.7 (api), `ken-legacy` =
dawny kontener piha (docker-exec, archived).
**Do zrobienia**:
1. **ha-diag-agent na piha**: przepiąć z `http://localhost:8123` (celuje w
legacy!) na `http://192.168.31.7:8123` — wymaga nowego tokenu
`diag_agent` wystawionego na instancji 31.7 (obecny token jest dla
kontenera piha i nie zadziała na nowym targecie).
2. **Wygaszenie `homeassistant5`**: import archiwalny do
`services/home-assistant/config/ken-legacy/``docker stop` (BEZ `rm`)
→ 7 dni obserwacji (upewnić się, że nic w domu nie polega na tym
kontenerze) → decyzja o `docker rm`.
3. **Adapter `api` w `import.sh` dla `ken`**: obecnie tylko `docker-exec`
jest zaimplementowany (`scripts/ha/import.sh`), a `ken` po cutoverze
używa `api`. Automatyzacje/skrypty/sceny przez
`/api/config/<domain>/config/<id>`, dashboardy przez websocket API.
Pełny import `/config` pozostaje poza zasięgiem (HAOS bez SSH) — patrz
DESIGN.md.
---
## Nowy podprojekt: Home Assistant configs-as-code (szkielet) ## Nowy podprojekt: Home Assistant configs-as-code (szkielet)
**Data**: 2026-07-21 **Data**: 2026-07-21

View file

@ -45,7 +45,8 @@ behind a common interface (`import.sh`/eventual `deploy.sh <instance>`):
| Instance | Adapter | Why | | Instance | Adapter | Why |
|---|---|---| |---|---|---|
| `ken` (piha, container `homeassistant5`) | **docker-exec over SSH** | No HA API port reachable from where imports run today; container filesystem is reachable via `ssh oskar@piha "docker exec homeassistant5 ..."`. See `hosts/piha/README.md`. | | `ken` (RPi4, HAOS, LAN `192.168.31.7:8123`) | **api** | Canonical home instance since the 2026-07-22 cutover (see Incident log). HAOS has no SSH access, so there is no `docker exec`/filesystem path — only the HA REST/websocket API is reachable. Full `/config` import is deferred until an alternative access path exists; for now the api adapter's import scope is limited to what the API exposes: automations, scripts, scenes, dashboards. |
| `ken-legacy` (piha, container `homeassistant5`) | **docker-exec over SSH** (archive-only) | Pre-migration container instance, superseded by `ken` at 31.7 (see Incident log) — same container filesystem access as the old `ken` entry (`ssh oskar@piha "docker exec homeassistant5 ..."`). Import only, for historical reference; never a deploy target. |
| `chelsty-ha` | **api** | Reachable over Tailscale at `100.70.180.90:8123` (confirmed working path — `services/ha-diag-agent/DEPLOY.md` already curls this for health checks). Config-as-code deploy will reuse the same reachability, calling the HA REST/websocket API rather than shelling into the container. | | `chelsty-ha` | **api** | Reachable over Tailscale at `100.70.180.90:8123` (confirmed working path — `services/ha-diag-agent/DEPLOY.md` already curls this for health checks). Config-as-code deploy will reuse the same reachability, calling the HA REST/websocket API rather than shelling into the container. |
**Open**: a `file` adapter (direct bind-mount / SSH `rsync` to the config **Open**: a `file` adapter (direct bind-mount / SSH `rsync` to the config
@ -131,6 +132,37 @@ copied into the repo.
the existing Telegram bot / approval-queue pattern from the existing Telegram bot / approval-queue pattern from
`services/control-plane/`. `services/control-plane/`.
## Incident log
### 2026-07-22 — two HA instances controlling the house in parallel
**Symptom**: automations firing twice from a single physical trigger — e.g.
`turn_on_led_nad_blatem_1` firing the same day from the same button press,
`mirror_on` at 04:30 and `gniazdka_w_lazience_on` at 05:00 all firing on
both instances.
**How detected**: comparing `last_triggered` from `restore_state` across the
two instances showed identical automation IDs firing at the same times on
both — the container on piha (`homeassistant5`, HA 2026.4.3, location_name
`KEN`, mounted at `/home/pi/homeassistant/config`) never actually stopped
running after the migration to the RPi4/HAOS instance at 192.168.31.7; it
stayed alive and MQTT-connected, so both were independently reacting to the
same physical events.
**Root cause**: `instances.yaml` had `ken` pointed at the piha container —
that was the pre-migration instance, not the real one. The actual home
instance had already moved to Home Assistant OS on a dedicated RPi4
(192.168.31.7:8123, ingress `ha.kapala.org` via NPM, confirmed HAOS via
observer :4357, HACS installed, 118 automations), but the repo never
followed the move.
**Decision**: 192.168.31.7 (HAOS/RPi4) is canonical `ken`. The piha
container is renamed `ken-legacy` in `instances.yaml`, `status: archived`.
Plan: archival import for historical reference → `docker stop` (not `rm`)
→ one week of observation → decide on `docker rm`. See `docs/backlog.md`
for the ha-diag-agent re-pointing and wind-down follow-ups this incident
generated.
## Open questions ## Open questions
- What actually drives the phase-3 operational agent (a new agent process - What actually drives the phase-3 operational agent (a new agent process

View file

@ -16,8 +16,11 @@ services/home-assistant/
└── fixtures/ # dated /api/states snapshots └── fixtures/ # dated /api/states snapshots
``` ```
Instances: `ken` (PIHA, container `homeassistant5`, docker-exec adapter), Instances: `ken` (RPi4/HAOS, LAN 192.168.31.7, api adapter — canonical home
`chelsty-ha` (Tailscale, api adapter — see `instances.yaml`). instance since the 2026-07-22 cutover), `ken-legacy` (PIHA, container
`homeassistant5`, docker-exec adapter, archived — pre-migration instance,
import only, never deploy), `chelsty-ha` (Tailscale, api adapter — see
`instances.yaml` and `DESIGN.md` "Incident log").
## Import ## Import

View file

@ -0,0 +1,20 @@
# ken-legacy — historical archive, do not deploy
This directory holds the `/config` import of the **pre-migration** Home
Assistant instance: the `homeassistant5` container on piha, wound down
2026-07. It is kept for historical reference only — e.g. recovering the
logic of an old automation — not as a live or deployable instance.
See `services/home-assistant/DESIGN.md`, "Incident log" (2026-07-22) for
why this instance exists separately from the canonical `ken` (now the
Home Assistant OS instance on the RPi4 at 192.168.31.7): this container
kept running after the real migration and was firing automations in
parallel with the real home instance until the cutover was caught and
fixed.
**Rules for humans and agents:**
- Never run `import.sh ken-legacy` expecting a deploy target — it isn't
one. `services/home-assistant/instances.yaml` marks it `status:
archived` for this reason.
- Never write back to `homeassistant5` from this directory.
- Treat everything here as read-only history.

View file

@ -4,7 +4,26 @@
# only the path to where each instance's token is expected on disk. # only the path to where each instance's token is expected on disk.
instances: instances:
# Cutover 2026-07-22: repo previously pointed "ken" at the piha container
# (homeassistant5), but that container is a pre-migration legacy instance
# that kept running and firing automations in parallel with the real home
# instance below. See DESIGN.md, "Incident log" for the full writeup.
ken: ken:
host: ken-haos
adapter: api
base_url: "http://192.168.31.7:8123"
token_path: ~/.config/ha-deploy/ken.token
status: active
site: ken
# Confirmed 2026-07-22: Home Assistant OS on a dedicated RPi4, LAN
# 192.168.31.7:8123, ingress ha.kapala.org via NPM. HACS installed,
# 118 automations. HAOS has no SSH access, so there is no
# docker-exec/filesystem path here — full `/config` import is deferred
# until an alternative access path exists. For now import.sh's scope
# for this instance is whatever the api adapter can reach: automations,
# scripts, scenes, dashboards.
ken-legacy:
host: piha host: piha
container: homeassistant5 container: homeassistant5
config_mount: /home/pi/homeassistant/config config_mount: /home/pi/homeassistant/config
@ -12,18 +31,15 @@ instances:
ssh: ssh:
user: oskar user: oskar
host: piha host: piha
token_path: ~/.config/ha-deploy/ken.token token_path: ~/.config/ha-deploy/ken-legacy.token
# TODO: verify actual container port mapping via `docker inspect homeassistant5` base_url: "http://localhost:8123" # confirmed 2026-07-22
# on piha (not runnable from this worktree — no SSH access here). Known so far status: archived
# from docs/infra/inventory-2026-06-30.md + inventory/topology.yaml:
# - ha-diag-agent on piha targets http://localhost:8123 (container reachable
# on piha's own loopback, so likely host networking or 8123:8123 published)
# - NPM ingress ha.kapala.org -> 192.168.31.7:8123 (piha's LAN IP), per
# inventory/topology.yaml services.home_assistant
# Until confirmed with `docker inspect`, treat this as unverified.
base_url: "http://localhost:8123" # TODO: confirm via docker inspect on piha
status: active
site: ken site: ken
# Pre-migration instance (HA 2026.4.3, location_name "KEN"), superseded
# by `ken` above (192.168.31.7). Still alive and MQTT-connected as of
# 2026-07-22 — being wound down, not deleted yet. Import is
# archival-only (historical reference); this instance is NEVER a deploy
# target. See DESIGN.md, "Incident log".
chelsty-ha: chelsty-ha:
host: chelsty-ha host: chelsty-ha