Jesse A. Green / notebook

Home Assistant Operating System — User Guide

Generated May 2026 from home-assistant/operating-system at a0b3eb6

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Quick Start

Home Assistant Operating System (HAOS) is a purpose-built Linux distribution designed to run Home Assistant on dedicated hardware or virtual machines. Built on Buildroot, it provides a minimal, managed OS with automatic over-the-air (OTA) updates, A/B boot slot redundancy, and a containerized Home Assistant stack — all pre-configured and ready to run.

Key features:

  • Plug-and-play installation — flash an image, boot, and Home Assistant is running
  • A/B partition scheme with automatic rollback on failed updates
  • OTA updates via RAUC with cryptographic signature verification
  • Docker-based Home Assistant Supervisor, Core, and add-ons
  • NetworkManager for wired, Wi-Fi, and VLAN networking
  • Swap and zRAM management with configurable sizes
  • Broad hardware support: Raspberry Pi, ODROID, x86-64 PCs, VMs, and dedicated appliances
  • AppArmor security profiles for containerized services

Prerequisites:

  • Supported hardware or virtualization platform (see Installation)
  • SD card, eMMC, USB drive, SSD, or virtual disk (32 GB minimum recommended)
  • Internet connection for initial setup and container image downloads

Fastest path to running:

  1. Download the correct image for your hardware from the Home Assistant installation page
  2. Flash the image to your boot media using Balena Etcher or similar
  3. Insert the media, power on the device, and wait approximately 5–20 minutes for first boot
  4. Open http://homeassistant.local:8123 in a browser

Tip

On first boot, HAOS expands the data partition to fill the entire disk, downloads the latest Supervisor and Home Assistant Core containers, and starts all services. The landing page at port 8123 appears once Home Assistant Core is ready.

What to explore next:

  • Configuring your network (see Configuration below)
  • Updating the OS (see Core Usage below)
  • Troubleshooting connectivity issues (see Troubleshooting below)

2. Installation

Supported Platforms

Platform Board / Target Image Type Boot Media
Raspberry Pi 3 (64-bit) rpi3-64 .img.xz SD card
Raspberry Pi 4 (64-bit) rpi4-64 .img.xz SD card, USB SSD, NVMe (via HAT)
Raspberry Pi 5 (64-bit) rpi5-64 .img.xz SD card, NVMe
Home Assistant Yellow yellow .img.xz eMMC (CM4/CM5 based)
NabuCasa Green green .img.xz eMMC
ODROID-C2 odroid_c2 .img.xz SD card, eMMC
ODROID-C4 odroid_c4 .img.xz SD card, eMMC
ODROID-M1 odroid_m1 .img.xz SD card, eMMC, NVMe
ODROID-M1S odroid_m1s .img.xz SD card, eMMC
ODROID-N2/N2+ odroid_n2 .img.xz SD card, eMMC
Khadas VIM3 khadas_vim3 .img.xz SD card, eMMC
Generic x86-64 (UEFI) generic-x86-64 .img.xz USB, SSD, NVMe
Generic AArch64 (UEFI) generic-aarch64 .img.xz USB, SSD
VirtualBox / VMware / KVM ova .ova Virtual disk

Important

Always use the image that matches your exact hardware. Using the wrong image (e.g., rpi4-64 on a Raspberry Pi 5) will fail to boot. The Raspberry Pi 5 requires the rpi5-64 image specifically.

Flashing the Image

SD Card / USB / SSD (.img.xz)

  1. Download the .img.xz image for your platform
  2. Flash using Balena Etcher, dd, or Raspberry Pi Imager:
xzcat haos_rpi4-64.img.xz | sudo dd of=/dev/sdX bs=4M status=progress
sync
1887+1 records in
1887+1 records out
7918845952 bytes (7.9 GB, 7.4 GiB) copied, 142.3 s, 55.6 MB/s
  1. Insert the media into your device and power on

Virtual Machine (.ova)

  1. Download the .ova file
  2. Import into VirtualBox, VMware, or Proxmox:
    • VirtualBox: File → Import Appliance → select the .ova
    • VMware: File → Open → select the .ova
    • Proxmox: use qm importovf or convert to qcow2
  3. Allocate at least 2 GB RAM and 32 GB disk
  4. Start the VM

Warning

