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 = {
|
homeassistant = {
|
||||||
name = "Home - Rechberg";
|
name = "Home - Rechberg";
|
||||||
unit_system = "metric";
|
unit_system = "metric";
|
||||||
|
internal_url = "http://${hostName}:8123";
|
||||||
|
external_url = "http://jupiter.solar.internal:8123";
|
||||||
};
|
};
|
||||||
mobile_app = {};
|
mobile_app = {};
|
||||||
automation = "!include automations.yaml";
|
automation = "!include automations.yaml";
|
||||||
|
|||||||
Reference in New Issue
Block a user