Merge branch 'chelsty-runtime-bootstrap'

This commit is contained in:
Oskar Kapala 2026-05-11 21:38:26 +02:00
commit 3606f53553
6 changed files with 209 additions and 0 deletions

60
docs/chelsty-runtime.md Normal file
View file

@ -0,0 +1,60 @@
# CHELSTY Runtime
This document describes the runtime environment and deployment flow for CHELSTY, an offline-capable home automation edge node.
## Runtime Layout
The CHELSTY runtime is located at `/opt/homelab`.
- `/opt/homelab/config/`: Service-specific configurations and compose overrides.
- `/opt/homelab/data/`: Persistent data for services.
- `/opt/homelab/logs/`: Service logs.
### Key Service Locations
- **Mosquitto**: `/opt/homelab/config/mosquitto/`
- **Zigbee2MQTT**: `/opt/homelab/config/zigbee2mqtt/`
## SLZB-06U Integration
CHELSTY uses a SMLIGHT SLZB-06U Zigbee coordinator connected via Ethernet/TCP.
- **Coordinator IP**: 192.168.1.105
- **Port**: 6638
- **Protocol**: TCP (ezsp adapter)
Zigbee2MQTT is configured to connect to this coordinator over the local network.
## Offline & LTE Assumptions
- **WAN Resilience**: All core automation (Zigbee, MQTT) runs locally on CHELSTY.
- **Connectivity**: LTE provides intermittent uplink for remote management and Tailscale access.
- **Home Assistant**: Runs in a separate VM, connecting to the Mosquitto broker on CHELSTY.
## Deployment Flow
1. **Initial Bootstrap**:
Run the bootstrap script on the CHELSTY node:
```bash
./scripts/bootstrap/chelsty-runtime.sh
```
2. **Manual Configuration**:
- Edit `/opt/homelab/config/zigbee2mqtt/.env` with MQTT credentials.
- Add Mosquitto user:
```bash
sudo mosquitto_passwd -b /opt/homelab/data/mosquitto/config/password.txt <user> <password>
```
3. **Service Deployment**:
Use the staged deployment runtime:
```bash
./scripts/deploy/deploy-node.sh chelsty
```
## Recovery Procedure
In case of runtime failure:
1. Verify Docker and Compose plugin: `docker compose version`
2. Re-run bootstrap script to ensure directory structure and basic configs.
3. Check Mosquitto logs: `tail -f /opt/homelab/data/mosquitto/log/mosquitto.log`
4. Verify SLZB-06U reachability: `ping 192.168.1.105`

View file

@ -0,0 +1,11 @@
services:
mosquitto:
volumes:
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
- /opt/homelab/data/mosquitto/config/password.txt:/mosquitto/config/password.txt:ro
# Healthcheck compatibility
healthcheck:
test: ["CMD-SHELL", "mosquitto_sub -t '$SYS/broker/version' -C 1 || exit 1"]
interval: 10s
timeout: 5s
retries: 5

View file

@ -0,0 +1,13 @@
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
# Default listener
listener 1883
allow_anonymous false
password_file /mosquitto/config/password.txt
# Local-only listener by default (inside Docker network, it's open to other containers)
# To expose to Tailscale, one might add:
# listener 1883 <tailscale_ip>

View file

@ -0,0 +1,23 @@
# Zigbee2MQTT configuration for CHELSTY
homeassistant: true
permit_join: false
mqtt:
base_topic: zigbee2mqtt
server: mqtt://mosquitto:1883
user: ${MQTT_USER}
password: ${MQTT_PASSWORD}
serial:
# SLZB-06U network coordinator
port: tcp://192.168.1.105:6638
adapter: ezsp
frontend:
port: 8080
advanced:
network_key: GENERATE
pan_id: GENERATE
ext_pan_id: GENERATE
channel: 11

View file

@ -0,0 +1,13 @@
services:
zigbee2mqtt:
volumes:
- ./configuration.yaml:/app/data/configuration.yaml:ro
environment:
- MQTT_USER=${MQTT_USER}
- MQTT_PASSWORD=${MQTT_PASSWORD}
# Healthcheck is already defined in base service, but we ensure compatibility
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080"]
interval: 10s
timeout: 5s
retries: 3

