vigilar/scripts/setup_nut.sh
Aaron D. Lee ebcc49b474 Add kiosk setup and deployment scripts (Phases 5 + 9)
Phase 5 — RPi Kiosk:
- setup_kiosk.sh: full RPi OS Lite setup (X11, Chromium kiosk mode,
  auto-login, DPMS disabled, GPU memory split, screen rotation)
- kiosk.service: systemd unit for reliable auto-start
- update_kiosk.sh: reconfigure URL/rotation/resolution without re-setup
- Handles both Bullseye and Bookworm RPi OS versions

Phase 9 — Hardening + Deployment:
- install.sh: full server setup (apt/pacman, vigilar user, venv,
  directories, permissions, mosquitto config, systemd units)
- gen_cert.sh: TLS cert via mkcert or openssl fallback
- gen_vapid_keys.sh: VAPID keys for Web Push notifications
- setup_nut.sh: NUT configuration with USB UPS auto-detection
- backup.sh: SQLite snapshot + config archive, cron-ready
- uninstall.sh: clean removal with data preservation option
- vigilar.service: hardened systemd unit (ProtectSystem, NoNewPrivileges,
  PrivateTmp, syscall filtering)
- vigilar-mosquitto.conf: localhost-only MQTT broker config

All scripts idempotent, bash -n validated, support Debian + Arch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:25:03 -04:00

204 lines
5.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Vigilar — NUT (Network UPS Tools) configuration helper
# Detects USB UPS devices and configures NUT for standalone monitoring.
info() { printf '\033[1;34m[INFO]\033[0m %s\n' "$*"; }
ok() { printf '\033[1;32m[ OK ]\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m[WARN]\033[0m %s\n' "$*"; }
fail() { printf '\033[1;31m[FAIL]\033[0m %s\n' "$*" >&2; exit 1; }
detect_pkg_manager() {
if command -v apt-get &>/dev/null; then
echo "apt"
elif command -v pacman &>/dev/null; then
echo "pacman"
else
fail "Unsupported package manager."
fi
}
install_nut() {
if command -v upsc &>/dev/null; then
ok "NUT already installed"
return
fi
info "Installing NUT"
local pkg_mgr
pkg_mgr="$(detect_pkg_manager)"
case "$pkg_mgr" in
apt)
sudo apt-get update -qq
sudo apt-get install -y -qq nut nut-client nut-server
;;
pacman)
sudo pacman -Sy --needed --noconfirm nut
;;
esac
ok "NUT installed"
}
detect_ups() {
info "Scanning for USB UPS devices..."
local driver=""
local port=""
local desc=""
# Try nut-scanner first
if command -v nut-scanner &>/dev/null; then
local scan_output
scan_output="$(sudo nut-scanner -U 2>/dev/null)" || true
if [[ -n "$scan_output" ]]; then
driver="$(echo "$scan_output" | grep -oP 'driver\s*=\s*"\K[^"]+' | head -1)" || true
port="$(echo "$scan_output" | grep -oP 'port\s*=\s*"\K[^"]+' | head -1)" || true
desc="$(echo "$scan_output" | grep -oP 'desc\s*=\s*"\K[^"]+' | head -1)" || true
fi
fi
# Fallback: check for common USB UPS vendor IDs
if [[ -z "$driver" ]]; then
if lsusb 2>/dev/null | grep -qi "051d"; then
driver="usbhid-ups"
port="auto"
desc="APC UPS (auto-detected via lsusb)"
elif lsusb 2>/dev/null | grep -qi "0764"; then
driver="usbhid-ups"
port="auto"
desc="CyberPower UPS (auto-detected via lsusb)"
elif lsusb 2>/dev/null | grep -qi "0463"; then
driver="usbhid-ups"
port="auto"
desc="Eaton UPS (auto-detected via lsusb)"
elif lsusb 2>/dev/null | grep -qi "06da"; then
driver="usbhid-ups"
port="auto"
desc="Phoenixtec/Tripp Lite UPS (auto-detected via lsusb)"
fi
fi
if [[ -z "$driver" ]]; then
warn "No USB UPS detected. Using generic usbhid-ups driver with auto port."
warn "You may need to edit /etc/nut/ups.conf manually."
driver="usbhid-ups"
port="auto"
desc="UPS (not auto-detected)"
else
ok "Detected UPS: ${desc:-unknown}"
fi
# Export for use in config generation
UPS_DRIVER="$driver"
UPS_PORT="$port"
UPS_DESC="${desc:-UPS}"
}
generate_configs() {
info "Generating NUT configuration"
# /etc/nut/nut.conf — standalone mode
sudo tee /etc/nut/nut.conf > /dev/null <<'NUTCONF'
# Vigilar NUT configuration — standalone mode
MODE=standalone
NUTCONF
# /etc/nut/ups.conf — UPS definition
sudo tee /etc/nut/ups.conf > /dev/null <<UPSCONF
# Vigilar UPS configuration
# Generated by setup_nut.sh
[ups]
driver = ${UPS_DRIVER}
port = ${UPS_PORT}
desc = "${UPS_DESC}"
pollinterval = 15
UPSCONF
# /etc/nut/upsd.conf — daemon config (localhost only)
sudo tee /etc/nut/upsd.conf > /dev/null <<'UPSDCONF'
# Vigilar upsd configuration
LISTEN 127.0.0.1 3493
UPSDCONF
# /etc/nut/upsd.users — local monitoring user
sudo tee /etc/nut/upsd.users > /dev/null <<'USERSCONF'
[vigilar]
password = vigilar_local
upsmon master
USERSCONF
# /etc/nut/upsmon.conf — monitoring config
sudo tee /etc/nut/upsmon.conf > /dev/null <<'MONCONF'
# Vigilar upsmon configuration
MONITOR ups@localhost 1 vigilar vigilar_local master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 15
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 45
RBWARNTIME 43200
NOCOMMWARNTIME 600
FINALDELAY 5
MONCONF
# Secure the config files
sudo chmod 0640 /etc/nut/ups.conf /etc/nut/upsd.conf /etc/nut/upsd.users /etc/nut/upsmon.conf
sudo chown root:nut /etc/nut/ups.conf /etc/nut/upsd.conf /etc/nut/upsd.users /etc/nut/upsmon.conf 2>/dev/null || true
ok "NUT configuration files written"
}
enable_services() {
info "Enabling and starting NUT services"
# Service names vary by distro
local driver_svc="nut-driver"
local server_svc="nut-server"
local monitor_svc="nut-monitor"
# On Arch, the services may be named differently
if ! systemctl list-unit-files "${server_svc}.service" &>/dev/null; then
if systemctl list-unit-files "upsd.service" &>/dev/null; then
server_svc="upsd"
monitor_svc="upsmon"
driver_svc="nut-driver-enumerator"
fi
fi
# Enable and start
for svc in "$driver_svc" "$server_svc" "$monitor_svc"; do
if systemctl list-unit-files "${svc}.service" &>/dev/null; then
sudo systemctl enable "${svc}.service" 2>/dev/null || true
sudo systemctl restart "${svc}.service" 2>/dev/null || warn "Could not start ${svc}.service — check UPS connection"
fi
done
ok "NUT services enabled"
}
main() {
info "=== Vigilar NUT Setup ==="
echo
install_nut
UPS_DRIVER=""
UPS_PORT=""
UPS_DESC=""
detect_ups
generate_configs
enable_services
echo
ok "=== NUT setup complete ==="
info "Test with: upsc ups@localhost"
info "Vigilar will monitor UPS at 127.0.0.1:3493 (ups name: 'ups')"
}
main "$@"