Repository navigation
Description
Problem statement
Every time a Home Assistant user installs the companion app on another Apple device (new iPhone, iPad, Mac, or a family hand-me-down signed into the same Apple Account), they have to set it up from scratch: discover or type the server URL, configure internal/external URLs and SSIDs, log in, grant permissions and re-tune settings. For users with several servers or several devices, this is repeated per device and per server.
Apple users already expect apps to "just be there" on a new device (passwords, Wi-Fi, app data via iCloud). The companion app doesn't meet that expectation, which adds friction at exactly the moment a user is trying to expand their use of Home Assistant.
Who is impacted: Apple-platform users with more than one device (iPhone + iPad + Mac is very common), users migrating to a new device, and users with multiple Home Assistant servers.
Why it matters to OHF: Reducing setup friction makes Home Assistant easier to adopt across a household's devices, and supports the goal of a polished, first-class companion app experience. It also gives us a chance to fix a long-standing issue where restoring/migrating devices produces cloned or broken mobile_app registrations.
Community signals
No response
Scope & Boundaries
In scope
- Sync the list of servers and their server-level configuration between devices signed into the same Apple Account (iPhone, iPad, Mac; Apple Watch keeps getting it from its paired iPhone).
- Server name, server identifier (UUID), internal URL, external URL, SSIDs / hardware addresses used for internal detection, user-facing server settings.
- On first launch on a new device, offer "Continue with Home (found in iCloud)" instead of the onboarding flow.
- Each device still registers itself with Core as its own device (see Foreseen solution).
- An in-app opt-in/opt-out toggle for iCloud sync, and a way to stop syncing a specific server.
Out of scope
- Syncing any device-specific data: webhook ID, webhook secret, cloudhook URL, remote UI URL, device ID, push token, sensors/notification categories, location settings.
- Sharing servers across different Apple Accounts (Family Sharing) — separate opportunity.
- Android / non-Apple platforms (could inspire a parallel effort with Google backup/Block Store, but not part of this bet).
- Syncing dashboards, Assist pipelines, or other server-side data (already lives on the server).
- Watch-only standalone setup changes.
Foreseen solution
Storage
- Server config (non-secret):
NSUbiquitousKeyValueStoreor a CloudKit private database. Small payload, automatically available on all devices signed into the same iCloud account. - Credentials (secret): iCloud Keychain item with
kSecAttrSynchronizable = truein the shared keychain access group. End-to-end encrypted by Apple, never touches our servers or plain iCloud storage.
Authentication — two phases
Phase 1 — Pre-configured, not pre-authenticated (low risk, ships first)
- New device reads the synced server config and skips URL discovery/entry.
- User authenticates on the new device via the normal HA login flow (same OAuth flow as today, just pre-pointed at the right server and URLs).
- Result: one tap + login instead of the full onboarding. No new Core APIs needed.
Phase 2 — Pre-authenticated via device enrollment (needs Core support)
- The existing device stores a synced bootstrap credential in iCloud Keychain.
- The new device does not reuse that refresh token long-term. It uses it once to call a new Core endpoint (in the new companion apps integration) that exchanges it for a brand-new, device-bound refresh token (e.g.
POST /api/companion/enroll, returning a new refresh token tied to the new device's client name). - Core records the new token as a separate session in the user's profile ("Bruno's iPad – iOS app"), so it can be revoked independently.
- Core sends a notification to the user's other devices / persistent notification: "A new device signed in as Bruno via iCloud". Optional admin setting to disable iCloud enrollment entirely.
- Reusing one shared refresh token across devices is explicitly rejected: revoking it would log out every device and Core couldn't tell devices apart.
Device registration on Core
- Sync carries no registration data. On first launch each device performs its own registration (mobile_app today, the new companion integration going forward) with its own installation UUID, device name, model and push token.
- Core creates a separate device + config entry + webhook per device, exactly like a fresh install today.
- Core dedupes by installation/device identifier so restoring a backup or re-installing doesn't create clones.
- The synced server UUID lets the app match the iCloud entry to the right server even if URLs differ.
Flow
New device launches
└─ iCloud has servers? ── no ──► normal onboarding
│ yes
▼
"Continue with Home?"
│
Phase 1: login flow ─┐
Phase 2: enroll with ├─► new device-bound refresh token
synced bootstrap ────┘
▼
Register device with Core (new webhook, device entry)
▼
Ready — permissions & sensors set up per device
Risks & open questions
- Security of pre-auth: anyone with access to a device signed into the same Apple Account (e.g. a shared family iPad) would get access to the user's HA. Mitigations: Phase 1 first, Phase 2 opt-in, notify on enrollment, require device passcode/biometrics before enrolling, admin kill-switch. Needs a security review.
- Core API for token exchange: HA auth has no "mint a new refresh token from an existing one" flow today. Needs alignment with Core/auth owners (Paulus, Franck) on design and whether it belongs in the companion integration or in
auth. - Refresh token lifecycle: what happens to the synced bootstrap token if the original device is removed or the token is revoked? Should the bootstrap token be a dedicated, short-lived/limited enrollment token rather than a real session token?
- Data model refactor in the app: current server storage mixes server-level and device-level data; it must be split cleanly so device-specific data is never synced.
- Conflict handling: two devices editing the same server config simultaneously, or a server deleted on one device — sync vs. local override semantics.
- iCloud availability: users with iCloud Keychain / iCloud Drive off, Managed Apple Accounts, or Advanced Data Protection — make sure we degrade gracefully to normal onboarding.
- Privacy: server URLs in iCloud KVS are not end-to-end encrypted unless ADP is on. Consider storing everything in iCloud Keychain instead.
- Dependency on the new companion apps integration in Core for the Phase 2 endpoint and improved registration/dedupe.
Appetite
Medium overall.
- Phase 1 (sync server config, login on new device): Small — ~1 cycle, iOS only, no Core changes.
- Phase 2 (pre-auth enrollment + Core endpoint + notifications): Medium — ~1–2 cycles across iOS and Core, plus security review.
Execution issues
No response
Decision log
| Date | Decision | Outcome |
|---|---|---|
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsConsidering
Activity