Add Drive Health (gustav0ar/drive-health) (#58)

* add Drive Health

* declare optional package manager commands

* use live Drive Health screenshot

* hide redundant dependency subtitle

* fix drive error counter alerts

* stabilize transient SMART availability

* address collector packaging review

* refactor: use generic collector service name

* test: harden collector packaging checks
This commit is contained in:
Gustavo de Andrade Rosa
2026-07-21 11:14:38 -04:00
committed by GitHub
parent a55b9e6b8a
commit ddb054ae3c
26 changed files with 6222 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env bash
set -euo pipefail
if (( EUID != 0 )); then
echo "Run this installer with sudo." >&2
exit 1
fi
project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
service_name="noctalia-drive-health"
target_user="${SUDO_USER:-${1:-}}"
if [[ -z "$target_user" || "$target_user" == root ]] || ! id "$target_user" >/dev/null 2>&1; then
echo "Unable to determine the desktop user. Run with sudo, or pass the username explicitly." >&2
exit 1
fi
target_gid="$(id -g "$target_user")"
for dependency in sh smartctl lsblk systemctl install sed mktemp id; do
if ! command -v "$dependency" >/dev/null 2>&1; then
echo "Missing required command: $dependency" >&2
exit 1
fi
done
rendered_service="$(mktemp)"
trap 'rm -f -- "$rendered_service"' EXIT
sed "s/@TARGET_GID@/$target_gid/g" \
"$project_dir/packaging/$service_name.service.in" >"$rendered_service"
install -Dm0755 \
"$project_dir/scripts/collect_raw.sh" \
"/usr/local/libexec/$service_name/collect_raw.sh"
install -Dm0755 \
"$project_dir/packaging/smart-action.sh" \
"/usr/local/libexec/$service_name/smart-action.sh"
install -Dm0644 \
"$rendered_service" \
"/etc/systemd/system/$service_name.service"
install -Dm0644 \
"$project_dir/packaging/$service_name.timer" \
"/etc/systemd/system/$service_name.timer"
systemctl daemon-reload
systemctl enable --now "$service_name.timer"
systemctl start "$service_name.service"
echo "Installed the read-only SMART collector."
echo "Cache: /run/$service_name/raw.json"
@@ -0,0 +1,36 @@
[Unit]
Description=Collect read-only SMART data for Noctalia Drive Health
Documentation=man:smartctl(8)
After=local-fs.target
[Service]
Type=oneshot
ExecStart=/bin/sh /usr/local/libexec/noctalia-drive-health/collect_raw.sh --output /run/noctalia-drive-health/raw.json
Group=@TARGET_GID@
RuntimeDirectory=noctalia-drive-health
RuntimeDirectoryMode=0750
RuntimeDirectoryPreserve=yes
UMask=0027
StandardOutput=null
StandardError=journal
TimeoutStartSec=60s
NoNewPrivileges=true
PrivateTmp=true
PrivateNetwork=true
ProtectSystem=strict
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
ProtectClock=true
RestrictAddressFamilies=AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
LockPersonality=true
MemoryDenyWriteExecute=true
CapabilityBoundingSet=CAP_DAC_OVERRIDE CAP_SYS_ADMIN CAP_SYS_RAWIO
ReadWritePaths=/run/noctalia-drive-health
@@ -0,0 +1,11 @@
[Unit]
Description=Refresh SMART data for Noctalia
[Timer]
OnBootSec=20s
OnUnitActiveSec=30s
AccuracySec=5s
Unit=noctalia-drive-health.service
[Install]
WantedBy=timers.target
+35
View File
@@ -0,0 +1,35 @@
#!/bin/sh
set -eu
if [ "$(id -u)" -ne 0 ]; then
echo "Run this SMART action as root." >&2
exit 1
fi
action=${1:-}
device=${2:-}
case "$action" in
short|long) ;;
*)
echo "usage: $0 {short|long} DEVICE" >&2
exit 2
;;
esac
case "$device" in
/dev/nvme[0-9]* )
[ -c "$device" ] || { echo "Not an NVMe controller: $device" >&2; exit 2; }
;;
/dev/* )
[ -b "$device" ] || { echo "Not a block device: $device" >&2; exit 2; }
[ "$(lsblk --nodeps --noheadings --output TYPE "$device" 2>/dev/null | tr -d ' ')" = "disk" ] \
|| { echo "SMART tests require a whole disk: $device" >&2; exit 2; }
;;
*)
echo "Device must be an absolute /dev path." >&2
exit 2
;;
esac
echo "Starting the $action SMART self-test on $device"
exec smartctl --test="$action" "$device"
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
if (( EUID != 0 )); then
echo "Run this uninstaller with sudo." >&2
exit 1
fi
service_name="noctalia-drive-health"
systemctl disable --now "$service_name.timer" 2>/dev/null || true
systemctl stop "$service_name.service" 2>/dev/null || true
rm -f \
"/etc/systemd/system/$service_name.service" \
"/etc/systemd/system/$service_name.timer"
rm -rf \
"/usr/local/libexec/$service_name" \
"/run/$service_name"
systemctl daemon-reload
systemctl reset-failed "$service_name.service" 2>/dev/null || true
echo "Removed the Noctalia Drive Health system collector."