Add your public key to the config and HA OS will import it on boot, enabling root SSH access on port 22222:
ssh:
authorized_keys: "~/.ssh/id_ed25519.pub"
havm creates a small MBR + FAT16 disk image with volume label CONFIG and
an authorized_keys file. HA OS auto-imports it on boot and starts dropbear
on port 22222. Without this file, HA OS disables the debug SSH server.
ssh root@<guest-ip> -p 22222
For the regular SSH add-on (Terminal & SSH or Advanced SSH & Web Terminal), install the add-on via the HA web UI — it listens on port 22.
On SIGTERM or Ctrl+C, havm tries these shutdown methods in order:
POST <ha.url>/api/services/hassio/host_shutdown, where the default
address is probed: http://<ip> on HAOS 2026.8+, http://<ip>:8123 before it
(requires a long-lived access token in ha.api_token)ssh root@<ip> -p 22222 shutdown -h now
(requires ssh.authorized_keys for CONFIG disk import)ssh root@<ip> -p 22 ha host shutdown
(requires the SSH add-on installed in HA)A method that fails falls through to the next one. If the REST API request is
sent but no response comes back, havm treats the guest as already halting and
waits for it rather than moving on to SSH.
shutdown.timeout_seconds is one budget for the whole chain, not a
timeout per method. Every request attempt and every wait for the guest to
halt is drawn from the same deadline, so falling through to the next method
does not restart the clock. When the budget runs out the VM is force-stopped —
even if a method accepted the shutdown request and the guest is still halting
cleanly. Raise it if your guest regularly needs longer than 90 seconds.
requestStop() is not used — HA OS on aarch64 uses PSCI
and ignores ACPI power button events.
ha:
api_token: "eyJ..." # HA long-lived access token
url: "https://homeassistant.local:443" # default: probed (see above)
shutdown:
timeout_seconds: 90 # budget for the whole shutdown chain (default: 90)
ha.api_tokenconfig.yml permissions
restrictive (chmod 600 ~/.config/havm/config.yml).
In bridge mode (the default) havm reaches the guest by its mDNS name —
network.hostname, defaulting to homeassistant.local. In NAT mode there is no
name, so it parses /var/db/dhcpd_leases and matches the VM’s MAC address.
Set a static IP or a unique name to override the default:
network:
hostname: "192.168.1.42"
Send SIGHUP to trigger a clean shutdown and restart. launchd / Homebrew
keep_alive will restart the process automatically:
kill -HUP $(cat ~/Library/Application\ Support/havm/vm/havm.pid)
This runs the full shutdown chain (REST API → SSH → force-stop) before exiting. Useful after changing config settings that require a restart (CPU, memory, disk size, network, USB).