Running Home Assistant on a Raspberry Pi 3B in 2026 is an exercise in strict resource management. While the Pi 4 and Pi 5 have become the standard recommendations, thousands of makers still have Pi 3B and 3B+ boards sitting in their parts bins. The direct answer to whether you can run it is yes, but you must aggressively manage the 1GB RAM limitation and bypass the default SD-card I/O bottlenecks. Home Assistant OS (HAOS) has grown significantly, and a stock Pi 3B configuration will choke on database writes and add-on memory leaks within weeks.
This guide bypasses the generic 'flash the image and wait' advice. We will cover the exact hardware tweaks required to keep a Pi 3B stable, map the GPIO UART pins for custom microcontroller sensors, provide a complete Python MQTT bridge script, and debug the most common serial permission errors that brick custom integrations.
The 2026 Reality: Pi 3B Hardware vs. Home Assistant Bloat
The primary bottleneck on the Raspberry Pi 3B (and 3B+) is the 1GB LPDDR2 RAM. Modern Home Assistant Core, combined with the Supervisor and a single add-on like Node-RED or Frigate, will easily exceed 1GB. When Linux runs out of RAM, it invokes the OOM (Out of Memory) killer, which usually assassinates the Home Assistant Core container, resulting in a stuck 'Loading data' screen.
| Specification | Raspberry Pi 3B | Raspberry Pi 3B+ | HAOS 2026 Minimum |
|---|---|---|---|
| RAM | 1GB LPDDR2 | 1GB LPDDR2 | 2GB (4GB Recommended) |
| CPU | 1.2GHz Quad-core | 1.4GHz Quad-core | 1.5GHz+ Quad-core |
| Network | 10/100 Ethernet | Gigabit (over USB 2.0) | Gigabit Ethernet |
| Boot Media | microSD | microSD / USB | USB SSD / NVMe |
To survive on 1GB, you must use the Home Assistant CLI to increase the swap file size. Connect a keyboard and monitor to your Pi, log into the HAOS prompt, and run ha os options --swap-size 2048 to allocate a 2GB swap file on your storage drive. This prevents OOM crashes during heavy automations or nightly backups.
Parts List & GPIO Pin Mapping for Custom Sensors
Integrating custom microcontroller sensors (like an Arduino reading a PMS5003 particulate sensor or an MH-Z19 CO2 sensor) directly into the Pi's GPIO headers bypasses the need for external USB-to-Serial adapters. Below is the exact bill of materials and pinout for this build.
Exact Parts List
- Compute Board: Raspberry Pi 3B+ V1.1 (The 3B+ is preferred over the 3B due to better thermal throttling and USB 2.0 bus improvements).
- Storage: Samsung EVO Plus 128GB microSD (High endurance required) OR a 120GB SATA SSD via a Sabrent USB 3.0 to SATA adapter (strongly recommended).
- Zigbee Coordinator: Sonoff Zigbee 3.0 USB Dongle Plus (P-Version / CC2652P). Avoid the E-Version (EFR32) as it requires heavier Silicon Labs multiprotocol add-ons that will crash a 1GB Pi.
- Logic Level Shifter: BSS138 bidirectional logic level shifter (Required if your sensor operates at 5V logic, as the Pi 3B GPIO is strictly 3.3V tolerant).
GPIO UART Pin Mapping
The Pi 3B uses the hardware UART (ttyAMA0) for Bluetooth by default, leaving the mini UART (ttyS0) for the GPIO pins. The mini UART lacks a configurable baud rate clock, which causes data corruption with microcontrollers. We must map the hardware UART back to the GPIO pins.
| Pi 3B+ Physical Pin | BCM GPIO | Function | Connection to Sensor/Arduino |
|---|---|---|---|
| Pin 8 | GPIO 14 (TXD) | Transmit Data | Connect to Sensor RX |
| Pin 10 | GPIO 15 (RXD) | Receive Data | Connect to Sensor TX |
| Pin 6 | GND | Ground Reference | Connect to Sensor GND |
Custom Integration: Python MQTT Bridge for Serial Sensors
Because Home Assistant OS is a containerized environment, you cannot run raw Python scripts directly on the host OS reliably. The best practice for the Pi 3B is to run a lightweight Docker container or use the 'Advanced SSH & Web Terminal' add-on to run a Python script that reads the serial port and publishes to Home Assistant's Mosquitto MQTT broker.
The following complete Python script targets the Raspberry Pi 3B+ with the hardware UART overlay enabled. It reads a comma-separated string (e.g., 22.5,45.0) from an Arduino connected to the GPIO UART and publishes it to MQTT with robust error handling.
import serial
import paho.mqtt.client as mqtt
import time
import json
import logging
# --- PIN & HARDWARE DEFINITIONS ---
# Target Board: Raspberry Pi 3B+ (Hardware UART enabled via disable-bt overlay)
# Physical Pin 8 (GPIO 14 / TXD) -> Connect to Sensor RX
# Physical Pin 10 (GPIO 15 / RXD) -> Connect to Sensor TX
# Note: Pi 3B logic is 3.3V. Ensure sensor is 3.3V or use a BSS138 level shifter.
UART_PORT = '/dev/ttyAMA0'
BAUD_RATE = 9600
MQTT_BROKER = 'core-mosquitto' # Default HAOS internal MQTT hostname
MQTT_PORT = 1883
MQTT_USER = 'your_ha_mqtt_user'
MQTT_PASS = 'your_ha_mqtt_password'
TOPIC_TEMP = 'homeassistant/sensor/pi3b_custom/temp'
TOPIC_HUM = 'homeassistant/sensor/pi3b_custom/humidity'
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def on_connect(client, userdata, flags, rc):
if rc == 0:
logging.info('Connected to HA MQTT Broker')
else:
logging.error(f'MQTT Connection failed with code {rc}')
client = mqtt.Client(client_id='pi3b_uart_bridge')
client.username_pw_set(MQTT_USER, MQTT_PASS)
client.on_connect = on_connect
try:
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_start()
except Exception as e:
logging.critical(f'Failed to connect to MQTT: {e}')
exit(1)
def read_serial_data():
try:
with serial.Serial(UART_PORT, BAUD_RATE, timeout=2) as ser:
logging.info(f'Listening on {UART_PORT}...')
while True:
try:
line = ser.readline().decode('utf-8').strip()
if line and ',' in line:
parts = line.split(',')
if len(parts) == 2:
temp = float(parts[0])
hum = float(parts[1])
# Publish with HA MQTT discovery compatible JSON
client.publish(TOPIC_TEMP, json.dumps({'value': temp, 'unit': 'C'}))
client.publish(TOPIC_HUM, json.dumps({'value': hum, 'unit': '%'}))
logging.debug(f'Published: Temp={temp}, Hum={hum}')
except ValueError:
logging.warning('Received malformed data from UART, skipping.')
except serial.SerialException as se:
logging.error(f'Serial read error: {se}')
time.sleep(5)
except serial.SerialException as e:
logging.critical(f'Fatal Serial Error: {e}')
raise
if __name__ == '__main__':
read_serial_data()
Debugging: Fixing the UART Permission Denied Error
When you first attempt to run the script above or configure a Zigbee dongle on the GPIO header, you will almost certainly hit this exact error string:
serial.serialutil.SerialException: [Errno 13] Permission denied: '/dev/ttyAMA0'
This happens because the Pi 3B's hardware UART is mapped to the Bluetooth module by default, and the /dev/ttyAMA0 device node is either locked by the hciuart service or restricted to the dialout group.
Ranked Causes and Fixes
- Bluetooth UART Conflict (Most Likely): The OS is using
ttyAMA0for Bluetooth. Fix: You must disable Bluetooth to free up the hardware UART for the GPIO pins. If running Raspberry Pi OS Lite alongside HA Container, adddtoverlay=disable-btto/boot/firmware/config.txtand runsudo systemctl disable hciuart. If running HAOS, you must use a USB-to-Serial adapter instead, as HAOS does not exposeconfig.txteasily. - Missing Group Permissions: Your user is not in the
dialoutgroup. Fix: Runsudo usermod -a -G dialout $USERand reboot. - Mini UART Fallback: The system fell back to
ttyS0. Fix: Change your Python script to use/dev/ttyS0, but be aware that baud rates may drift if the core clock changes. Addcore_freq=250toconfig.txtto stabilize the mini UART clock.
1. Run
ls -l /dev/tty* to verify which user/group owns the port.2. Run
vcgencmd get_mem and dmesg | grep -i oom to ensure the kernel isn't silently killing your Python script due to the 1GB RAM limit.3. Run
raspi-config -> Interface Options -> Serial Port. Ensure 'Login shell' is NO, and 'Serial port hardware' is YES.
Extending and Simplifying Your Pi 3B Build
Once your custom sensors are flowing into Home Assistant via MQTT, you need to manage the database to prevent the Pi 3B from grinding to a halt.
How to Simplify: By default, Home Assistant uses SQLite. On a Pi 3B with an SD card, SQLite write amplification will kill the card. Go to Settings > System > Recorder and set the 'Purge keep days' to 5. Exclude high-frequency entities (like your custom MQTT sensor if it updates every second) from the recorder by adding them to the exclude list in configuration.yaml. This stops the database from ballooning past 500MB.
How to Extend: If you need long-term data storage, do not run the MariaDB add-on on the Pi 3B itself; it will consume 400MB+ of RAM just idling. Instead, extend your build by hosting a PostgreSQL or MariaDB instance on a separate NAS or old laptop on your network, and point the Home Assistant Recorder integration to that external database via the db_url parameter. This offloads the heavy I/O and RAM usage, allowing the Pi 3B to focus purely on Zigbee processing and automation execution.
Frequently Asked Questions
Is the Raspberry Pi 3B still viable for Home Assistant in 2026?
Yes, but only as a dedicated, streamlined node. It is viable if you boot from a USB SSD, use an external database, and avoid heavy add-ons like Frigate, Plex, or local LLMs. If you attempt to run a 'kitchen sink' setup with 20+ add-ons, the 1GB RAM will cause daily crashes. For heavy setups, upgrade to a Pi 4 (4GB) or a used Dell OptiPlex micro PC.
Why does my Pi 3B take 10 minutes to boot Home Assistant OS?
A 10-minute boot time on a Pi 3B is almost always caused by SD card I/O throttling or a corrupted filesystem forcing fsck repairs on boot. The Pi 3B's SD card interface is limited to roughly 25MB/s. When HAOS attempts to load the Supervisor, Core, and initialize the SQLite database simultaneously, the I/O queue maxes out. Switching to a USB 3.0 SATA SSD reduces boot times to under 90 seconds.
Can I use a Raspberry Pi 3B for Home Assistant with a Zigbee dongle?
Absolutely. In fact, the Sonoff Zigbee 3.0 USB Dongle Plus (P-Version) runs exceptionally well on the Pi 3B because the CC2652P chip handles most of the Zigbee network routing internally, sparing the Pi's CPU. However, you must use a USB 2.0 extension cable (at least 1 meter long) to move the dongle away from the Pi's HDMI and power circuitry, which generate severe 2.4GHz RF interference that will cripple your Zigbee mesh.
Should I use Home Assistant OS or Docker on the Pi 3B?
For a Pi 3B, Docker (Home Assistant Container) running on Raspberry Pi OS Lite (64-bit) is vastly superior to HAOS. HAOS includes overhead for the Supervisor and add-on management that consumes precious RAM. By running Docker, you strip away the Supervisor overhead, manage your own MQTT and Zigbee2MQTT containers, and can fine-tune the Linux swap file and kernel parameters to squeeze every megabyte of performance out of the 1GB limit. See the official Home Assistant installation docs for the exact Docker compose commands.