For VirtualBox and Proxmox VMs, Bluetooth passthrough is not supported natively. If you need Bluetooth for Zigbee or Z-Wave dongles, use USB passthrough for the physical adapter instead. See GitHub issue #2142.

Generic x86-64 (Bare Metal UEFI)

  1. Flash the generic-x86-64 image to a USB drive
  2. Boot from the USB drive (configure BIOS/UEFI boot order accordingly)
  3. HAOS installs to the internal disk and boots from it on subsequent startups

Post-Install Verification

After the device boots and the initial setup completes, verify the installation:

  1. Open http://homeassistant.local:8123 in a browser (or use the device's IP address)
  2. The Home Assistant onboarding wizard should appear
  3. From the Home Assistant CLI (via SSH add-on or console), confirm the OS:
ha os info
version: 14.2
version_latest: 14.2
update_available: false
board: rpi4-64
boot: slot0
data_disk: /dev/mmcblk0p8

Tip

If homeassistant.local does not resolve, use your router's DHCP client list to find the device's IP address, or connect a monitor and keyboard to see the console output showing the IP.


3. Configuration

HAOS is designed to require minimal user configuration. Most settings are managed through the Home Assistant Supervisor UI or CLI. The OS itself exposes a limited set of configuration options through specific files and paths.

Network Configuration

Networking is managed by NetworkManager. Configuration can be done via:

  • The Home Assistant UI: Settings → System → Network
  • The ha CLI: ha network info, ha network update
  • NetworkManager connection files on the config partition

To pre-configure networking before first boot, place NetworkManager connection files in the CONFIG partition (mounted at /mnt/config on the running system):

CONFIG/
└── network/
    └── my-network

The NetworkManager configuration file at /etc/NetworkManager/NetworkManager.conf sets these defaults:

Setting Value Purpose
wifi.scan-rand-mac-address no Disables random MAC addresses for consistent network identity
connection.llmnr 2 (disabled) Disables Link-Local Multicast Name Resolution
connection.mdns 2 (enabled) Enables mDNS for .local hostname resolution
connectivity.uri https://checkonline.home-assistant.io/online.txt Online connectivity check endpoint

Note

DNS resolution uses systemd-resolved with a fallback stub resolver configured at /etc/resolv.conf. If you experience DNS issues with local domain resolution, see the Troubleshooting section for known issue #2988.

Swap Configuration

HAOS creates a swap file on the data partition at /mnt/data/swapfile. The swap size can be customized by writing to /etc/default/haos-swapfile:

echo 'SWAPSIZE=512M' > /etc/default/haos-swapfile

After setting, reboot for the change to take effect. The swap service (haos-swapfile.service) reads this file and creates a swap file of the specified size.

Value Behavior
SWAPSIZE=512M Creates a 512 MB swap file
SWAPSIZE=1G Creates a 1 GB swap file
SWAPSIZE=0 Disables swap entirely
(not set) Uses the system default formula

Warning

Setting SWAPSIZE=0 completely disables swap. On memory-constrained devices (1 GB RAM or less), this may cause out-of-memory kills for Home Assistant or add-ons. Only disable swap if you have sufficient physical RAM.

Hostname

The system hostname defaults to homeassistant and can be changed through the Home Assistant UI or CLI:

ha host options --hostname myhome

Time Synchronization

Time synchronization uses systemd-timesyncd. The configuration at /etc/systemd/timesyncd.conf uses the default NTP servers. A NetworkManager dispatcher script at /usr/lib/NetworkManager/dispatcher.d/10-ntp manages NTP server updates when network connections change.

Docker Configuration

Docker runs with the containerd snapshotter backend. The daemon configuration at /etc/docker/daemon.json is pre-configured by HAOS:

{
    "log-driver": "journald",
    "storage-driver": "overlay2"
}

Important

Do not modify the Docker configuration manually. HAOS manages Docker settings through the Supervisor. Manual changes may be overwritten on updates or cause the Supervisor to fail.

For the complete configuration reference covering all system files and systemd units, see the Admin Guide.


4. Core Usage

Checking OS Status

View the current OS version, board type, and boot slot:

ha os info
version: 14.2
version_latest: 14.3
update_available: true
board: rpi4-64
boot: slot0

Updating the OS

