This guide explains how to deploy Home Assistant Container on a Radxa SBC running Debian or Ubuntu with Docker Compose, then extend it with MQTT, Xiaomi Home, and a GPIO sensor pipeline. It addresses the practical challenges of containerized deployment, LAN discovery, and sensor integration. Keywords: Home Assistant, Docker Compose, MQTT.
The technical specification snapshot provides a quick deployment overview
| Parameter | Details |
|---|---|
| Platform | Radxa SBC |
| Operating System | Debian / Ubuntu |
| Deployment Method | Docker Compose |
| Network Mode | host |
| Core Services | Home Assistant, Mosquitto |
| Extension Capabilities | Xiaomi Home, I2C sensors, MQTT auto-discovery |
| Core Dependencies | docker.io, Docker Compose plugin, git, paho-mqtt, smbus2 |
| Protocols | HTTP, MQTT, I2C, OAuth 2.0 |
| GitHub Stars | Not provided in the original article |
This architecture fits ARM single-board computers used for home automation infrastructure
Home Assistant Container includes only Home Assistant Core. It does not include Supervisor or Add-ons. That makes the system lighter, but capabilities such as MQTT, ESPHome, Node-RED, and Zigbee2MQTT must be orchestrated as separate containers.
This model works especially well on a Radxa SBC: the host handles hardware access and systemd lifecycle management, while containers run application services. This approach preserves GPIO and I2C flexibility without piling large application dependencies onto the host OS.
Install Docker and the Compose runtime first
sudo apt update
sudo apt install -y docker.io docker-compose-plugin git
sudo systemctl enable --now docker
# Add the current user to the docker group so container commands can run without sudo
sudo usermod -aG docker $USER
newgrp docker
docker version
These commands install the container runtime, enable Docker at boot, and configure user permissions.
Note that Home Assistant officially requires Docker Engine 23.0.0 or later. If your distribution repository ships an older version, switch to Docker’s official repository.
A clean directory and configuration layout reduces long-term maintenance complexity
It is a good practice to keep all data under /opt/homeassistant and reserve a dedicated directory for sensor scripts. This makes backup, migration, and upgrades easier to manage.
/opt/homeassistant/
├── docker-compose.yml
├── config/
├── mosquitto/
│ ├── config/
│ │ └── mosquitto.conf
│ ├── data/
│ └── log/
└── sensors/
└── sht31_mqtt.py
This structure explicitly separates container configuration, persistent data, and host-based data collection scripts.
Create the directories and write the Mosquitto configuration
sudo mkdir -p /opt/homeassistant/config
sudo mkdir -p /opt/homeassistant/mosquitto/config
sudo mkdir -p /opt/homeassistant/mosquitto/data
sudo mkdir -p /opt/homeassistant/mosquitto/log
sudo mkdir -p /opt/homeassistant/sensors
sudo chown -R $USER:$USER /opt/homeassistant
cd /opt/homeassistant
This step creates the host-side directories required for Home Assistant, the MQTT broker, and the sensor collection scripts.
listener 1883 0.0.0.0
allow_anonymous true
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
This Mosquitto configuration is suitable for quick validation. In production, disable anonymous access and enable username/password authentication.
Using host networking improves LAN auto-discovery reliability
Home Assistant depends on discovery protocols such as mDNS and SSDP. In most home network deployments, network_mode: host is simpler than bridge mode and allows containers to access the host network stack directly.
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
restart: unless-stopped
network_mode: host
privileged: true
environment:
TZ: Asia/Shanghai
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
mosquitto:
container_name: mosquitto
image: eclipse-mosquitto:2
restart: unless-stopped
network_mode: host
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
This Compose file starts both Home Assistant and Mosquitto and persists their configuration through bind mounts.
docker compose up -d
docker compose ps
Use these commands to start the services in the background and verify container status.
Open http://<SBC-IP>:8123 in your browser to complete initialization. Then add the MQTT integration in Home Assistant, using 127.0.0.1 as the broker and 1883 as the port.
The Xiaomi Home integration belongs in custom_components, not Add-ons
ha_xiaomi_home is a custom integration, not an Add-on. You must install it directly into the custom_components path under the Home Assistant configuration directory.
cd /opt/homeassistant/config
git clone https://github.com/XiaoMi/ha_xiaomi_home.git
cd ha_xiaomi_home
./install.sh /opt/homeassistant/config
cd /opt/homeassistant
docker compose restart homeassistant
These commands pull the Xiaomi-maintained integration source and install it into the /config directory mapped into the container.
After installation, go to Settings -> Devices & services -> Add integration -> Xiaomi Home in Home Assistant and complete the OAuth 2.0 login flow. The configuration directory stores tokens, device metadata, and certificates, so you must protect /opt/homeassistant/config carefully.
If you need to upgrade Xiaomi Home, switch to a specific tag
cd /opt/homeassistant/config/ha_xiaomi_home
git fetch --tags
git checkout <version-tag>
./install.sh /opt/homeassistant/config
cd /opt/homeassistant
docker compose restart homeassistant
This workflow is useful for rollbacks or version pinning, helping you avoid compatibility issues during integration upgrades.
Connecting an I2C temperature and humidity sensor over GPIO is the most practical edge extension
On a Radxa SBC, I2C sensors such as the SHT31, AHT20, and BME280 are typically more stable than DHT11 or DHT22 modules. The wiring principle is straightforward: connect VCC to 3.3V, GND to ground, and SDA/SCL to the matching I2C pins.
sudo apt update
sudo apt install -y i2c-tools python3-pip
ls /dev/i2c-*
sudo i2cdetect -y 1
pip3 install --user paho-mqtt smbus2
This step verifies that the I2C bus exists, scans for device addresses, and installs the libraries required for MQTT publishing and SMBus access.
The data collection script reads the sensor and publishes MQTT auto-discovery messages
#!/usr/bin/env python3
import json
import time
import paho.mqtt.client as mqtt
from smbus2 import SMBus
MQTT_HOST = "127.0.0.1"
MQTT_PORT = 1883
I2C_BUS = 1
SHT31_ADDR = 0x44
STATE_TOPIC = "radxa/sbc/sht31/state"
AVAILABILITY_TOPIC = "radxa/sbc/sht31/availability"
def read_sht31():
with SMBus(I2C_BUS) as bus:
bus.write_i2c_block_data(SHT31_ADDR, 0x24, [0x00]) # Send the single-shot high-repeatability measurement command
time.sleep(0.02) # Wait for the sensor to complete sampling
data = bus.read_i2c_block_data(SHT31_ADDR, 0x00, 6)
raw_temperature = data[0] << 8 | data[1]
raw_humidity = data[3] << 8 | data[4]
temperature = -45 + 175 * raw_temperature / 65535 # Convert to degrees Celsius
humidity = 100 * raw_humidity / 65535 # Convert to relative humidity
return round(temperature, 1), round(humidity, 1)
def main():
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.connect(MQTT_HOST, MQTT_PORT, 60)
client.publish(AVAILABILITY_TOPIC, "online", retain=True)
while True:
temperature, humidity = read_sht31()
payload = {"temperature": temperature, "humidity": humidity}
client.publish(STATE_TOPIC, json.dumps(payload), retain=True) # Publish the state to MQTT
client.loop(timeout=1.0)
time.sleep(30) # Sample every 30 seconds
if __name__ == "__main__":
main()
This script reads SHT31 data over I2C and publishes it to the local MQTT broker on a fixed interval.
chmod +x /opt/homeassistant/sensors/sht31_mqtt.py
python3 /opt/homeassistant/sensors/sht31_mqtt.py
Use these commands to test whether the script can collect and publish data correctly.
Running the host-side sensor script under systemd is better for long-term operation
Running GPIO and I2C collection scripts on the host instead of inside a container reduces device-mapping complexity and aligns better with standard Linux service management.
[Unit]
Description=Radxa SHT31 MQTT publisher
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/python3 /opt/homeassistant/sensors/sht31_mqtt.py
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
This unit file ensures that the sensor script starts automatically after boot and restarts if it exits unexpectedly.
sudo systemctl daemon-reload
sudo systemctl enable --now radxa-sht31-mqtt.service
sudo systemctl status radxa-sht31-mqtt.service
This step places the script under the systemd lifecycle, which is ideal for stable 24×7 operation.
The Docker Compose model replaces Add-ons with standalone containers for greater flexibility
In the Container installation model, Mosquitto, Node-RED, ESPHome, Zigbee2MQTT, MariaDB, InfluxDB, and Grafana should all be added as independent services in docker-compose.yml. The advantages are clear service boundaries and easier migration. The tradeoff is that you must manage logs, upgrades, and backups yourself.
Daily maintenance should be standardized into a minimal command set
cd /opt/homeassistant
docker compose ps
docker compose logs -f homeassistant
docker compose logs -f mosquitto
docker compose pull
docker compose up -d
docker compose restart homeassistant
These commands cover status inspection, log tracing, image upgrades, and service restarts—the most common maintenance loop.
FAQ
Why choose Home Assistant Container instead of Home Assistant OS?
Home Assistant Container is a better fit for a Radxa SBC that already runs Debian or Ubuntu. It preserves host-level control and makes it easier to work with GPIO, I2C, and custom scripts. The tradeoff is that you must manage MQTT, backups, and extension services yourself.
Why recommend network_mode: host?
Home Assistant depends heavily on discovery mechanisms such as mDNS and SSDP in home networks. Host mode reduces multicast and port-mapping issues and also makes it easier to access the local MQTT broker through 127.0.0.1:1883.
Why not place the sensor script directly inside the Home Assistant container?
Direct host access to I2C and GPIO is simpler, requires fewer permissions and device mappings, and creates a cleaner fault boundary. Let the container handle the automation platform while the host handles hardware collection. That separation of responsibilities is usually more reliable.
Core summary: This guide reconstructs a complete deployment pattern for Home Assistant Container on a Radxa SBC running Debian or Ubuntu. It covers Docker Compose orchestration, Mosquitto MQTT integration, Xiaomi Home custom integration installation, and SHT31 temperature and humidity sensor access over the 40-pin GPIO plus I2C, with systemd used for persistent host-side operation.