havm

Zero-config CLI for running Home Assistant OS on Apple Silicon using the native Virtualization framework. One command from download to boot.

License: MIT Swift 6.4 Apple Virtualization macOS 15+ Sponsor
Homebrew Install Source on GitHub

Your smart home, one command away

Zero setup

Downloads and prepares HA OS automatically on first run. No Shortcuts, AppleScript, or manual launchd plists.

🔄

Starts at login

Designed for headless operation as a launchd service. Fire-and-forget: your smart home boots with your Mac.

💾

Persistent

All HA OS data — configs, add-ons, history — lives on a raw disk image. NVRAM and MAC address survive reboots.

🔌

USB accessories

Attach coordinators via the menu bar item. Hot-plug, no restart needed. macOS 27+.

🔑

SSH key import

Virtual CONFIG disk imports your public key for root SSH on port 22222 — HA OS picks it up automatically.

Graceful shutdown

REST API → SSH → force-stop fallback on SIGTERM. Three methods before pulling the plug.

📊

Prometheus metrics

Built-in HTTP endpoint for monitoring VM state and USB accessories. Grafana-ready.

📦

Self-contained

No Homebrew at runtime, no Python, no shell scripts. A single ~2.1 MB binary with zero external dependencies.

First run does it all

Download

Fetches the latest stable HA OS release from GitHub. Cached for instant re-installs.

Decompress

Built-in XZ decoder via libzma — no external tools, no Homebrew dependencies.

Prepare disk

Copies and resizes the raw disk image. APFS sparse files keep it lean.

Boot

UEFI boot from the GPT disk. No kernel extraction, no initrd. Just point at the image.

Terminal — brew install havm
$ brew install ingmarstein/havm/havm
==> Fetching downloads for: havm
✔︎ Formula havm (0.2.2)                                              Verified    857.5KB/857.5KB
==> Installing havm from ingmarstein/havm
==> Caveats
Downloads and sets up Home Assistant OS automatically on first run.

Data: /opt/homebrew/var/lib/havm/
Optional config: /opt/homebrew/etc/havm/config.yml

To start ingmarstein/havm/havm now and restart at login:
  brew services start ingmarstein/havm/havm
Or, if you don't want/need a background service you can just run:
  /opt/homebrew/opt/havm/bin/havm run -c /opt/homebrew/etc/havm/config.yml --data-dir /opt/homebrew/var/lib/havm
==> Summary
🍺  /opt/homebrew/Cellar/havm/0.2.2: 12 files, 2.2MB, built in 2 seconds
==> Running `brew cleanup havm`...
==> Caveats
fish completions have been installed to:
  /opt/homebrew/share/fish/vendor_completions.d

Then run it — havm handles the rest automatically:

Terminal — havm run (first boot)
 havm run
2026-06-29T20:26:47+0200 info havm.run: [Havm] Config loaded: CPU=4 Memory=4 GiB Network=bridge Log=text
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Starting HA OS setup...
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Found HA OS 18.0: haos_generic-aarch64-18.0.img.xz
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Using cached image: /Users/ingmar/Library/Caches/havm/haos_generic-aarch64-18.0.img
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Copied disk image to /Users/ingmar/Library/Application Support/havm/vm/haos.img
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Resizing disk from 963661824 B to 32 GiB...
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Disk resized. HA OS will auto-expand partitions on first boot.
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] SSH key path configured: ~/.ssh/id_ed25519.pub
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] SSH CONFIG disk created at /Users/ingmar/Library/Application Support/havm/vm/config.img
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] ✅ HA OS setup complete.
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] CPU: 4, Memory: 4 GiB
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] SSH CONFIG disk attached (USB)
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] USB: 1 device(s)
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Network: Bridge (en0, MAC ca:cb:0a:be:56:71)
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] VM configuration validated successfully
2026-06-29T20:26:47+0200 info havm.run: [HavmCore] Starting VM...
2026-06-29T20:26:48+0200 info havm.run: [HavmCore] VM started successfully
2026-06-29T20:26:48+0200 info havm.run: [HavmRuntime] VM state: running
2026-06-29T20:26:48+0200 info havm.run: [HavmRuntime] VM is running. Press Ctrl+C to stop, or send SIGTERM for graceful shutdown.

╔══════════════════════════════════════════════════════════╗
║  Home Assistant OS is booting.                           ║
║                                                          ║
║  Once ready, open:                                       ║
║    http://homeassistant.local:8123                       ║
║                                                          ║
║  Or check your router's DHCP lease table for the VM's    ║
║  IP address and open http://<ip>:8123                    ║
╚══════════════════════════════════════════════════════════╝

2026-06-29T20:26:48+0200 info havm.run: [HavmRuntime] USB: Listener registered — 0 already connected
2026-06-29T20:26:49+0200 info havm.run: [HavmRuntime] Waiting for resolution of homeassistant.local...
2026-06-29T20:27:03+0200 info havm.run: [HavmRuntime] Guest reachable at 192.168.1.42 — Home Assistant should be ready shortly
2026-06-29T20:27:03+0200 info havm.run: [HavmRuntime]   Web: http://homeassistant.local:8123
2026-06-29T20:27:03+0200 info havm.run: [HavmRuntime]   SSH: ssh root@homeassistant.local -p 22222
2026-06-29T20:27:31+0200 info havm.run: [HavmRuntime] Home Assistant is ready at http://homeassistant.local:8123

VM hardware

ComponentChoiceWhy
BootUEFI (VZEFIBootLoader)Boots directly from the GPT disk image
CPU4 cores (configurable)Sufficient for HA OS + add-ons
Memory4 GiB (configurable)Balloon lets macOS reclaim idle guest memory
EntropyVirtIO entropy deviceRandom numbers for guest crypto and ASLR
Disk32 GiB raw image, VirtIO blockAPFS sparse on disk (~6 GiB used after first boot)
NetworkBridge with stable MACLAN-reachable IP; falls back to NAT without entitlement
CONFIG diskUSB mass storage (XHCI)HA OS imports SSH keys from USB, not VirtIO
NVRAMPersisted EFI variable storeGRUB boot state survives reboots
PlatformVZGenericPlatformConfigurationStable machine ID → consistent MAC

Trust & transparency

MIT license
Full source on GitHub
No telemetry, no accounts
No external runtime dependencies
No surprise network calls
Single self-contained binary

Install

Homebrew (recommended)

Terminal
$ brew install ingmarstein/havm/havm
$ havm run

Or run as a background service that starts at login:

Terminal
$ brew services start havm

Build from source

Terminal
$ git clone https://github.com/IngmarStein/havm.git && cd havm
$ cp resources/build.xcconfig.example resources/build.xcconfig
$ ./scripts/build.sh release
$ .build/release/havm run

Data layout

ForegroundService
VM data~/Library/Application Support/havm/vm//opt/homebrew/var/lib/havm/
Config (optional)~/.config/havm/config.yml/opt/homebrew/etc/havm/config.yml
Downloads cache~/Library/Caches/havm/

Configuration

Everything works with zero config. Tweak ~/.config/havm/config.yml if you want:

~/.config/havm/config.yml
vm:
  cpu_count: 4
  memory_size: "4 GiB"
  disk_size: "32 GiB"
network:
  type: bridge
haos:
  release_channel: stable
ssh:
  authorized_keys: "~/.ssh/id_ed25519.pub"
metrics:
  enabled: true

Full configuration reference

Documentation