install: make NUT/udev UPS setup declarative and idempotent

This commit is contained in:
Brad Stein 2026-04-03 15:17:26 -03:00
parent 27c7d119c0
commit 08ee1e4fc8
2 changed files with 76 additions and 0 deletions

View File

@ -36,6 +36,14 @@ The installer is idempotent:
- Preserves existing `/etc/hecate/hecate.yaml` - Preserves existing `/etc/hecate/hecate.yaml`
- Ensures required dependencies are installed (`kubectl`, `nut-*`, `ssh`, `go`, etc.) - Ensures required dependencies are installed (`kubectl`, `nut-*`, `ssh`, `go`, etc.)
- Installs/refreshes systemd units and enables boot-time self-update - Installs/refreshes systemd units and enables boot-time self-update
- Applies declarative NUT + udev UPS configuration by default (can be tuned via env vars)
Installer knobs (optional):
- `HECATE_ENABLE_BOOTSTRAP=1` enables `hecate-bootstrap.service` on this host.
- `HECATE_MANAGE_NUT=0` skips writing NUT/udev files.
- `HECATE_NUT_UPS_NAME` (default `atlasups`)
- `HECATE_NUT_VENDOR_ID` / `HECATE_NUT_PRODUCT_ID` (defaults `0764` / `0601`)
- `HECATE_NUT_MONITOR_USER` / `HECATE_NUT_MONITOR_PASSWORD` (defaults `monuser` / `atlasupsmon`)
Bootstrap now (without reboot): Bootstrap now (without reboot):

View File

@ -15,6 +15,12 @@ LIB_DIR="/usr/local/lib/hecate"
START_NOW=1 START_NOW=1
INSTALL_DEPS=1 INSTALL_DEPS=1
ENABLE_BOOTSTRAP="${HECATE_ENABLE_BOOTSTRAP:-0}" ENABLE_BOOTSTRAP="${HECATE_ENABLE_BOOTSTRAP:-0}"
MANAGE_NUT="${HECATE_MANAGE_NUT:-1}"
NUT_UPS_NAME="${HECATE_NUT_UPS_NAME:-atlasups}"
NUT_VENDOR_ID="${HECATE_NUT_VENDOR_ID:-0764}"
NUT_PRODUCT_ID="${HECATE_NUT_PRODUCT_ID:-0601}"
NUT_MONITOR_USER="${HECATE_NUT_MONITOR_USER:-monuser}"
NUT_MONITOR_PASSWORD="${HECATE_NUT_MONITOR_PASSWORD:-atlasupsmon}"
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
@ -84,6 +90,66 @@ ensure_dependencies() {
install_kubectl_if_missing install_kubectl_if_missing
} }
configure_nut() {
if [[ "${MANAGE_NUT}" != "1" ]]; then
echo "[install] skipping NUT configuration (HECATE_MANAGE_NUT=${MANAGE_NUT})"
return 0
fi
echo "[install] configuring NUT + udev for UPS ${NUT_UPS_NAME} (${NUT_VENDOR_ID}:${NUT_PRODUCT_ID})"
install -d -m 0755 /etc/nut /etc/udev/rules.d
cat > /etc/nut/nut.conf <<EOF
MODE=standalone
EOF
cat > /etc/nut/ups.conf <<EOF
[${NUT_UPS_NAME}]
driver = usbhid-ups
port = auto
vendorid = ${NUT_VENDOR_ID}
productid = ${NUT_PRODUCT_ID}
pollinterval = 5
EOF
cat > /etc/nut/upsd.users <<EOF
[${NUT_MONITOR_USER}]
password = ${NUT_MONITOR_PASSWORD}
upsmon primary
EOF
chmod 0640 /etc/nut/upsd.users
if getent group nut >/dev/null 2>&1; then
chown root:nut /etc/nut/upsd.users
else
chown root:root /etc/nut/upsd.users
fi
cat > /etc/nut/upsmon.conf <<EOF
RUN_AS_USER nut
MONITOR ${NUT_UPS_NAME}@localhost 1 ${NUT_MONITOR_USER} ${NUT_MONITOR_PASSWORD} primary
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
EOF
cat > /etc/udev/rules.d/99-hecate-ups.rules <<EOF
# Managed by Hecate install.sh: ensure UPS USB HID devices are readable by NUT
ACTION=="add|change", SUBSYSTEM=="usb", ATTR{idVendor}=="${NUT_VENDOR_ID}", ATTR{idProduct}=="${NUT_PRODUCT_ID}", MODE:="0660", GROUP:="nut"
EOF
udevadm control --reload-rules || true
udevadm trigger --subsystem-match=usb --attr-match=idVendor="${NUT_VENDOR_ID}" --attr-match=idProduct="${NUT_PRODUCT_ID}" || true
systemctl enable nut-driver-enumerator.service nut-server.service nut-monitor.service >/dev/null 2>&1 || true
systemctl restart nut-driver-enumerator.service >/dev/null 2>&1 || true
systemctl restart "nut-driver@${NUT_UPS_NAME}.service" >/dev/null 2>&1 || true
systemctl restart nut-server.service nut-monitor.service >/dev/null 2>&1 || true
}
ensure_dependencies ensure_dependencies
echo "[install] building hecate" echo "[install] building hecate"
@ -113,6 +179,8 @@ install -m 0644 deploy/systemd/hecate-update.service "${SYSTEMD_DIR}/hecate-upda
install -m 0644 deploy/systemd/hecate-update.timer "${SYSTEMD_DIR}/hecate-update.timer" install -m 0644 deploy/systemd/hecate-update.timer "${SYSTEMD_DIR}/hecate-update.timer"
install -m 0755 scripts/hecate-self-update.sh "${LIB_DIR}/hecate-self-update.sh" install -m 0755 scripts/hecate-self-update.sh "${LIB_DIR}/hecate-self-update.sh"
configure_nut
systemctl daemon-reload systemctl daemon-reload
systemctl enable hecate.service hecate-update.timer systemctl enable hecate.service hecate-update.timer
if [[ "${ENABLE_BOOTSTRAP}" == "1" ]]; then if [[ "${ENABLE_BOOTSTRAP}" == "1" ]]; then