Background: I used Tailscale for remote access to HA. It mostly worked well, but in the driveway the phone is half on cellular, half on wifi. The HA app keeps an old connection and hangs most of the time when I just quickly want to open the garage door. Kill, reopen, wait. That was annoying enough that I wrote something that fixes that over the weekend.
ha-iroh is a small Android app plus a HACS integration, built on iroh (p2p QUIC). Every phone has a keypair with HA, traffic is end-to-end encrypted, NAT hole punching is done automatically where possible, otherwise a relay is used that only sees ciphertext. Setup (one-time, first connection) is done by scanning a QR-Code.
There is no persistent tunnel. The app dials HA when you tap something and disconnects afterwards, so network switches don’t matter and my in-front-of-the-garage-door wait is gone.
Features
- Device Controls in the Android power menu / quick settings: lights, switches, fans, climate, covers, locks, scenes, scripts, buttons, with live state
- Assist via quick settings tile or launcher shortcut (text only for now)
- the normal HA dashboard in a WebView, login once, any auth provider incl. MFA
- several HA instances in one app
- pairing by QR code from the HA config flow. Delete the device in HA and the phone is out
Not included, on purpose Sensors, location, notifications, widgets, Wear OS, iOS. I still use the official app for all of that. ha-iroh only covers quick control when I’m not home.
Status
- v0.2.x. I’ve not received any major bug reports yet, but DO expect rough edges. For me at least it currently works reliably enough.
- Android 12+, arm64 APK via GitHub Releases or Obtainium. Not on Play.
- HA 2026.3+, HACS custom repo. The integration starts a small Rust bridge as a subprocess, x86_64 and aarch64 bundled, so HA OS / Container / Supervised work.
- Optional: forward one UDP port and iroh connects directly always instead of sometimes via relay. Not required.
- Two HA settings to check, both in the README:
ip_ban_enabled(the bridge connects from localhost, so wrong passwords from one phone can ban 127.0.0.1, i.e. all phones) and never put loopback intotrusted_networks.
Disclosure
Large parts of this were built with an LLM. If that’s a dealbreaker for you, this project is not for you.
Links
- Repo + install guide: https://github.com/pzeinlinger/ha-iroh
- MIT
- https://buymeacoffee.com/pzeinlinger
Bug reports welcome, especially from people behind CGNAT or on Fritz!Box / MikroTik.
Although LLM-assisted projects are no bueno for me, I am upvoting for your transparency 👍 best of luck
Just to put this out there, a Nabu Casa sub directly supports the development of HA. For me the remote connectivity is just a bonus (that I honestly don’t need since I could easily put it through a cloudflared tunnel or set it up through NGINX proxy manager.
Not that this isn’t cool, having more ways to use HA is always great. Personally I expose my garage doors as Apple Home devices through HA and so get buttons on CarPlay that generally work well (as long as I have any signal which isn’t always the case in the driveway).
100% agree, nabu casa is worth it for the support alone, not trying to replace that! this is for the “i dont want HA reachable from the internet, period” crowd and me. the android power menu is my version of the carplay button. and my initial problem wasn’t no signal, rather the opposite: coming home and my phone connecting to wifi outside the garage - and that messing up ha + tailscale’s connection.
Automation trigger: I go off my home WiFi SSID
Action: activate WireGuard vpn to my home.
Trigger: I join home WiFi
Action: disconnect WireGuard VPN
This solved my garage problems without an app.
A cool project! Sure hope it’s not AI slop!
em dashes in code comments
sigh
I get this is the HA community, but how is fumbling with a smartphone in your car more convenient than dedicated button built/clipped to your car’s sun visor?
Physical button: 1 action, no logic
Software button: infinite actions, complete logic over everything in HA
It’s like ‘why should I use HA, the light switch is right there’ yes technically but you’re missing the whole point. Why should you go on trips and see the sights of other places, Google Street View is right there.
E: real world example, though my network reaches far beyond my driveway so no button required:
Automation
alias: Midnight - Travel, Arriving Home description: '' triggers: - trigger: zone entity_id: person.midnight zone: zone.home event: enter conditions: - condition: state entity_id: input_boolean.midnight_awake state: - 'on' - condition: time after: '10:00:00' actions: - if: - condition: not conditions: - alias: Connected to home wifi network condition: state entity_id: sensor.midnights_phone_wi_fi_connection state: - input_text.home_network then: - wait_for_trigger: - trigger: state entity_id: - sensor.midnights_phone_wi_fi_connection to: - input_text.home_network timeout: hours: 0 minutes: 1 seconds: 0 milliseconds: 0 continue_on_timeout: true - if: - condition: state entity_id: light.midnight_s_bedroom state: - 'off' then: - action: light.turn_on metadata: {} target: entity_id: light.midnight_s_bedroom data: brightness_pct: 35 - action: input_boolean.turn_on target: entity_id: input_boolean.midnight_s_light_override data: {} - if: - condition: numeric_state entity_id: light.midnight_s_bedroom attribute: brightness below: 35 then: - action: light.turn_on metadata: {} target: entity_id: light.midnight_s_bedroom data: brightness_pct: 35 - delay: hours: 0 minutes: 0 seconds: 15 milliseconds: 0 enabled: true - action: automation.trigger metadata: {} target: entity_id: - automation.battery_low - automation.midnight_s_bedroom_midnight_s_thermostat_outside_is_cooler - automation.midnight_s_bedroom_midnight_s_thermostat_outside_is_warmer data: skip_condition: false - action: tts.speak metadata: {} target: entity_id: tts.piper data: cache: false media_player_entity_id: media_player.midnight_s_bedroom_home_assistant_voice_media_player message: Welcome home, Midnight! mode: single




