feat: stop installing the NUT client on new Proxmox nodes
Lint / Shell (shellcheck) (push) Successful in 6s

The rack moved from a USB-attached APC on monitor-02 to a UniFi UPS 2U Pro,
a network device running its own NUT server. Cluster nodes no longer run
NUT at all, so this section installed a client that could never connect.

Two reasons it is gone rather than repointed:

  - The UPS allow-lists NUT client IPs and caps at ~3, and requires
    credentials. Only monitor-02 is allow-listed, and it cannot relay:
    dummy-ups repeater mode on NUT 2.8.1 (Debian trixie) cannot
    authenticate upstream, as `authconf` is 2.8.6+.

  - The per-node upsmon was harmful anyway. Its only action was
    SHUTDOWNCMD "/sbin/poweroff", which skips the graceful VM/LXC
    shutdown and the Ceph protective flags that ups-shutdown.sh sets.

Replaced with a startup banner making the real requirement explicit: a new
node is only covered once it is added to the NODES array in ups-shutdown.sh.
That dependency was previously implicit and easy to miss.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-08 19:49:09 -04:00
co-authored by Claude Opus 5
parent 195343dcfe
commit 63a4544302
+37 -62
View File
@@ -479,72 +479,47 @@ if [[ ! -s /etc/hwmonDaemon/.env ]] || grep -q "your_api_key_here" /etc/hwmonDae
fi
# =============================================================================
# NUT UPS Client — connects to monitor-02 (10.10.10.9) for UPS awareness
# NUT UPS Client — intentionally NOT installed
# =============================================================================
# Cluster nodes no longer run NUT. Do not re-add this.
#
# The rack is on a UniFi UPS 2U Pro, a network device running its own NUT
# server. Two things follow from that:
#
# 1. Its NUT server allow-lists client IPs and caps out at ~3, and it
# requires credentials. Only monitor-02 (10.10.10.9) is allow-listed.
# monitor-02 cannot relay to other nodes either: dummy-ups repeater mode
# on NUT 2.8.1 (the version in Debian trixie) cannot authenticate
# upstream, since `authconf` is 2.8.6+.
#
# 2. More importantly, the per-node upsmon was actively harmful. Its only
# action was SHUTDOWNCMD "/sbin/poweroff", which skips the graceful
# VM/LXC shutdown and the Ceph protective flags (noout, nobackfill,
# norecover, pause). A node powering itself off mid-outage is worse than
# one that waits.
#
# All shutdown is orchestrated over SSH from monitor-02 by ups-shutdown.sh.
# A new node is covered automatically once it is added to the NODES array in
# that script:
#
# https://code.lotusguild.org/LotusGuild/nut-ups → ups-shutdown.sh
#
# *** Add new UPS-backed Proxmox nodes to that NODES array, or they will not
# *** be shut down during a power outage.
if [[ "$PLATFORM" == "pve" ]]; then
echo "Installing NUT UPS monitoring client..."
apt-get install -y nut-client
mkdir -p /etc/nut
# Fetch the NUT password from the server
NUT_ENV_URL="http://10.10.10.63:3000/LotusGuild/nut-ups/raw/branch/main/upsmon-client.conf.template"
# Fetch the NUT password from monitor-02 (server holds the canonical password)
# We pull the client conf template and substitute the password inline.
# The password must be set manually or fetched here if you store it securely.
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " NUT UPS Client Configuration"
echo " UPS shutdown coverage — ACTION REQUIRED"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " This node does NOT run a NUT client (by design)."
echo " Power-loss shutdown is orchestrated over SSH from monitor-02."
echo ""
echo " To cover this node, add it to the NODES array in ups-shutdown.sh:"
echo " repo: LotusGuild/nut-ups"
echo " line: NODES=( \"<ip>:<hostname>\" ... )"
echo ""
echo " Also confirm monitor-02 can SSH here as root without a password:"
echo " ssh -o BatchMode=yes root@$(hostname -I | awk '{print $1}') hostname"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Enter the NUT password (from /etc/nut/nut.env on monitor-02):"
read -r -s -p " NUT_PASSWORD: " NUT_CLIENT_PASS
echo ""
if [[ -n "$NUT_CLIENT_PASS" ]]; then
# Write nut.conf (client mode)
cat > /etc/nut/nut.conf << 'NUTEOF'
MODE=netclient
NUTEOF
# Fetch upsmon-client.conf.template and substitute password
if curl --max-time 15 --retry 2 -s "$NUT_ENV_URL" -o /tmp/upsmon-client.conf.template; then
sed "s/NUT_PASSWORD_PLACEHOLDER/${NUT_CLIENT_PASS}/g" \
/tmp/upsmon-client.conf.template > /etc/nut/upsmon.conf
rm -f /tmp/upsmon-client.conf.template
else
# Fallback: write inline
cat > /etc/nut/upsmon.conf << UPSMONEOF
MONITOR apcups@10.10.10.9 1 upsmon_remote ${NUT_CLIENT_PASS} slave
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/poweroff"
POLLFREQ 5
POLLFREQALERT 2
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
NOTIFYFLAG ONLINE SYSLOG+WALL
NOTIFYFLAG ONBATT SYSLOG+WALL
NOTIFYFLAG LOWBATT SYSLOG+WALL
NOTIFYFLAG FSD SYSLOG+WALL
NOTIFYFLAG SHUTDOWN SYSLOG+WALL
NOTIFYFLAG NOCOMM SYSLOG+WALL
UPSMONEOF
fi
chown root:nut /etc/nut/upsmon.conf 2>/dev/null || true
chmod 640 /etc/nut/upsmon.conf
systemctl enable nut-monitor
if systemctl start nut-monitor 2>/dev/null; then
echo "✓ NUT client connected to UPS monitor on monitor-02"
else
echo "⚠️ NUT client installed but could not connect yet (monitor-02 may not be running NUT server)"
echo " It will connect automatically once nut-server is running on monitor-02."
fi
else
echo "⚠️ NUT password not provided — skipping NUT client setup."
echo " Run manually: apt install nut-client && configure /etc/nut/upsmon.conf"
fi
fi