initial commit fixed
parent
eeee51dabe
commit
0cc22f82b3
|
|
@ -0,0 +1,51 @@
|
||||||
|
# AI-Managed Smart Home
|
||||||
|
|
||||||
|
Local-first, open-source smart home: Home Assistant + Zigbee + RuView (CSI presence)
|
||||||
|
+ Bermuda (BLE identity) + local LLM (Ollama) + Frigate (peephole face recognition)
|
||||||
|
+ Grocy (kitchen kiosk) + Nextcloud calendar sync.
|
||||||
|
|
||||||
|
See [`docs/project-plan.md`](docs/project-plan.md) for the full hardware list,
|
||||||
|
software stack, and phased implementation plan.
|
||||||
|
|
||||||
|
## Repo layout
|
||||||
|
|
||||||
|
```
|
||||||
|
docs/ Project plan and design notes
|
||||||
|
hosts/
|
||||||
|
container-host/ Docker Compose stack: HA, Mosquitto, Zigbee2MQTT,
|
||||||
|
Frigate, Grocy, Node-RED, monitoring, etc.
|
||||||
|
configs/ Per-service config files (mosquitto.conf, etc.)
|
||||||
|
scripts/ Host setup / bootstrap scripts
|
||||||
|
llm-host/ Ollama + GPU host setup (separate physical machine)
|
||||||
|
firmware/
|
||||||
|
ruview/ RuView ESP32-S3 CSI presence node configs
|
||||||
|
esphome-ble-proxy/ ESPHome configs for Bermuda BLE proxy nodes
|
||||||
|
identity/ Face<->MAC<->name correlation logic (Node-RED flow
|
||||||
|
export once stabilized, or a Python service)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
- [x] Project plan drafted
|
||||||
|
- [x] Container host setup script v1 (HA, Mosquitto, Zigbee2MQTT USB, Frigate, Grocy)
|
||||||
|
- [ ] Add Node-RED + monitoring (Netdata) + dashboard (Homepage) + ntfy + Portainer to compose stack
|
||||||
|
- [ ] Bermuda / ESPHome BLE proxy configs
|
||||||
|
- [ ] RuView node configs
|
||||||
|
- [ ] Frigate peephole camera config (real RTSP details)
|
||||||
|
- [ ] Grocy kiosk (Pi + touchscreen) setup
|
||||||
|
- [ ] LLM host (Ollama) setup script
|
||||||
|
- [ ] CalDAV / Nextcloud calendar integration notes
|
||||||
|
- [ ] Identity correlation flow (Node-RED)
|
||||||
|
- [ ] Backup (restic) setup
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd hosts/container-host/scripts
|
||||||
|
sudo ./setup-container-host.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit the variables at the top of the script first (timezone, Zigbee USB device
|
||||||
|
path, Mealie/hardware-accel toggles). See `docs/project-plan.md` for the full
|
||||||
|
phased rollout order — don't skip straight to Phase 4+ automations before the
|
||||||
|
Phase 2 reactive baseline (presence -> light, no LLM in the loop) is working.
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
# AI-Managed Smart Home — Full Build Plan (v2)
|
||||||
|
|
||||||
|
Local-first, open-source stack: Home Assistant + RuView presence + Bermuda BLE identity + local LLM (Ollama) + Zigbee sensors/lighting + Frigate (peephole face recognition) + Grocy kitchen kiosk + Nextcloud calendar sync + Node-RED glue logic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Hardware
|
||||||
|
|
||||||
|
### 1.1 Already in your possession
|
||||||
|
| Item | Use in this build |
|
||||||
|
|---|---|
|
||||||
|
| Framework 12 (primary) | Dev machine, dotfiles/Claude Code work |
|
||||||
|
| ThinkPad T440p (secondary) | Spare compute, webcam presence daemon testing |
|
||||||
|
| Nextcloud instance | Calendar backend (CalDAV sync target) |
|
||||||
|
| "Scraps" x86 machine | Candidate for LLM host (CPU-only tier) or Proxmox host |
|
||||||
|
| Haozee Zigbee USB dongle (CC2652P + CH340C) | Zigbee coordinator — USB passthrough into container, adapter type `zstack` |
|
||||||
|
|
||||||
|
### 1.2 Core AI / HA hosts
|
||||||
|
| Item | Est. Price (EUR) | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Mini PC / SFF for Home Assistant + attached services (Raspberry Pi 5, 8GB) | €80 | Runs HA Core (Container), Mosquitto, Zigbee2MQTT, Frigate, Grocy, Node-RED, monitoring |
|
||||||
|
| SSD for boot (USB3, 128GB+) | €20 | Avoid SD card for reliability |
|
||||||
|
| Official Pi 5 PSU + case | €25 | |
|
||||||
|
| Used RTX 3060 12GB | €200–250 | LLM inference host (Qwen2.5-14B Q4) |
|
||||||
|
| Cheap SFF/tower host for GPU (spare PCIe x16 slot, 170W+ on 12V rail) | €40–60 | Only needs to feed the GPU |
|
||||||
|
| *(Fallback: skip GPU)* Use existing "scraps" x86 box, CPU-only Ollama | €0 | Slower (5–10 tok/s), fine to validate before buying GPU |
|
||||||
|
|
||||||
|
**Subtotal (with GPU tier): ~€365–435** | **Subtotal (CPU-only fallback): ~€125**
|
||||||
|
|
||||||
|
### 1.3 Zigbee backbone
|
||||||
|
Already covered — using your existing Haozee CC2652P USB dongle. No coordinator purchase needed. *Contingency: if Zigbee2MQTT can't establish a network, the dongle may need CC2652P coordinator firmware reflashed (generic-branded gateways sometimes ship with non-coordinator firmware).*
|
||||||
|
|
||||||
|
### 1.4 Zigbee sensors (price per unit — multiply by room count)
|
||||||
|
| Item | Est. Price/unit | Suggested qty | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| innr RB 285 C (Zigbee RGBWW bulb) | €15–20 | 1 per AI-managed room | Tunable 2200K–6500K, acts as Zigbee router |
|
||||||
|
| Sonoff SNZB-02P (temp/humidity) | €10–12 | 1 per room | Avoid older Aqara — mesh drop issues |
|
||||||
|
| Sonoff SNZB-06P (presence/illuminance) or Aqara Light Sensor | €12–15 | 1 per room needing lux data | Feeds LLM brightness decisions |
|
||||||
|
| Sonoff SNZB-04P (door/window contact) | €13–15 | 1 per door/window of interest | Gates automations |
|
||||||
|
| IKEA Vindstyrka (air quality, optional) | ~€30 | 1–2 | Requires Zigbee2MQTT |
|
||||||
|
|
||||||
|
### 1.5 BLE identity layer (Bermuda)
|
||||||
|
| Item | Est. Price/unit | Suggested qty | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| ESP32 board (D1 Mini32 or similar — no CSI needed, just BT+WiFi) | €5–10 | 1 per room for identity resolution | Runs ESPHome `bluetooth_proxy`, separate hardware from RuView nodes |
|
||||||
|
| Fixed-MAC BLE tag per household member (optional but recommended) | €5–8 | 1 per person | More reliable anchor than phone MAC (which randomizes on iOS/Android); Bermuda + HA's Private BLE Device can also resolve phones via IRK if you skip this |
|
||||||
|
|
||||||
|
### 1.6 RuView presence mesh
|
||||||
|
| Item | Est. Price/unit | Suggested qty | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| ESP32-S3 dev board | €8–12 | 1 per room/zone needing CSI presence | Runs RuView firmware — separate boards from the Bermuda BLE proxies above (one chip = one firmware) |
|
||||||
|
|
||||||
|
### 1.7 Door-spy / peephole camera
|
||||||
|
| Item | Est. Price | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Peephole IP camera (ONVIF/RTSP, color, "-IR" variant only if hallway is dark) | €50–65 | Isolate on its own VLAN, block WAN egress |
|
||||||
|
| *(You're handling the physical mounting yourself)* | €0 | |
|
||||||
|
|
||||||
|
### 1.8 Frigate acceleration (optional)
|
||||||
|
| Item | Est. Price | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Hailo-8L (Raspberry Pi 5 AI kit) | €70 | Only if CPU/iGPU isn't keeping up with more cameras later |
|
||||||
|
| *(Default: none needed for 1 camera — use CPU or Intel iGPU/OpenVINO)* | €0 | |
|
||||||
|
|
||||||
|
### 1.9 Kitchen inventory kiosk (camera + touchscreen)
|
||||||
|
| Item | Est. Price | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Raspberry Pi 3B+ or 4 (2–4GB) | €35–50 | Chromium kiosk + camera decode |
|
||||||
|
| 7" official/compatible touchscreen | €30–40 | |
|
||||||
|
| USB webcam w/ macro focus | €10–15 | Barcode scanning via Grocy's browser PWA |
|
||||||
|
| Case/mount for kitchen wall or cupboard | €10–15 | |
|
||||||
|
|
||||||
|
**Subtotal: ~€85–120**
|
||||||
|
|
||||||
|
### 1.10 Deferred / out of scope for now
|
||||||
|
- **Projector + camera tabletop AI surface** — genuinely interesting but high-effort (projector-camera calibration, fingertip touch detection is an active CV research problem, poor legibility with ambient light). If pursued, treat as an isolated experimental side project, not wired into critical automations. Not included in this plan's budget or phases.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Software (all open source / self-hosted)
|
||||||
|
|
||||||
|
| Layer | Software | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| Home automation core | **Home Assistant** (Container install) | Central hub, automations, dashboards |
|
||||||
|
| Zigbee | **Zigbee2MQTT** + **Mosquitto** | Broadest device compatibility, USB passthrough to your CC2652P dongle |
|
||||||
|
| BLE identity | **Bermuda** (HACS) + **ESPHome** (`bluetooth_proxy`) + HA's **Private BLE Device** | Room-level BLE presence, resolves randomized MACs via IRK, feeds `person.*` entities |
|
||||||
|
| Automation glue | **Node-RED** | Visual flows for cross-system logic — home for the face↔MAC identity-correlation logic, easy iteration/debugging |
|
||||||
|
| LLM runtime | **Ollama** | Serves Qwen2.5-14B-Instruct (GPU tier) or Qwen2.5-7B/3B (CPU tier) |
|
||||||
|
| Conversation agent | **HA Ollama conversation integration** | Ties LLM into Assist + AI Task |
|
||||||
|
| Voice STT/TTS | **Wyoming faster-whisper** + **Piper** | Local speech pipeline |
|
||||||
|
| Presence (CSI) | **RuView** (ESP32-S3 firmware + server) | Anonymous room-level presence, feeds gating automations |
|
||||||
|
| Presence (webcam) | Your custom daemon (dotfiles repo) | Desktop-specific, not tied to HA sensors directly |
|
||||||
|
| Camera NVR / face recognition | **Frigate** (0.16+) | Native face recognition, object detection, peephole cam ingest |
|
||||||
|
| Identity store | Small dict/table (SQLite or JSON) — name, face label, associated MACs, confidence | Built up conversationally via LLM tool calls (`propose_person_link`, `confirm_person`, `rename_person`); merges require confirmation, never silent |
|
||||||
|
| Container runtime | **Docker + Docker Compose** | Hosts all of the above |
|
||||||
|
| Inventory / shopping list | **Grocy** | Self-hosted stock + shopping list, native browser barcode scanning |
|
||||||
|
| Meal planning (optional) | **Mealie** | Recipe manager + shopping list + meal-plan calendar |
|
||||||
|
| Calendar backend | **Nextcloud Calendar** (already running) | Source of truth for household schedule |
|
||||||
|
| Calendar bridge | **HA CalDAV integration** | Read/write bridge, `calendar.create_event` supported; keep recurring events created in Nextcloud directly |
|
||||||
|
| Monitoring | **Netdata** | Consistent with your existing Ansible-fleet monitoring evaluation |
|
||||||
|
| Dashboard | **Homepage** or **Homarr** | Single landing page for HA / Grocy / Frigate / Zigbee2MQTT / Node-RED UIs |
|
||||||
|
| Container management | **Portainer** (optional) | GUI over the Docker host |
|
||||||
|
| Notifications | **ntfy** | Self-hosted push, replaces relying on a phone OS's proprietary push channel |
|
||||||
|
| Long-term stats (optional) | **InfluxDB + Grafana** | Only if you want history beyond HA's default recorder retention |
|
||||||
|
| Backup | **restic** | Scheduled encrypted backups of all stateful volumes |
|
||||||
|
| Kiosk browser | **Chromium (kiosk mode)** | Displays Grocy PWA on the kitchen touchscreen |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Implementation Plan
|
||||||
|
|
||||||
|
### Phase 0 — Infrastructure prep
|
||||||
|
1. Decide: Proxmox host (if virtualizing) vs. bare-metal. Given your homelab habits, Proxmox with HAOS/container-host as VMs/LXCs is reasonable.
|
||||||
|
2. Set up a dedicated **camera VLAN** (peephole cam + future cameras), no WAN egress, firewalled from the main LAN.
|
||||||
|
3. Provision the container host (Debian 12 or Raspberry Pi OS Lite).
|
||||||
|
|
||||||
|
### Phase 1 — Core containers + Zigbee
|
||||||
|
1. Docker + Compose stack: Home Assistant, Mosquitto, Zigbee2MQTT (USB passthrough to the Haozee dongle), Node-RED.
|
||||||
|
2. Pair Zigbee sensors room by room: bulb → temp/humidity → illuminance → door/window contact.
|
||||||
|
3. Confirm entities populate correctly in HA.
|
||||||
|
|
||||||
|
### Phase 2 — Presence: RuView + Bermuda, in parallel
|
||||||
|
1. Deploy RuView ESP32-S3 nodes per room (dedicated CSI firmware).
|
||||||
|
2. Separately, flash plain ESP32 boards with ESPHome (`bluetooth_proxy`), install Bermuda via HACS, configure Private BLE Device for phone IRK resolution, and/or distribute fixed-MAC BLE tags per person.
|
||||||
|
3. Build plain HA automations: presence (RuView) on → light on at neutral default; off (with delay) → light off. **Validate this works with the LLM host powered off — this is your safety-net baseline.**
|
||||||
|
|
||||||
|
### Phase 3 — LLM host + conversation agent
|
||||||
|
1. Stand up the GPU host (or CPU fallback) with Ollama, pull Qwen2.5-14B-Instruct (or 7B/3B for CPU).
|
||||||
|
2. Add the Ollama integration in HA, point it at the LLM host over LAN.
|
||||||
|
3. Set up Wyoming faster-whisper + Piper, configure an Assist pipeline.
|
||||||
|
4. Test open-ended conversation and basic tool-calling before wiring into presence logic.
|
||||||
|
|
||||||
|
### Phase 4 — AI-managed brightness/color
|
||||||
|
1. Script triggered after the presence-automation light-on event, calling `ai_task.generate_data` with room/time/occupancy context, requesting structured JSON (`brightness`, `rgb_color`).
|
||||||
|
2. Apply via `light.turn_on`; fallback to neutral default on timeout/error.
|
||||||
|
3. Feed illuminance sensor data into the LLM's exposed-entity list.
|
||||||
|
|
||||||
|
### Phase 5 — Peephole camera + Frigate
|
||||||
|
1. Mount your color camera (your own work), isolate on the camera VLAN.
|
||||||
|
2. Deploy Frigate, add the RTSP stream, enable native face recognition.
|
||||||
|
3. Enroll known faces; automation for known vs. unknown at the door.
|
||||||
|
4. Set conservative confidence thresholds given the narrow FOV/low light.
|
||||||
|
|
||||||
|
### Phase 6 — Identity correlation (face ↔ MAC ↔ name)
|
||||||
|
1. Build the correlation logic as a **Node-RED flow** first: listen to Frigate face-recognition MQTT events + Bermuda/BLE MQTT topics, tally co-occurrence, apply a confidence threshold.
|
||||||
|
2. Expose LLM tool calls (`propose_person_link`, `confirm_person`, `rename_person`) so the LLM can name people conversationally and propose merges — **never auto-commit a merge silently**, require confirmation.
|
||||||
|
3. Once the logic stabilizes, consider porting to a small Python service if it outgrows Node-RED's comfort zone (git/test-ability).
|
||||||
|
|
||||||
|
### Phase 7 — Kitchen inventory kiosk
|
||||||
|
1. Deploy Grocy via Compose.
|
||||||
|
2. Pi + touchscreen running Chromium kiosk mode pointed at Grocy's PWA.
|
||||||
|
3. Attach USB webcam, test in-browser barcode scanning (Open Food Facts lookup).
|
||||||
|
4. Use Grocy's own add/consume UI — no extra hardware/logic needed for the "in vs. out" problem.
|
||||||
|
|
||||||
|
### Phase 8 — Nextcloud calendar sync
|
||||||
|
1. Add HA's CalDAV integration, point at Nextcloud's CalDAV URL.
|
||||||
|
2. Confirm read + write (`calendar.create_event`) both work.
|
||||||
|
3. Expose the calendar entity to the LLM's tool list.
|
||||||
|
4. Gate delete/move actions behind a confirmation step; create recurring events directly in Nextcloud, not via HA.
|
||||||
|
|
||||||
|
### Phase 9 — Observability, dashboard, backup
|
||||||
|
1. Deploy Netdata (or your team's eventual choice from the Netdata/Checkmk evaluation) for container/host monitoring.
|
||||||
|
2. Deploy Homepage/Homarr as a single landing page across all service UIs.
|
||||||
|
3. Deploy ntfy for local push notifications (door alerts, automation failures).
|
||||||
|
4. Set up restic scheduled backups of all stateful volumes (HA config, Zigbee2MQTT device DB, Grocy data, Frigate face embeddings, Node-RED flows).
|
||||||
|
|
||||||
|
### Phase 10 — Optional expansion
|
||||||
|
1. Mealie for meal-plan-aware shopping lists.
|
||||||
|
2. InfluxDB + Grafana if you want longer-term historical dashboards than HA's recorder retains.
|
||||||
|
3. Additional RuView/Bermuda nodes as more rooms are covered.
|
||||||
|
4. Dedicated Frigate accelerator (Hailo-8L) only if you expand beyond 1–2 cameras.
|
||||||
|
|
||||||
|
### Testing checklist before calling any phase "done"
|
||||||
|
- Does the reactive path (presence → light on) work with the LLM host powered off? (It must.)
|
||||||
|
- Does a bad/slow LLM response ever block a light switch? (It must not.)
|
||||||
|
- Are cameras verified to have zero WAN egress?
|
||||||
|
- Does the calendar integration survive a Nextcloud restart without orphaning entities?
|
||||||
|
- Does an identity merge ever get auto-committed without confirmation? (It must not.)
|
||||||
|
|
@ -0,0 +1,319 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Smart Home Container Host Setup
|
||||||
|
# Target: Debian 12 (Bookworm) or Raspberry Pi OS Lite (Bookworm-based)
|
||||||
|
#
|
||||||
|
# Sets up Docker + a compose stack for:
|
||||||
|
# - Home Assistant (Container install)
|
||||||
|
# - Mosquitto (MQTT broker)
|
||||||
|
# - Zigbee2MQTT (talks to your network-attached SLZB-06 coordinator)
|
||||||
|
# - Frigate (NVR + face recognition, for the peephole cam)
|
||||||
|
# - Grocy (self-hosted inventory / shopping list)
|
||||||
|
#
|
||||||
|
# Run as: sudo ./setup-smart-home-host.sh
|
||||||
|
#
|
||||||
|
# EDIT THE VARIABLES BELOW BEFORE RUNNING.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# CONFIGURATION — edit these before running
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
BASE_DIR="/opt/smart-home" # Where all container config/data will live
|
||||||
|
TIMEZONE="Europe/Vienna" # Adjust to your timezone
|
||||||
|
ENABLE_MEALIE="false" # Set to "true" to also deploy Mealie
|
||||||
|
ENABLE_INTEL_HWACCEL="false" # Set to "true" if this host has an Intel iGPU for Frigate
|
||||||
|
|
||||||
|
# --- Zigbee adapter: USB (CC2652P/CH340C, e.g. Haozee/Sonoff Dongle-P style) ---
|
||||||
|
# Run `ls -l /dev/serial/by-id/` AFTER plugging the adapter in, and paste the
|
||||||
|
# full path it shows here. This is more stable across reboots than /dev/ttyUSB0.
|
||||||
|
# Example: /dev/serial/by-id/usb-1a86_USB_Serial-if00-port0
|
||||||
|
ZIGBEE_USB_DEVICE="/dev/serial/by-id/usb-1a86_USB_Serial-if00-port0"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Sanity checks
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "Please run as root (sudo ./setup-smart-home-host.sh)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -qi "debian" /etc/os-release; then
|
||||||
|
echo "Warning: this script targets Debian/Raspberry Pi OS. Proceeding anyway..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -e "$ZIGBEE_USB_DEVICE" ]]; then
|
||||||
|
echo "Warning: $ZIGBEE_USB_DEVICE does not exist yet."
|
||||||
|
echo " Plug in your Zigbee adapter and run 'ls -l /dev/serial/by-id/' to find the correct path,"
|
||||||
|
echo " then edit ZIGBEE_USB_DEVICE at the top of this script before re-running."
|
||||||
|
echo " Continuing anyway — the zigbee2mqtt container just won't start correctly until this is fixed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Smart Home Container Host Setup ==="
|
||||||
|
echo "Base directory: $BASE_DIR"
|
||||||
|
echo "Timezone: $TIMEZONE"
|
||||||
|
echo "Zigbee adapter (USB): ${ZIGBEE_USB_DEVICE}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 1. System update + prerequisites
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "--- Updating system and installing prerequisites ---"
|
||||||
|
apt-get update
|
||||||
|
apt-get upgrade -y
|
||||||
|
apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
gnupg \
|
||||||
|
lsb-release \
|
||||||
|
jq
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 2. Install Docker Engine + Compose plugin (official Docker repo)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo "--- Installing Docker Engine ---"
|
||||||
|
install -m 0755 -d /etc/apt/keyrings
|
||||||
|
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
|
||||||
|
ARCH="$(dpkg --print-architecture)"
|
||||||
|
CODENAME="$(. /etc/os-release && echo "$VERSION_CODENAME")"
|
||||||
|
echo \
|
||||||
|
"deb [arch=${ARCH} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian ${CODENAME} stable" \
|
||||||
|
> /etc/apt/sources.list.d/docker.list
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
|
||||||
|
# Allow the invoking (non-root) user to run docker without sudo, if applicable
|
||||||
|
if [[ -n "${SUDO_USER:-}" ]]; then
|
||||||
|
usermod -aG docker "$SUDO_USER"
|
||||||
|
echo "Added $SUDO_USER to the docker group. Log out/in for it to take effect."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "--- Docker already installed, skipping ---"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 3. Directory structure
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "--- Creating directory structure under $BASE_DIR ---"
|
||||||
|
mkdir -p "$BASE_DIR"/{homeassistant,mosquitto/config,mosquitto/data,mosquitto/log,zigbee2mqtt/data,frigate/config,frigate/media,grocy/config,grocy/data}
|
||||||
|
if [[ "$ENABLE_MEALIE" == "true" ]]; then
|
||||||
|
mkdir -p "$BASE_DIR"/mealie/data
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 4. Mosquitto config
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "--- Writing Mosquitto config ---"
|
||||||
|
cat > "$BASE_DIR/mosquitto/config/mosquitto.conf" <<'EOF'
|
||||||
|
# Basic internal-network broker config.
|
||||||
|
# This trusts anything on your Docker/LAN network. If Mosquitto will ever be
|
||||||
|
# reachable beyond your trusted LAN, add password_file auth before exposing it.
|
||||||
|
listener 1883
|
||||||
|
allow_anonymous true
|
||||||
|
persistence true
|
||||||
|
persistence_location /mosquitto/data/
|
||||||
|
log_dest file /mosquitto/log/mosquitto.log
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 5. Zigbee2MQTT config (pre-seeded for the SLZB-06 network coordinator)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "--- Writing Zigbee2MQTT config ---"
|
||||||
|
cat > "$BASE_DIR/zigbee2mqtt/data/configuration.yaml" <<EOF
|
||||||
|
homeassistant: true
|
||||||
|
permit_join: false
|
||||||
|
mqtt:
|
||||||
|
base_topic: zigbee2mqtt
|
||||||
|
server: 'mqtt://mosquitto:1883'
|
||||||
|
serial:
|
||||||
|
port: '/dev/ttyACM0'
|
||||||
|
adapter: zstack
|
||||||
|
advanced:
|
||||||
|
network_key: GENERATE
|
||||||
|
frontend:
|
||||||
|
port: 8080
|
||||||
|
EOF
|
||||||
|
echo " NOTE: adapter set to 'zstack' for your CC2652P (Haozee/Sonoff Dongle-P style) USB dongle."
|
||||||
|
echo " If Zigbee2MQTT fails to connect, it may need CC2652P coordinator firmware flashed first"
|
||||||
|
echo " (generic-branded gateways sometimes ship with non-coordinator firmware)."
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 6. Frigate config (placeholder — edit before first real use)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "--- Writing Frigate placeholder config ---"
|
||||||
|
cat > "$BASE_DIR/frigate/config/config.yml" <<'EOF'
|
||||||
|
mqtt:
|
||||||
|
host: mosquitto
|
||||||
|
port: 1883
|
||||||
|
|
||||||
|
# Face recognition (Frigate 0.16+)
|
||||||
|
face_recognition:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
cameras:
|
||||||
|
peephole:
|
||||||
|
ffmpeg:
|
||||||
|
inputs:
|
||||||
|
- path: rtsp://USERNAME:PASSWORD@CAMERA_IP:554/STREAM_PATH
|
||||||
|
roles:
|
||||||
|
- detect
|
||||||
|
- record
|
||||||
|
detect:
|
||||||
|
width: 1280
|
||||||
|
height: 720
|
||||||
|
fps: 5
|
||||||
|
record:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Uncomment and adjust if using Intel QuickSync/OpenVINO hardware acceleration:
|
||||||
|
# ffmpeg:
|
||||||
|
# hwaccel_args: preset-vaapi
|
||||||
|
# detectors:
|
||||||
|
# ov:
|
||||||
|
# type: openvino
|
||||||
|
# device: GPU
|
||||||
|
EOF
|
||||||
|
echo " NOTE: edit $BASE_DIR/frigate/config/config.yml with your real camera RTSP URL before starting Frigate."
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 7. docker-compose.yml
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "--- Writing docker-compose.yml ---"
|
||||||
|
|
||||||
|
FRIGATE_DEVICES=""
|
||||||
|
if [[ "$ENABLE_INTEL_HWACCEL" == "true" ]]; then
|
||||||
|
FRIGATE_DEVICES=" devices:
|
||||||
|
- /dev/dri:/dev/dri"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MEALIE_BLOCK=""
|
||||||
|
if [[ "$ENABLE_MEALIE" == "true" ]]; then
|
||||||
|
MEALIE_BLOCK="
|
||||||
|
mealie:
|
||||||
|
image: ghcr.io/mealie-recipes/mealie:latest
|
||||||
|
container_name: mealie
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- \"9925:9000\"
|
||||||
|
volumes:
|
||||||
|
- ${BASE_DIR}/mealie/data:/app/data
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
- ALLOW_SIGNUP=false
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > "$BASE_DIR/docker-compose.yml" <<EOF
|
||||||
|
name: smart-home
|
||||||
|
|
||||||
|
services:
|
||||||
|
homeassistant:
|
||||||
|
image: ghcr.io/home-assistant/home-assistant:stable
|
||||||
|
container_name: homeassistant
|
||||||
|
restart: unless-stopped
|
||||||
|
privileged: true
|
||||||
|
network_mode: host
|
||||||
|
volumes:
|
||||||
|
- ${BASE_DIR}/homeassistant:/config
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
|
||||||
|
mosquitto:
|
||||||
|
image: eclipse-mosquitto:2
|
||||||
|
container_name: mosquitto
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "1883:1883"
|
||||||
|
volumes:
|
||||||
|
- ${BASE_DIR}/mosquitto/config:/mosquitto/config
|
||||||
|
- ${BASE_DIR}/mosquitto/data:/mosquitto/data
|
||||||
|
- ${BASE_DIR}/mosquitto/log:/mosquitto/log
|
||||||
|
|
||||||
|
zigbee2mqtt:
|
||||||
|
image: koenkk/zigbee2mqtt:latest
|
||||||
|
container_name: zigbee2mqtt
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- mosquitto
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- ${BASE_DIR}/zigbee2mqtt/data:/app/data
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
devices:
|
||||||
|
- ${ZIGBEE_USB_DEVICE}:/dev/ttyACM0
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
|
||||||
|
frigate:
|
||||||
|
image: ghcr.io/blakeblackshear/frigate:stable
|
||||||
|
container_name: frigate
|
||||||
|
restart: unless-stopped
|
||||||
|
privileged: true
|
||||||
|
shm_size: "256mb"
|
||||||
|
depends_on:
|
||||||
|
- mosquitto
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
- "8554:8554"
|
||||||
|
- "8555:8555/tcp"
|
||||||
|
- "8555:8555/udp"
|
||||||
|
volumes:
|
||||||
|
- ${BASE_DIR}/frigate/config:/config
|
||||||
|
- ${BASE_DIR}/frigate/media:/media/frigate
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
${FRIGATE_DEVICES}
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
|
||||||
|
grocy:
|
||||||
|
image: lscr.io/linuxserver/grocy:latest
|
||||||
|
container_name: grocy
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "9283:80"
|
||||||
|
volumes:
|
||||||
|
- ${BASE_DIR}/grocy/config:/config
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=${TIMEZONE}
|
||||||
|
${MEALIE_BLOCK}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 8. Bring the stack up
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "--- Starting containers ---"
|
||||||
|
cd "$BASE_DIR"
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Done ==="
|
||||||
|
echo "Services should be reachable at:"
|
||||||
|
echo " Home Assistant : http://<host-ip>:8123"
|
||||||
|
echo " Zigbee2MQTT UI : http://<host-ip>:8080"
|
||||||
|
echo " Frigate : http://<host-ip>:5000"
|
||||||
|
echo " Grocy : http://<host-ip>:9283"
|
||||||
|
if [[ "$ENABLE_MEALIE" == "true" ]]; then
|
||||||
|
echo " Mealie : http://<host-ip>:9925"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Edit $BASE_DIR/frigate/config/config.yml with your real peephole camera RTSP URL, then:"
|
||||||
|
echo " docker compose -f $BASE_DIR/docker-compose.yml restart frigate"
|
||||||
|
echo " 2. Check 'docker logs zigbee2mqtt' — if it can't open the serial port, confirm"
|
||||||
|
echo " ZIGBEE_USB_DEVICE at the top of this script matches 'ls -l /dev/serial/by-id/',"
|
||||||
|
echo " and that the dongle has Z-Stack coordinator firmware (not stock gateway firmware)."
|
||||||
|
echo " 3. Complete Home Assistant's onboarding wizard at :8123."
|
||||||
|
echo " 4. In HA, add the MQTT integration (it should auto-discover Zigbee2MQTT devices)."
|
||||||
|
echo " 5. Add the CalDAV integration pointing at your Nextcloud instance."
|
||||||
|
echo " 6. Point HA's Ollama conversation integration at your separate GPU/LLM host."
|
||||||
|
echo
|
||||||
|
echo "Updating later: cd $BASE_DIR && docker compose pull && docker compose up -d"
|
||||||
|
echo "Backing up: stop the stack (docker compose down), then tar/copy $BASE_DIR, then start it again."
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7c50cf1803ee141f405cadf1bbc622dd388de9a3
|
|
||||||
Loading…
Reference in New Issue