HAOS supports over-the-air updates. Updates are downloaded, installed to the inactive boot slot, and activated on the next reboot:

ha os update
Processing... Done.
Command completed successfully.

The system reboots automatically into the updated slot. If the update fails to boot, RAUC automatically rolls back to the previous working slot.

Tip

To update to a specific version rather than the latest:

ha os update --version 14.3

Managing Boot Slots

HAOS uses an A/B partition scheme with two kernel and two system slots. You can switch between them:

ha os boot-slot other

This reboots into the alternate slot. Use this to roll back to a previous OS version or test a different slot.

To check the current RAUC slot status at the system level:

rauc status

Note

The rauc status command shows detailed information about both boot slots including version, boot status (good/bad), and which slot is currently active. The active slot is listed as kernel.0 in the boot primary field.

Viewing System Logs

Access system logs through the journal:

ha host logs

For Supervisor-specific logs:

ha su logs

For kernel messages:

dmesg

Checking Service Status

View the status of all systemd services:

systemctl --no-pager -l status -a

Check for any failed services:

systemctl --no-pager -l list-units --state=failed
0 loaded units listed.

Warning

If any services show as failed, note the service name and check its logs with journalctl -u <service-name>. Common failures after updates are documented in the Troubleshooting section.

Checking Network Connectivity

Verify the system has internet connectivity:

nmcli network connectivity check
full

You can also verify from within the Supervisor container:

curl -f https://checkonline.home-assistant.io/online.txt
NetworkManager is online

5. Common Tasks

Task: Create and Restore a Backup

Goal: Create a full system backup and restore it if needed.

Steps:

  1. Create a backup:
ha backups new
slug: abc123de
  1. List available backups:
ha backups list
  1. Restore a backup (including a specific add-on):
ha backups restore abc123de --app core_ssh
  1. Restore a specific folder from a backup:
ha backups restore abc123de --folders ssl

If it fails: Check that the data partition has sufficient free space with df -h /mnt/data.

Task: Move the Data Disk to External Storage

Goal: Move the HAOS data partition to an external USB drive or SSD for better performance and storage capacity.

Steps:

  1. Connect the external drive to the device
  2. Use the Home Assistant CLI to identify the drive:
ha os datadisk list
  1. Move the data disk:
ha os datadisk move /dev/sda

Caution

Moving the data disk erases all data on the target drive. This operation requires a reboot and cannot be undone easily. Create a backup before proceeding.

Verify: After reboot, confirm the new data disk:

ha os info

The data_disk field should show the new device path.

Task: Configure a Static IP Address

Goal: Set a static IP instead of DHCP.

Steps:

  1. Identify the network interface:
ha network info
  1. Configure the static IP:
ha network update enp0s3 --ipv4-method static --ipv4-address 192.168.1.100/24 --ipv4-gateway 192.168.1.1 --ipv4-nameserver 8.8.8.8

Verify:

ha network info

Task: Enable SSH Access

Goal: Access the HAOS command line remotely.

Steps:

  1. Install the SSH add-on from the Home Assistant Add-on Store
  2. Configure a password or authorized keys in the add-on configuration
  3. Start the add-on
  4. Connect via SSH:
ssh [email removed] -p 22222

Tip

The ha CLI is available directly in the SSH session. For low-level OS access, use login at the console prompt to enter the host shell.

Task: Check and Update Supervisor Components

Goal: Ensure all Supervisor components are up to date.

Steps:

  1. Check component versions:
ha supervisor info
  1. Update individual components:
ha supervisor update
ha dns update
ha audio update
ha cli update
ha observer update
ha multicast update
  1. Verify no errors in the resolution center:
ha resolution info

If it fails: If an update reports "Another job is running," wait for the current operation to complete and retry.

Task: Reset the System (Factory Wipe)

Goal: Reset HAOS to a clean state, removing all user data.

Caution

This permanently deletes all Home Assistant configuration, add-ons, backups, and user data. This cannot be undone.

Steps:

  1. From the host console or SSH:
ha os wipe-data
  1. The system reboots and reinitializes with a fresh data partition.

6. Troubleshooting

Diagnostic Decision Tree

System won't boot?
├── LED activity? → Wait 5–20 min for first boot
├── No LED → Check power supply, re-flash image
└── Boots but no web UI → Check network, try IP directly

