From 2000265646389a1d859bc2c38ccab4310f1cbaf7 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Mon, 29 Dec 2025 17:34:26 +0100 Subject: [PATCH] domoticz: add docker app manifest and docs --- DOCS/DOCUMENTATION-INDEX.md | 5 + DOCS/embedded/domoticz-docker.md | 3 + docs/documentation-index.md | 12 ++ docs/embedded/domoticz-docker.md | 69 +++++++++++ luci-app-secubox/Makefile | 9 +- plugins/domoticz/manifest.json | 39 +++++++ secubox-app-domoticz/Makefile | 42 +++++++ .../files/etc/config/domoticz | 7 ++ .../files/etc/init.d/domoticz | 23 ++++ .../files/usr/sbin/domoticzctl | 107 ++++++++++++++++++ 10 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 DOCS/embedded/domoticz-docker.md create mode 100644 docs/embedded/domoticz-docker.md create mode 100644 plugins/domoticz/manifest.json create mode 100644 secubox-app-domoticz/Makefile create mode 100644 secubox-app-domoticz/files/etc/config/domoticz create mode 100644 secubox-app-domoticz/files/etc/init.d/domoticz create mode 100644 secubox-app-domoticz/files/usr/sbin/domoticzctl diff --git a/DOCS/DOCUMENTATION-INDEX.md b/DOCS/DOCUMENTATION-INDEX.md index 56876efa..9297d1a5 100644 --- a/DOCS/DOCUMENTATION-INDEX.md +++ b/DOCS/DOCUMENTATION-INDEX.md @@ -233,6 +233,11 @@ Pointer: see `docs/embedded/wizard-profiles.md` for the canonical version. Pointer: see `docs/embedded/lyrion-docker.md` for the canonical version. +#### **embedded/domoticz-docker.md** 🏠 +*Deploy Domoticz home automation via Docker.* + +Pointer: see `docs/embedded/domoticz-docker.md` for the canonical version. + --- ### 5. Tools & Scripts Documentation diff --git a/DOCS/embedded/domoticz-docker.md b/DOCS/embedded/domoticz-docker.md new file mode 100644 index 00000000..9ff83f71 --- /dev/null +++ b/DOCS/embedded/domoticz-docker.md @@ -0,0 +1,3 @@ +# Domoticz on SecuBox (Docker) + +Same content as docs/embedded/domoticz-docker.md. diff --git a/docs/documentation-index.md b/docs/documentation-index.md index 7b7b8874..f242b964 100644 --- a/docs/documentation-index.md +++ b/docs/documentation-index.md @@ -271,6 +271,18 @@ Follow this template when creating or revising documentation: **Size:** Short (~120 lines) +#### **embedded/domoticz-docker.md** 🏠 +*Deploy Domoticz home automation via Docker.* + +**Contents:** +- `secubox-app-domoticz` usage and `domoticzctl` commands +- UCI options + wizard fields +- VHost + DMZ profile guidance + +**When to use:** Hosting Domoticz using the new App Store manifest. + +**Size:** Short (~120 lines) + --- ### 5. Tools & Scripts Documentation diff --git a/docs/embedded/domoticz-docker.md b/docs/embedded/domoticz-docker.md new file mode 100644 index 00000000..94d0b512 --- /dev/null +++ b/docs/embedded/domoticz-docker.md @@ -0,0 +1,69 @@ +# Domoticz on SecuBox (Docker) + +**Version:** 1.0.0 +**Last Updated:** 2025-12-28 +**Status:** Active + +This guide documents the Domoticz (home automation) “app” packaged as `secubox-app-domoticz` plus its manifest-driven wizard entry. + +--- + +## Installation + +```sh +opkg update +opkg install secubox-app-domoticz luci-app-vhost-manager +/domoticzctl install +/etc/init.d/domoticz start +``` + +Then open **SecuBox → Wizard → App Wizards → Domoticz** to set data/devices paths or custom ports. + +--- + +## UCI Config (`/etc/config/domoticz`) + +```uci +config domoticz 'main' + option enabled '1' + option image 'domoticz/domoticz:latest' + option data_path '/srv/domoticz' + option devices_path '/srv/devices' + option port '8080' + option timezone 'UTC' +``` + +Adjust via `uci` or the wizard: +```sh +uci set domoticz.main.port='8181' +uci commit domoticz +/etc/init.d/domoticz restart +``` + +--- + +## CLI Helper (`/usr/sbin/domoticzctl`) + +- `domoticzctl install` – checks Docker, prepares `/srv/domoticz`, pulls `domoticz/domoticz` image, enables service. +- `domoticzctl check` – rerun storage/cgroup/Docker validation. +- `domoticzctl update` – pull new image and restart if enabled. +- `domoticzctl status/logs` – interact with the Docker container. + +--- + +## VHost & Profiles + +- Use `scripts/vhostctl.sh add --domain ha.secubox.local --upstream http://127.0.0.1:` to publish the web UI via HTTPS. +- The manifest tags Domoticz for the **Gateway + DMZ** profile, ensuring DMZ isolation by default. + +--- + +## Troubleshooting + +| Issue | Fix | +|-------|-----| +| Container fails to start | Check `/srv/domoticz/config` permissions; ensure Docker is running. | +| No devices under `/srv/devices` | Mount your serial/Zigbee USB adapter and bind-mount it into the container as needed. | +| LuCI wizard fields empty | Confirm manifest at `/usr/share/secubox/plugins/domoticz/manifest.json` and rerun SecuBox wizard. | + +Domoticz now follows the same manifest-driven workflow as Lyrion/Zigbee2MQTT, paving the way for a full “SecuBox Apps Store.” diff --git a/luci-app-secubox/Makefile b/luci-app-secubox/Makefile index 87888bac..884c6028 100644 --- a/luci-app-secubox/Makefile +++ b/luci-app-secubox/Makefile @@ -24,8 +24,13 @@ include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/install $(call Package/luci/install,$(1)) - $(INSTALL_DIR) $(1)/usr/share/secubox/plugins/zigbee2mqtt - $(INSTALL_DATA) $(CURDIR)/../plugins/zigbee2mqtt/manifest.json $(1)/usr/share/secubox/plugins/zigbee2mqtt/manifest.json + $(INSTALL_DIR) $(1)/usr/share/secubox/plugins + for dir in $(CURDIR)/../plugins/*; do \ + [ -d $$dir ] || continue; \ + name=$$(basename $$dir); \ + $(INSTALL_DIR) $(1)/usr/share/secubox/plugins/$$name; \ + $(INSTALL_DATA) $$dir/manifest.json $(1)/usr/share/secubox/plugins/$$name/manifest.json; \ + done $(INSTALL_DIR) $(1)/usr/share/secubox/profiles for file in $(CURDIR)/../profiles/*.json; do \ $(INSTALL_DATA) $$file $(1)/usr/share/secubox/profiles/$$(basename $$file); \ diff --git a/plugins/domoticz/manifest.json b/plugins/domoticz/manifest.json new file mode 100644 index 00000000..6f20cf63 --- /dev/null +++ b/plugins/domoticz/manifest.json @@ -0,0 +1,39 @@ +{ + "id": "domoticz", + "name": "Domoticz", + "description": "Home automation server (Docker-based).", + "type": "docker", + "version": "1.0.0", + "source": "https://www.domoticz.com/", + "packages": [ + "secubox-app-domoticz", + "luci-app-vhost-manager" + ], + "ports": [ + { "name": "ui", "protocol": "http", "port": 8080, "expose": true } + ], + "volumes": [ + "/srv/domoticz", + "/srv/devices" + ], + "network": { + "default_mode": "router", + "dmz_supported": true + }, + "wizard": { + "uci": { "config": "domoticz", "section": "main" }, + "fields": [ + { "id": "data_path", "label": "Data Path", "type": "text", "uci_option": "data_path", "placeholder": "/srv/domoticz" }, + { "id": "devices_path", "label": "Devices Path", "type": "text", "uci_option": "devices_path", "placeholder": "/srv/devices" }, + { "id": "port", "label": "HTTP Port", "type": "number", "uci_option": "port", "placeholder": "8080" }, + { "id": "timezone", "label": "Timezone", "type": "text", "uci_option": "timezone", "placeholder": "UTC" } + ] + }, + "profiles": ["home", "gateway_dmz"], + "actions": { + "install": "domoticzctl install", + "check": "domoticzctl check", + "update": "domoticzctl update", + "status": "/etc/init.d/domoticz status" + } +} diff --git a/secubox-app-domoticz/Makefile b/secubox-app-domoticz/Makefile new file mode 100644 index 00000000..d64deca3 --- /dev/null +++ b/secubox-app-domoticz/Makefile @@ -0,0 +1,42 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=secubox-app-domoticz +PKG_RELEASE:=1 +PKG_VERSION:=1.0.0 +PKG_MAINTAINER:=CyberMind Studio +PKG_LICENSE:=Apache-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/secubox-app-domoticz + SECTION:=utils + CATEGORY:=Utilities + SUBMENU:=SecuBox Apps + TITLE:=SecuBox Domoticz docker app + DEPENDS:=+uci +libuci +dockerd +docker +containerd +endef + +define Package/secubox-app-domoticz/description +Installer, configuration, and service manager for running Domoticz +inside Docker on SecuBox-powered OpenWrt systems. +endef + +define Package/secubox-app-domoticz/conffiles +/etc/config/domoticz +endef + +define Build/Compile +endef + +define Package/secubox-app-domoticz/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/etc/config/domoticz $(1)/etc/config/domoticz + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/etc/init.d/domoticz $(1)/etc/init.d/domoticz + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/domoticzctl $(1)/usr/sbin/domoticzctl +endef + +$(eval $(call BuildPackage,secubox-app-domoticz)) diff --git a/secubox-app-domoticz/files/etc/config/domoticz b/secubox-app-domoticz/files/etc/config/domoticz new file mode 100644 index 00000000..2d133de9 --- /dev/null +++ b/secubox-app-domoticz/files/etc/config/domoticz @@ -0,0 +1,7 @@ +config domoticz 'main' + option enabled '0' + option image 'domoticz/domoticz:latest' + option data_path '/srv/domoticz' + option devices_path '/srv/devices' + option port '8080' + option timezone 'UTC' diff --git a/secubox-app-domoticz/files/etc/init.d/domoticz b/secubox-app-domoticz/files/etc/init.d/domoticz new file mode 100644 index 00000000..7f5bb70d --- /dev/null +++ b/secubox-app-domoticz/files/etc/init.d/domoticz @@ -0,0 +1,23 @@ +#!/bin/sh /etc/rc.common + +START=95 +STOP=10 +USE_PROCD=1 + +SERVICE_BIN="/usr/sbin/domoticzctl" + +start_service() { + procd_open_instance + procd_set_param command "$SERVICE_BIN" service-run + procd_set_param respawn 2000 5 5 + procd_close_instance +} + +stop_service() { + "$SERVICE_BIN" service-stop >/dev/null 2>&1 +} + +restart_service() { + stop_service + start_service +} diff --git a/secubox-app-domoticz/files/usr/sbin/domoticzctl b/secubox-app-domoticz/files/usr/sbin/domoticzctl new file mode 100644 index 00000000..6fdba715 --- /dev/null +++ b/secubox-app-domoticz/files/usr/sbin/domoticzctl @@ -0,0 +1,107 @@ +#!/bin/sh +# SecuBox Domoticz manager + +CONFIG="domoticz" +CONTAINER="secbx-domoticz" +OPKG_UPDATED=0 + +usage() { + cat <<'USAGE' +Usage: domoticzctl + +Commands: + install Install prerequisites, prepare directories, pull image + check Run prerequisite checks + update Pull new image and restart + status Show container status + logs Show container logs (use -f to follow) + service-run Internal: run container via procd + service-stop Stop container +USAGE +} + +require_root() { [ "$(id -u)" -eq 0 ]; } + +uci_get() { uci -q get ${CONFIG}.main.$1; } + +defaults() { + image="$(uci_get image || echo domoticz/domoticz:latest)" + data_path="$(uci_get data_path || echo /srv/domoticz)" + devices_path="$(uci_get devices_path || echo /srv/devices)" + port="$(uci_get port || echo 8080)" + timezone="$(uci_get timezone || echo UTC)" +} + +ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; } + +ensure_packages() { + for pkg in "$@"; do + if ! opkg status "$pkg" >/dev/null 2>&1; then + if [ "$OPKG_UPDATED" -eq 0 ]; then + opkg update || return 1 + OPKG_UPDATED=1 + fi + opkg install "$pkg" || return 1 + fi + done +} + +check_prereqs() { + defaults + ensure_dir "$data_path" + [ -d /sys/fs/cgroup ] || { echo "[ERROR] /sys/fs/cgroup missing" >&2; return 1; } + ensure_packages dockerd docker containerd + /etc/init.d/dockerd enable >/dev/null 2>&1 + /etc/init.d/dockerd start >/dev/null 2>&1 +} + +pull_image() { defaults; docker pull "$image"; } + +stop_container() { docker stop "$CONTAINER" >/dev/null 2>&1 || true; docker rm "$CONTAINER" >/dev/null 2>&1 || true; } + +cmd_install() { + require_root || { echo Root required >&2; exit 1; } + check_prereqs || exit 1 + ensure_dir "$data_path/config" + pull_image || exit 1 + uci set ${CONFIG}.main.enabled='1' + uci commit ${CONFIG} + /etc/init.d/domoticz enable + echo "Domoticz prerequisites installed. Start with /etc/init.d/domoticz start" +} + +cmd_check() { check_prereqs; echo "Prerequisite check completed."; } + +cmd_update() { + require_root || { echo Root required >&2; exit 1; } + pull_image || exit 1 + /etc/init.d/domoticz restart +} + +cmd_status() { docker ps -a --filter "name=$CONTAINER"; } + +cmd_logs() { docker logs "$@" "$CONTAINER"; } + +cmd_service_run() { + require_root || { echo Root required >&2; exit 1; } + check_prereqs || exit 1 + defaults + stop_container + local docker_args="--name $CONTAINER -p ${port}:8080 -v $data_path/config:/config" + [ -d "$devices_path" ] && docker_args="$docker_args -v $devices_path:/devices" + exec docker run --rm $docker_args -e TZ="$timezone" "$image" +} + +cmd_service_stop() { require_root || { echo Root required >&2; exit 1; }; stop_container; } + +case "${1:-}" in + install) shift; cmd_install "$@" ;; + check) shift; cmd_check "$@" ;; + update) shift; cmd_update "$@" ;; + status) shift; cmd_status "$@" ;; + logs) shift; cmd_logs "$@" ;; + service-run) shift; cmd_service_run "$@" ;; + service-stop) shift; cmd_service_stop "$@" ;; + help|--help|-h|'') usage ;; + *) echo "Unknown command: $1" >&2; usage >&2; exit 1 ;; +esac