# Home Assistant Performance Fix & Infrastructure Migration ## Problem Summary Home Assistant at `ha.hideawaygaming.com.au` (HAOS 2026.5.3) periodically becomes unresponsive. Because critical infrastructure services (AdGuard DNS, Tailscale VPN, Guacamole RDP, Nginx Proxy Manager) all run as HA add-ons inside the same VM, any HA freeze causes house-wide network and access failures. ## Network Plan | Service | CT ID | IP | Port(s) | |---------|-------|----|---------| | OPNsense (gateway) | — | 10.0.0.254 | — | | Proxmox (HAL-HOST) | — | 10.0.0.240 | 8006 | | HAOS VM | — | 10.0.0.55 | 8123 | | AdGuard Home (LXC) | 120 | 10.0.0.224 | 53, 80 | | Guacamole (LXC) | 121 | 10.0.0.225 | 8080 | | NPM (LXC) | 122 | 10.0.0.226 | 80, 443, 81 | ## Execution Order Run the scripts on the Proxmox host (10.0.0.240) as root. ### 1. Apply recorder exclude (HA side) Merge `recorder_exclude.yaml` into `/config/configuration.yaml`, restart HA. ### 2. Deploy AdGuard LXC ```bash chmod +x setup-adguard-lxc.sh ./setup-adguard-lxc.sh ``` - The script attempts SSH config migration from HAOS (no GUI export exists) - If SSH fails, follow the manual migration steps printed at the end - After setup: update OPNsense DHCP DNS from 10.0.0.55 → 10.0.0.224 ### 3. Deploy NPM LXC ```bash chmod +x setup-npm-lxc.sh ./setup-npm-lxc.sh ``` - Migrates SQLite DB, Let's Encrypt certs, and custom configs from HA addon - After setup: update OPNsense port forwards (80/443) from 10.0.0.55 → 10.0.0.226 - For automated backup-based migration, set `HA_TOKEN` env var before running ### 4. Deploy Guacamole LXC ```bash chmod +x setup-guacamole-lxc.sh ./setup-guacamole-lxc.sh ``` - Re-create RDP connections in the web UI - Set up NPM proxy with WebSocket support ### 5. Cleanup HA - Stop AdGuard, NPM, and Guacamole add-ons in HA - Clean up browser_mod, Plex, Pioneer VSX-832 stale entities - Increase HAOS VM memory to 8 GB - Optionally re-add AdGuard as HA integration pointing to 10.0.0.224 ## Docker-in-LXC Note The Guacamole and NPM scripts create **unprivileged** LXC containers with `lxc.apparmor.profile: unconfined` set automatically. This is required because Docker inside unprivileged LXC cannot access `net.ipv4.ip_unprivileged_port_start` under the default AppArmor profile. The setup scripts handle this automatically — the fix is applied between container creation and first start. If you already deployed the containers before this fix was baked in, run `fix-docker-lxc.sh` followed by `fix-guac-npm.sh` to retroactively apply it. ## Architecture After Migration ``` Internet │ ┌────┴────┐ │ OPNsense │ 10.0.0.254 │ Gateway │ └────┬────┘ │ ┌───────────┬───────┴───────┬───────────┐ │ │ │ │ ┌──┴──┐ ┌───┴───┐ ┌───┴───┐ ┌───┴───┐ │ AGH │ │ NPM │ │ HAOS │ │ Guac │ │ LXC │ │ LXC │ │ VM │ │ LXC │ │.224 │ │ .226 │ │ .55 │ │ .225 │ │DNS │ │ HTTP/S│ │HA only│ │ RDP │ └─────┘ └───────┘ └───┬───┘ └───────┘ │ ┌────┴────┐ │Tailscale│ │(in HA) │ └─────────┘ ``` ## Files | File | Purpose | |------|---------| | `recorder_exclude.yaml` | Recorder exclude config — merge into `configuration.yaml` | | `setup-adguard-lxc.sh` | CT 120 — AdGuard Home with SSH config migration | | `setup-guacamole-lxc.sh` | CT 121 — Guacamole via Docker Compose (AppArmor fix baked in) | | `setup-npm-lxc.sh` | CT 122 — NPM with DB/cert migration (AppArmor fix baked in) | | `fix-docker-lxc.sh` | Retroactive fix — adds AppArmor unconfined to CT 121 & 122 | | `fix-guac-npm.sh` | Retroactive fix — reinits Guacamole DB + retries NPM migration |