Web UI unreachable?
├── Can you ping the device? → Check port 8123
├── Can't ping → Check network cable/Wi-Fi, check router DHCP
└── Ping works, port closed → Check container status via console

OS update failed?
├── System rebooted to old version → RAUC rolled back, check logs
├── "Don't have an URL for OTA updates" → Reload Supervisor: ha su reload
└── Stuck in update → Wait, then check ha os info

Error: Bluetooth not working in VirtualBox/Proxmox VM

Cause: Virtual machines do not have native Bluetooth hardware. USB passthrough of Bluetooth adapters may not work correctly with all hypervisors.

Solution:

  1. Use USB passthrough for the physical Bluetooth adapter instead of virtual Bluetooth
  2. In VirtualBox, enable USB 2.0 or 3.0 controller and add a USB device filter for the adapter
  3. In Proxmox, pass through the USB device at the host level

Prevention: For Zigbee/Z-Wave, consider using a networked coordinator (e.g., USB adapter on another machine with ser2net) instead of direct USB passthrough.

Related: #2142

Error: DNS resolution for LAN hostnames broken

Cause: HAOS uses systemd-resolved which may not properly resolve local network hostnames, especially with .local domains that conflict with mDNS.

Solution:

  1. Verify DNS settings: ha network info
  2. Set explicit DNS servers: ha network update <interface> --ipv4-nameserver 192.168.1.1
  3. If using a custom domain, ensure your local DNS server is reachable from the HAOS device

Prevention: Use IP addresses instead of hostnames for critical integrations, or ensure your local DNS infrastructure properly resolves all names.

Related: #2988

Error: OS update fails (e.g., 16.2 to 16.3)

Cause: Certain version transitions may fail due to OTA URL resolution issues or download failures during the update process.

Solution:

  1. Reload the Supervisor to refresh version info:
    ha su reload
    
  2. Retry the update:
    ha os update --version 16.3
    
  3. If it persists, wait for ongoing downloads (Core, Supervisor) to complete before retrying

Prevention: Ensure stable internet connectivity during OS updates. Avoid updating during periods of high network activity.

Related: #4419

Error: OS stuck on old version — unable to update

Cause: The update mechanism may fail if the Supervisor cannot reach the version endpoint or if the OTA URL is not available for the current board.

Solution:

  1. Check connectivity: curl -f https://checkonline.home-assistant.io/online.txt
  2. Reload Supervisor data: ha su reload
  3. Check for available updates: ha os info
  4. If no update URL is available, manually download the .raucb update bundle and apply it locally

Prevention: Keep the Supervisor up to date, as older Supervisors may not correctly resolve OTA URLs for newer OS versions.

Related: #3633

Error: USB subsystem failure after OS update (RPi 4B)

Cause: Kernel updates may introduce regressions affecting USB controller drivers, particularly on Raspberry Pi 4B.

Solution:

  1. Boot into the previous slot: ha os boot-slot other
  2. Check kernel taint status: cat /proc/sys/kernel/tainted (should be 0)
  3. Report the issue with dmesg output if the kernel is tainted

Prevention: Before updating, check the release notes for known hardware-specific issues.

Related: #4627

Error: Samba shares fail on reboot

Cause: The Samba add-on may fail to start if its data directory mount is not ready when the service starts.

Solution:

  1. Restart the Samba add-on from the Home Assistant UI
  2. If persistent, check the data mount: mount | grep /mnt/data
  3. Verify no failed systemd units: systemctl list-units --state=failed

Related: #4459

Error: FQDN resolution errors — .local.hass.io appended to hostnames

Cause: The system intermittently appends .local.hass.io to fully qualified domain names, causing DNS resolution failures.

Solution:

  1. Check /etc/resolv.conf for unexpected search domains
  2. Restart systemd-resolved: systemctl restart systemd-resolved
  3. Verify DNS behavior: resolvectl query example.com

Related: #4434

Error: USB serial device (CP210x / Sonoff Zigbee) disappears periodically in VM

Cause: USB device enumeration issues in KVM/QEMU VMs, particularly with newer HAOS kernel versions.

Solution:

  1. Verify USB passthrough configuration in the hypervisor
  2. Check dmesg for USB disconnect/reconnect messages
  3. Try a different USB controller type (e.g., switch from xHCI to EHCI)

