docker and stacks¶
the pi is a standalone docker host. it has its own environment in portainer, and its stacks deploy from git like the swarm's.
docker¶
Docker CE comes from Docker's own apt repository, the same setup get.docker.com creates:
/etc/apt/keyrings/docker.asc
/etc/apt/sources.list.d/docker.list:
deb [arch=arm64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian trixie stable
there is no /etc/docker/daemon.json, and containerd's config is the package
default (disabled_plugins = ["cri"]). nothing is tuned.
portainer agent¶
the agent is started by hand, not from git, because it is what lets portainer deploy everything else here. the command is on add a host.
radios¶
the USB radios are passed to containers by their /dev/serial/by-id/ names, so
they land on the right device whatever order they enumerate in.
| radio | by-id name starts | used by |
|---|---|---|
| Zooz 800 Z-Wave stick | usb-Zooz_800_Z-Wave_Stick_ |
zwave-js-ui |
| Nabu Casa SkyConnect | usb-Nabu_Casa_SkyConnect_v1.0_ |
ser2net |
| Sonoff Zigbee 3.0 USB Dongle Plus | usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_ |
zigbee2mqtt |
containers¶
each stack polls its own deploy/pi-zwave01/<stack> branch, see
stacks in git.
zwave-js-ui¶
zwave-js-ui runs the Z-Wave network on the Zooz 800 stick. Home Assistant's Z-Wave JS integration connects to it.
compose.yml, 23 lines
| network | its own bridge |
| ports | 80 to the UI on 8091, 3000 for the Z-Wave JS websocket Home Assistant uses |
| data | /docker-data/zwavejs2mqtt/store: settings, network keys, node cache |
- renovate never bumps it on its own. it has to stay compatible with Home Assistant's integration, and an upgrade migrates the node database one way. i approve each one when i can watch Home Assistant afterwards
- the store directory keeps its old
zwavejs2mqttname. renaming it means changing the stack too
zigbee2mqtt¶
zigbee2mqtt runs the Zigbee network on the Sonoff dongle and publishes its devices to mosquitto on the swarm.
compose.yml, 14 lines
| network | its own bridge |
| ports | 8080 to the UI |
| data | /docker-data/zigbee2mqtt/data: configuration.yaml, the device database and the coordinator backup |
configuration.yamlnames the broker,mqtt://mqtt.mydomain.com:1883, and the adapter,zstack. the network itself (channel, PAN ID and keys) lives on the dongle and incoordinator_backup.json- keep
coordinator_backup.json. with it, a new container resumes the network. without it, and a config that doesn't match the dongle, zigbee2mqtt forms a new network and every device has to be paired again
ser2net¶
ser2net shares the SkyConnect over the network on TCP port 8000, so Home
Assistant's OpenThread Border Router app can use the radio from its VM.
thread radio has the config and why each line is there.
compose.yml, 19 lines
| network | host |
| ports | 8000 |
| data | /docker-data/ser2net/data/ser2net.yaml |
its healthcheck looks for an established connection on port 8000, so healthy
means a client is attached. unhealthy usually means the app is down, but ser2net
failing to start, read its config or open the radio looks the same. check the
connection first, then its logs.
dozzle agent¶
the dozzle agent serves this host's container logs on port 7007 to the
dozzle hub on the swarm. the certificate pair it
authenticates with is in /docker-data/dozzle.
glances¶
glances serves host metrics for the dashboard on
port 61208. it uses host networking to see the pi's real interfaces, and
mounts an empty directory from the root filesystem read-only to report the pi's
own disk.
/docker-data¶
every stack's state lives under one directory, so one directory is what gets backed up:
| path | holds |
|---|---|
/docker-data/zwavejs2mqtt/store |
the Z-Wave network: settings, keys, node cache, logs |
/docker-data/ser2net/data |
ser2net.yaml |
/docker-data/dozzle |
the dozzle agent's certificate pair |
/docker-data/zigbee2mqtt/data |
zigbee2mqtt config and database |