diff --git a/Apps/Scrutiny/docker-compose.yml b/Apps/Scrutiny/docker-compose.yml new file mode 100644 index 0000000..c60fe11 --- /dev/null +++ b/Apps/Scrutiny/docker-compose.yml @@ -0,0 +1,123 @@ +name: thundersquared-scrutiny +services: + scrutiny: + # renovate: datasource=docker depName=ghcr.io/analogj/scrutiny + image: ghcr.io/analogj/scrutiny:master-omnibus@sha256:18689773150d6b8b53c94a435f40f7b6e946fd4a6d40b44c64fa2154a5b38941 + environment: + TZ: $TZ + COLLECTOR_CRON_SCHEDULE: "0 0 * * *" + ports: + - target: 8080 + published: "8080" + protocol: tcp + volumes: + - type: bind + source: /DATA/AppData/scrutiny/config + target: /opt/scrutiny/config + - type: bind + source: /DATA/AppData/scrutiny/influxdb + target: /opt/scrutiny/influxdb + - type: bind + source: /run/udev + target: /run/udev + read_only: true + devices: + - /dev/sda:/dev/sda + networks: + - scrutiny + restart: unless-stopped + cap_drop: + - ALL + cap_add: + - CHOWN + - DAC_OVERRIDE + - FOWNER + - SETGID + - SETUID + - SYS_RAWIO + security_opt: + - no-new-privileges:true + healthcheck: + test: ["CMD-SHELL", "curl -fsS http://localhost:8080/api/health >/dev/null"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 60s + x-casaos: + envs: + - container: TZ + description: + en_US: Timezone used by Scrutiny and its collector cron schedule. + - container: COLLECTOR_CRON_SCHEDULE + description: + en_US: Cron schedule for the bundled S.M.A.R.T. collector. Defaults to daily at midnight; a collection also runs once at startup. + ports: + - container: "8080" + description: + en_US: Scrutiny web dashboard and API. It has no authentication; keep it on a trusted LAN. + volumes: + - container: /opt/scrutiny/config + description: + en_US: Persistent Scrutiny configuration, including scrutiny.yaml and notification URLs. Stored at /DATA/AppData/scrutiny/config on the host. + - container: /opt/scrutiny/influxdb + description: + en_US: Persistent bundled InfluxDB data with S.M.A.R.T. history and the generated InfluxDB admin token. Stored at /DATA/AppData/scrutiny/influxdb on the host. + - container: /run/udev + description: + en_US: Read-only host udev database used to identify disks by serial and WWN. + devices: + - container: /dev/sda + description: + en_US: First SATA/SAS disk to monitor. Add one mapping per disk (/dev/sdb, ...); NVMe drives need the controller (/dev/nvme0) and the SYS_ADMIN capability. + +networks: + scrutiny: + driver: bridge + +x-casaos: + id: com.thundersquared.scrutiny + main: scrutiny + index: / + port_map: "8080" + scheme: http + icon: https://cdn.jsdelivr.net/gh/selfhst/icons@main/png/scrutiny.png + title: + en_US: Scrutiny + tagline: + en_US: Hard drive S.M.A.R.T. monitoring dashboard + description: + en_US: >- + Scrutiny omnibus image bundling the web dashboard, the S.M.A.R.T. + collector, and InfluxDB in one bridge-mode container on HTTP port 8080. + The collector runs smartctl once at startup and then on a cron schedule, + and the dashboard tracks drive health against manufacturer thresholds and + Backblaze failure rates. Disks are passed through individually; /dev/sda + is mapped by default with SYS_RAWIO for S.M.A.R.T. access. The InfluxDB + port is not published. + tips: + before_install: + en_US: >- + Scrutiny has no login, so keep port 8080 on a trusted LAN and put any + external access behind an authenticated reverse proxy, VPN, or tunnel. + Only /dev/sda is passed through by default and installation fails if it + does not exist; edit the device list to match your disks (one entry per + disk, for example /dev/sdb). NVMe drives need the controller device + (/dev/nvme0, not /dev/nvme0n1) plus the SYS_ADMIN capability, which + grants broad host administration rights; add it only deliberately. + The InfluxDB volume holds an admin token; treat backups as sensitive. + author: thundersquared + developer: AnalogJ + category: Others + architectures: + - amd64 + - arm64 + # Scrutiny omnibus is consumed from the moving master-omnibus channel, so the + # store assigns a counter version here. Each digest change bumps the patch + # component, which is the only update signal the ZimaOS client can compare. + version: "1.0.0" + release_notes: + en_US: Pinned ghcr.io/analogj/scrutiny:master-omnibus at sha256:18689773150d. + website: https://github.com/AnalogJ/scrutiny + repo: https://github.com/AnalogJ/scrutiny + support: https://github.com/AnalogJ/scrutiny/issues + docs: https://github.com/AnalogJ/scrutiny/tree/master/docs diff --git a/README.md b/README.md index 841dac1..33f55d6 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,15 @@ Manual Docker Compose import remains possible from each source definition. - TVHeadend: bridge-mode UI and HTSP on TCP 9981 and 9982 with GPU and DVB tuner passthrough. - Zigbee2MQTT: bridge-mode Zigbee gateway on TCP 9442 with adapter hardware opt-in. - Proxmox Backup Server: dockurr bridge-mode HTTPS UI on TCP 8007 with persistent config and datastore. +- Scrutiny: omnibus bridge-mode S.M.A.R.T. dashboard on TCP 8080 with bundled + collector and InfluxDB, and per-disk passthrough. Every app image uses a pinned manifest-list digest and, where upstream publishes one, an explicit version tag. Both `amd64` and `arm64` are required. Hardware access remains opt-in except for -the documented Home Assistant Bluetooth D-Bus path and TVHeadend GPU/DVB -devices. Host networking is used only for documented discovery or VPN -exceptions. WAN exposure remains an +the documented Home Assistant Bluetooth D-Bus path, TVHeadend GPU/DVB +devices, and Scrutiny disk devices. Host networking is used only for +documented discovery or VPN exceptions. WAN exposure remains an opt-in edit documented in the app metadata. ## Security Boundary @@ -81,6 +83,17 @@ for trusted-LAN use. Keep both ports off untrusted networks; UDP 1900 also requires no competing host SSDP service. Port 8921 is published for HTTPS but remains inactive until certificates and Jellyfin HTTPS settings are configured. +Scrutiny uses the omnibus image so the web dashboard, the S.M.A.R.T. collector, +and InfluxDB run in one container. The dashboard has no authentication, so keep +TCP 8080 on a trusted LAN. InfluxDB port 8086 is not published. Only `/dev/sda` +is passed through by default, with `SYS_RAWIO` for S.M.A.R.T. access and a +read-only `/run/udev`; edit the device list to match the host's disks before +installing, since a missing device prevents the container from starting. NVMe +drives need the controller device (`/dev/nvme0`) plus `SYS_ADMIN`, which grants +broad host administration rights and stays opt-in. The collector runs once at +startup and then on `COLLECTOR_CRON_SCHEDULE` (daily at midnight by default). +The InfluxDB volume stores an admin token; treat backups as sensitive. + ## Build GitHub Actions runs the official pinned ZimaOS v2 builder. The generated @@ -104,8 +117,9 @@ field instead, and runs on every publish before the store is built: `eclipse-mosquitto:2.1.2-alpine` publishes as `2.1.2`. Both keys are consumed by the reconcile script, not by the store build. A prefix or suffix that no longer matches the tag is ignored and reported by `check` -- LinuxServer `tvheadend` publishes no version tag, so it carries a counter - version that the same rule increments on every digest change +- LinuxServer `tvheadend` and Scrutiny `master-omnibus` publish no version + tag, so they carry a counter version that the same rule increments on every + digest change - `release_notes` and `update_at` are regenerated from the image reference that actually shipped, which removes the stale release notes that image-only updates used to leave behind. Release notes always quote the unmodified tag, diff --git a/renovate.json5 b/renovate.json5 index 96f8ece..256a23b 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -28,7 +28,7 @@ "description": "Refresh moving container channels immediately", "matchDatasources": ["docker"], "matchUpdateTypes": ["digest"], - "matchCurrentValue": "/^(latest|stable|edge|master|master-debian)$/", + "matchCurrentValue": "/^(latest|stable|edge|master|master-debian|master-omnibus)$/", "minimumReleaseAge": "0 days", "addLabels": ["upstream-moving-tag"] }