View file

@ -0,0 +1,89 @@
#!/usr/bin/env bash
# chelsty-runtime.sh - Bootstrap script for CHELSTY edge node runtime
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
RUNTIME_DIR="/opt/homelab"
CHELSTY_CONFIG="$REPO_ROOT/hosts/chelsty/runtime"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
log "Starting CHELSTY runtime bootstrap..."
# 1. Validate Docker availability
if ! command -v docker &> /dev/null; then
error "Docker is not installed. Please install Docker first."
fi
# 2. Validate compose plugin
if ! docker compose version &> /dev/null; then
error "Docker Compose plugin is not installed."
fi
log "Docker and Compose plugin verified."
# 3. Create runtime directories
log "Creating runtime directories in $RUNTIME_DIR..."
sudo mkdir -p "$RUNTIME_DIR/data/mosquitto/config" \
"$RUNTIME_DIR/data/mosquitto/data" \
"$RUNTIME_DIR/data/mosquitto/log" \
"$RUNTIME_DIR/data/zigbee2mqtt/data" \
"$RUNTIME_DIR/config/mosquitto" \
"$RUNTIME_DIR/config/zigbee2mqtt"
# 4. Copy runtime templates if absent
log "Deploying runtime configurations..."
# Mosquitto
if [ ! -f "$RUNTIME_DIR/config/mosquitto/mosquitto.conf" ]; then
sudo cp "$CHELSTY_CONFIG/mosquitto/mosquitto.conf" "$RUNTIME_DIR/config/mosquitto/"
log "Copied mosquitto.conf"
fi
if [ ! -f "$RUNTIME_DIR/config/mosquitto/docker-compose.override.yml" ]; then
sudo cp "$CHELSTY_CONFIG/mosquitto/docker-compose.override.yml" "$RUNTIME_DIR/config/mosquitto/"
fi
# Zigbee2MQTT
if [ ! -f "$RUNTIME_DIR/config/zigbee2mqtt/configuration.yaml" ]; then
sudo cp "$CHELSTY_CONFIG/zigbee2mqtt/configuration.yaml" "$RUNTIME_DIR/config/zigbee2mqtt/"
log "Copied zigbee2mqtt configuration.yaml"
fi
if [ ! -f "$RUNTIME_DIR/config/zigbee2mqtt/docker-compose.override.yml" ]; then
sudo cp "$CHELSTY_CONFIG/zigbee2mqtt/docker-compose.override.yml" "$RUNTIME_DIR/config/zigbee2mqtt/"
fi
# 5. Create missing .env files from examples
log "Checking for environment files..."
if [ ! -f "$RUNTIME_DIR/config/zigbee2mqtt/.env" ]; then
warn "Creating template .env for Zigbee2MQTT. PLEASE EDIT IT!"
echo "MQTT_USER=admin" | sudo tee "$RUNTIME_DIR/config/zigbee2mqtt/.env" > /dev/null
echo "MQTT_PASSWORD=password" | sudo tee -a "$RUNTIME_DIR/config/zigbee2mqtt/.env" > /dev/null
fi
# 6. Ensure password file exists for Mosquitto
if [ ! -f "$RUNTIME_DIR/data/mosquitto/config/password.txt" ]; then
log "Creating empty mosquitto password file..."
sudo touch "$RUNTIME_DIR/data/mosquitto/config/password.txt"
warn "Mosquitto password file is empty. Use 'mosquitto_passwd' to add users."
fi
log "Bootstrap complete!"
echo -e "\n${YELLOW}Next-step instructions:${NC}"
echo "1. Edit $RUNTIME_DIR/config/zigbee2mqtt/.env with real credentials."
echo "2. Add Mosquitto user: sudo mosquitto_passwd -b $RUNTIME_DIR/data/mosquitto/config/password.txt <user> <password>"
echo "3. Deploy services using the homelab deployment framework:"
echo " ./scripts/deploy/deploy-node.sh chelsty"
echo "4. Verify Zigbee2MQTT logs to ensure it connects to SLZB-06U."
echo "5. Check Home Assistant (separate VM) for MQTT discovery."