Prevention: For VM-based installations, consider using a networked serial-to-TCP solution (ser2net) instead of USB passthrough.

Related: #4595

Warning

After any OS update, always check systemctl list-units --state=failed to catch services that may not have started correctly. The RAUC boot slot rollback only triggers if the boot itself fails, not if individual services fail post-boot.

Error: RPi 5 NVMe — boot slot B always marked bad

Cause: The Raspberry Pi 5 tryboot mechanism may incorrectly mark boot slot B as bad when using NVMe storage.

Solution:

  1. Check RAUC status: rauc status --detailed
  2. If slot B is marked bad, investigate via rauc status mark-good
  3. Verify both slots show correct status

Related: #4632

Error: RPi 4B CPU stuck at max frequency after OS update

Cause: A kernel regression in the cpufreq driver may lock the CPU frequency at maximum, increasing power consumption and heat.

Solution:

  1. Boot into the previous slot: ha os boot-slot other
  2. Verify with cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
  3. Report with dmesg output attached

Related: #4633

Caution

Do not manually flash or modify the boot partition. HAOS uses RAUC for managed updates, and manual changes will break the A/B update mechanism and signature verification.


7. FAQ

General

Q: What is the difference between HAOS and a manual Home Assistant installation on regular Linux?

HAOS is a dedicated, minimal operating system that manages the entire system stack — OS updates, Docker, networking, and the Home Assistant Supervisor. A manual installation gives you more control but requires you to manage all of these components yourself. HAOS is the recommended installation method for most users.

Q: Can I install additional software on HAOS?

HAOS is a read-only, managed operating system. You cannot install packages with apt or yum. Additional functionality should be added through Home Assistant add-ons, which run as Docker containers managed by the Supervisor.

Q: How much disk space does HAOS need?

A minimum of 32 GB is recommended. The OS itself uses approximately 2–4 GB for the system partitions. The data partition (for add-ons, backups, recordings, etc.) grows over time.

Q: Does HAOS support Wi-Fi?

Yes, on hardware with Wi-Fi capabilities (Raspberry Pi, certain USB adapters). Wi-Fi is managed through NetworkManager and can be configured via the Home Assistant UI or CLI.

Updates

Q: What happens if an OS update fails?

HAOS uses an A/B partition scheme with RAUC. Updates are installed to the inactive slot. If the new version fails to boot, the system automatically rolls back to the previous working slot. Your data is never affected by OS updates.

Q: Can I downgrade to a previous OS version?

You can switch to the other boot slot which contains the previous version:

ha os boot-slot other

This reboots into the version that was active before the last update.

Q: How do I disable automatic OS updates?

Automatic OS updates are controlled by the Supervisor. In the updater configuration at /mnt/data/supervisor/updater.json, set:

{"auto_update": false}

Then restart the Supervisor: systemctl restart hassos-supervisor.service

Hardware

Q: Can I use HAOS on a Raspberry Pi with an NVMe drive?

Yes, the Raspberry Pi 5 (rpi5-64 image) natively supports NVMe boot. For the Raspberry Pi 4, NVMe is supported via USB-to-NVMe adapters or PCIe HATs, but boot must start from the SD card with the data disk moved to NVMe.

Q: My data disk is almost full. What can I do?

  1. Remove old backups: check Settings → System → Backups
  2. Remove unused add-ons
  3. Move the data disk to a larger drive: ha os datadisk move /dev/sda
  4. Check Docker disk usage from the console: the docker-disk-check utility at /usr/libexec/docker-disk-check monitors available space

Related: #4607

Q: How do I check if my kernel is tainted?

cat /proc/sys/kernel/tainted

A value of 0 means the kernel is clean. Any non-zero value indicates taint from out-of-tree modules, firmware issues, or other causes.

Networking

Q: Why does homeassistant.local not resolve?

The .local domain uses mDNS (multicast DNS). If your router or network infrastructure blocks multicast traffic, mDNS will not work. Use the IP address directly, or configure your DNS server to resolve the hostname.

Q: How do I fix IPv4 and IPv6 settings affecting each other?

This is a known issue with NetworkManager configuration. When modifying network settings, configure IPv4 and IPv6 independently and avoid changing both protocols in the same ha network update command.

Related: #4637