feat(home-assistant): set internal/external URLs for mobile_app push
The HA Companion app needs an external_url for clickable notification deep-links to resolve when the phone is off the home Wi-Fi. Reach is via Tailscale (Headscale tailnet solar.internal), so external_url points at the FQDN jupiter.solar.internal:8123; internal_url stays on the bare hostname for LAN-attached devices. Phase A only: device registration + notify group + smoke-test land in a follow-up commit once Companion has registered real mobile_app_<slug> service names. See docs/superpowers/specs/2026-05-18-ha-push-notifications.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# Smartphone push notifications from Home Assistant
|
||||
|
||||
## Goal
|
||||
|
||||
Send push notifications from jupiter's Home Assistant to the user's
|
||||
smartphones over the home Tailscale (Headscale) tailnet `solar.internal`.
|
||||
|
||||
## Architecture
|
||||
|
||||
- HA's `mobile_app` integration is enabled (already in `extraComponents`
|
||||
and present as `mobile_app = {}` in config).
|
||||
- Each smartphone runs the **HA Companion app**, signs in to HA, and
|
||||
auto-registers as a `notify.mobile_app_<device_slug>` service.
|
||||
- Reach: phones connect to HA via Tailscale, so HA's `external_url` is
|
||||
set to the Headscale FQDN `http://jupiter.solar.internal:8123`. The
|
||||
`internal_url` is `http://jupiter:8123` for LAN-attached devices.
|
||||
- No public exposure, no reverse proxy, no TLS termination in scope.
|
||||
|
||||
## Phase A — done in this branch
|
||||
|
||||
NixOS module change in `modules/environments/home-assistant/default.nix`:
|
||||
|
||||
```nix
|
||||
homeassistant = {
|
||||
name = "Home - Rechberg";
|
||||
unit_system = "metric";
|
||||
internal_url = "http://${hostName}:8123";
|
||||
external_url = "http://jupiter.solar.internal:8123";
|
||||
};
|
||||
```
|
||||
|
||||
After deploy, perform the user-side registration:
|
||||
|
||||
1. Install the Companion app:
|
||||
- iOS: search "Home Assistant" in the App Store.
|
||||
- Android: search "Home Assistant" in Google Play.
|
||||
2. Ensure Tailscale is running and connected on the phone.
|
||||
3. Open the Companion app. When asked to connect, enter
|
||||
`http://jupiter.solar.internal:8123` and sign in with the HA account.
|
||||
4. Approve the registration prompt in HA.
|
||||
5. In HA, go to **Settings → Devices & Services → Mobile App** and
|
||||
confirm the phone appears as a device.
|
||||
6. In HA, go to **Developer Tools → Services**, type `notify.mobile_app_`
|
||||
and note the exact service slug for each phone (e.g.
|
||||
`notify.mobile_app_iphone_finn`). These slugs are needed for Phase B.
|
||||
|
||||
### Verifying Phase A end-to-end
|
||||
|
||||
Build-time:
|
||||
|
||||
```
|
||||
nix eval '.#nixosConfigurations.jupiter.config.services.home-assistant.config.homeassistant' \
|
||||
--extra-experimental-features 'nix-command flakes'
|
||||
```
|
||||
|
||||
Expect the rendered attrset to contain both `external_url` and
|
||||
`internal_url`.
|
||||
|
||||
Deploy on jupiter:
|
||||
|
||||
```
|
||||
sudo nixos-rebuild switch --flake '.#jupiter'
|
||||
systemctl status home-assistant
|
||||
journalctl -u home-assistant -n 50 --no-pager
|
||||
```
|
||||
|
||||
Functional check after Companion sign-in:
|
||||
|
||||
- HA UI → **Developer Tools → Services** → choose
|
||||
`notify.mobile_app_<your_device>` → service data
|
||||
`{ "message": "Phase A test" }` → **Call Service** → push arrives on
|
||||
the phone.
|
||||
|
||||
## Phase B — follow-up commit (after registration)
|
||||
|
||||
Once device slugs are known, a separate commit adds:
|
||||
|
||||
1. A `notify` group fanning out to every registered phone:
|
||||
|
||||
```nix
|
||||
notify = [
|
||||
{
|
||||
name = "all_phones";
|
||||
platform = "group";
|
||||
services = [
|
||||
{ service = "mobile_app_<slug_1>"; }
|
||||
{ service = "mobile_app_<slug_2>"; }
|
||||
];
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
2. A smoke-test mechanism. Approach to be decided in Phase B based on
|
||||
whether future Nix-managed automations are expected:
|
||||
|
||||
- Pragmatic: document a one-time UI call to `notify.all_phones` from
|
||||
Developer Tools (no automation in YAML).
|
||||
- Compromise: switch `automation = "!include automations.yaml"` to
|
||||
`!include_dir_merge_list automations/` so a Nix-managed
|
||||
`00-smoke-test.yaml` can coexist with UI-editable automations.
|
||||
|
||||
### Verifying Phase B end-to-end
|
||||
|
||||
- Restart HA, watch `journalctl -u home-assistant` for YAML schema errors.
|
||||
- Call `notify.all_phones` from Developer Tools — every registered phone
|
||||
receives the push.
|
||||
|
||||
## Open items
|
||||
|
||||
- After Companion registration, collect the `mobile_app_<slug>` service
|
||||
names from HA and update this spec + open Phase B PR.
|
||||
@@ -40,6 +40,8 @@ in
|
||||
homeassistant = {
|
||||
name = "Home - Rechberg";
|
||||
unit_system = "metric";
|
||||
internal_url = "http://${hostName}:8123";
|
||||
external_url = "http://jupiter.solar.internal:8123";
|
||||
};
|
||||
mobile_app = {};
|
||||
automation = "!include automations.yaml";
|
||||
|
||||
Reference in New Issue
Block a user