This weekend, I finally migrated my home automation setup off the Raspberry Pi 4 it’s been running on for the last four years and into an LXC container managed by Proxmox on my Beelink U59 Pro.
I’ve been meaning to do this for a while, and things finally fell into place yesterday when I had a bit of time to spare.
Previous Installments
In case you haven’t been following along for the past seven years, here’s a brief summary of the major milestones so far:
- Part 1 - Sonoff/Tasmota S20 outlets
- Part 2 - Node-RED, Broadlink IR (since discontinued) and security
- Part 3 - debugging and Xiaomi/Aqara Zigbee sensors
- Part 3.5 - a detour through Azure IoT (since discontinued, but fun)
- Part 4 - old Docker setup, Node-RED wizardry and HomeKit accessory spoofing
- Part 4.5 - switched to a Pi 4 and away from Docker
- Part 5 - Push-button Tasmota timers and upgrade to Zigbee 3.0
- Part 5.5 - Zigbee 3.0 firmware updates
Why
It’s mostly about consolidation and cleanup, since I now have one less power plug and Ethernet port in use on my server closet.
Being able to backup everything consistently and migrate the setup to any machine I want (as long as it has an USB port for my Zigbee coordinator) is just icing on the cake.
Although HomeKit hasn’t really improved substantially over the past few years (in fact, the Home app has only gotten worse, and most of my unscheduled interactions are via Siri), homebridge
and zigbee2mqtt
satisfy my relatively simple needs for home automation rather well.
I’ve written about that at length over the years, so the list above should give you a good idea of the finer points of my setup.
But, in short, everything operates 99% on the LAN (with no devices calling home to anyone or relying on outside services to work) while allowing me to do the occasional remote action securely without any new software on our phones, and I quite like it that way.
I also wanted to do a general cleanup of the whole thing from scratch, including renaming all my accessories using a slightly different convention (including renaming them directly in zigbee2mqtt
to make sure names are consistent throughout the stack) and removing redundant accessories, since (for instance) I no longer have the need to have as many temperature sensors around the house now that all my heatpumps have been HomeKit-enabled by the addition of ESP32 modules.
Finally, I was having some trouble keeping things up to date, mostly due to JavaScript packaging vagaries. Every update I wanted to make eventually led to me having to either upgrade NodeJS or fiddle with the latest fashion in package management, so it was time to go back to a Docker-based setup for consistency with the rest of what I’m running–although I am not doing automated updates for this stack.
Why both homebridge
and zigbee2mqtt
don’t have sensible alternatives written in something like Go I have no idea. Even Java would have been better.
How
The actual process was pretty straightforward:
- Backed up all my configuration and data.
- Created an LXC container on u59 with the original hostname and made sure my router updated its local DNS (after some finagling with DHCP), so that the Tasmota devices could connect immediately.
- Configured Proxmox to pass through the USB device for my Zigbee controller.
- Wrote up a
docker-compose.yaml
file to set uphomebridge
,zigbee2mqtt
,mosquitto
andnode-red
. - Restored the config for each in turn, doing minor tweaks as needed.
- Renamed all my Zigbee devices (this makes it easier to manage things on the Home app when HomeKit throws a fit).
- Set up
piku
to manage some MQTT microservices like theplex-listener
that powers my “now playing” display and my homelab homepage (which is now a variant of this little dashboard/homepage I hacked a while back). - Set up backups (both of the complete LXC filesystem and
git
versioning of the configurations) - Started cleaning up old Node-RED flows, removing redundant accessories, etc.
The current filesystem layout is pretty straightforward:
.
|-- README.md
|-- docker-compose.yaml
|-- homebridge
| |-- accessories
| |-- auth.json
| |-- backups (excluded from git)
| |-- config.json
| |-- lgtvKeyFile
| |-- node_modules (excluded from git)
| |-- package.json
| |-- persist (contains bridge data and identifiers)
| |-- startup.sh
| `-- webostv
|-- mosquitto
| |-- data
| `-- log
|-- nodered
| |-- flows.json
| |-- flows_cred.json
| |-- flows_home.json
| |-- homekit-persist (contains data for Node-RED Homekit shims)
| |-- itunes.db
| |-- lib (excluded from git)
| |-- metrics.db (14GB, _definitely_ excluded from git...)
| |-- metrics.db-shm
| |-- metrics.db-wal
| |-- metrics.sql
| |-- node_modules (excluded from git)
| |-- nrchkb
| |-- package-lock.json
| |-- package.json
| |-- projects
| |-- security.db
| `-- settings.js
`-- zigbee2mqtt
|-- configuration.yaml
|-- coordinator_backup.json
|-- database.db
`-- state.json
Next Steps
Right now I’m still removing redundant devices, as well as planning replacing some Tasmota plugs with Zigbee equivalents to improve the mesh coverage.
Another thing I will be doing is replacing some Node-RED flows that do metric logging and MQTT transformations with Python microservices.
I no longer have a need to tweak them, so their behavior can be frozen and any changes better versioned in git
(Node-RED does support git
, but it’s just messy to do some things that way).