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:
marthsincemelee
2026-05-18 12:07:31 +02:00
parent 4cb4455d37
commit d2775e35d9
2 changed files with 113 additions and 0 deletions
@@ -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";