USV / UPS NUT Server/Client einrichten Debian/Ubuntu

Eine USV “unterbrechungsfreien Stromversorgung” ist für Kritische Anwendungen zu empfehlen, sie wird für verschiedene Geräte wie z.b. Server oder Netzwerkspeicher eingesetzt damit sie beim Stromausfall sauber herunterfahren können, ohne das Risiko von Datenverlust zu haben.

ich benutze eine USV von Eaton “EATON Ellipse PRO 850 USV” die mit USB angeschlossen wird, um mit den Geräten zu kommunizieren, beim QNAP NAS kann sie direkt angeschlossen werden und sogar auch als Netzwerk USV fungieren um auch andere Geräte das Signal zu geben das sie runterfahren sollen.

in meinem Fall nutze ich einen Raspberry Pi um die USV als Netzwerk USV zu betreiben, um alle Geräte damit zu versorgen, diese USV von Eaton kann über USB ja nur an einem Gerät direkt angeschlossen werden.

für Linux gibt es die Software Network UPS Tools “NUT” https://networkupstools.org/

hier eine Beispiel Konfiguration für Server und Client

einfach mit apt das Paket installieren

apt install nut

die Default Konfiguration wird in /etc/nut/ installiert

Einstellungen für den Server

/etc/nut/nut.conf

MODE=netserver

/etc/nut/ups.conf

die USV hinzufügen am ende, der Name qnapups ist gewählt weil ich gelesen habe das es sonst Probleme mit QNAP NAS geben kann beim hinzufügen, “ich habe es nicht verifiziert ob es mit anderen Namen auch geht, mit qnapups funktioniert es zumindest bei QNAP” alle anderen Default werte können unberührt bleiben

[qnapups]
driver = “usbhid-ups”
port = “auto”
desc = “EATON Ellipse PRO 850 USV”
pollinterval = 10

/etc/nut/upsd.conf

hier wird die IP vom NUT Server gesetzt, am ende einfügen oder anpassen, bei bedarf auch ipv6

LISTEN 127.0.0.1 3493
#LISTEN ::1 3493
LISTEN 10.0.10.5 3493

/etc/nut/upsd.users

Benutzer anlegen für master “Server” und Client “slave”

[root]
password = supergeheimespasswort
upsmon master

#Nur für QNAP-User:
[admin]
password = supergeheimespasswort
actions = SET
instcmds = ALL
upsmon slave

/etc/nut/upsmon.conf

werte anpassen und hinzufügen, alle anderen Default werte können unberührt bleiben

RUN_AS_USER root
SHUTDOWNCMD “/sbin/shutdown -P now”

MONITOR qnapups@localhost 1 root supergeheimespasswort master
NOTIFYCMD /usr/sbin/upssched
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOCOMM SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC

/etc/nut/upssched.conf

CMDSCRIPT /bin/upssched-cmd auskommentieren und den Rest am ende einfügen, der wichtigste Parameter ist AT ONBATT * START-TIMER SHUTDOWN 600 , die 600 sind Sekunden wie lange im Batterie Modus gewartet werden soll bis heruntergefahren wird und an alle Client FSD “Forced Shutdown” gesendet wird zum herunterfahren, der wert kann angepasst werden, bei LOWBATT wird sowiso FSD gesendet

##############################################################################
# NUT upssched configuration - PRIMARY / NETSERVER
##############################################################################

CMDSCRIPT /etc/nut/upssched-cmd
PIPEFN /run/nut/upssched.pipe
LOCKFN /run/nut/upssched.lock

##############################################################################
# Grace period when power fails (10 minutes)
##############################################################################

AT ONBATT   * START-TIMER SHUTDOWN 600
AT ONLINE   * CANCEL-TIMER SHUTDOWN

##############################################################################
# Critical conditions
##############################################################################

# If battery is really low -> force immediate shutdown
AT LOWBATT  * EXECUTE LOWBATT-FSD

# When FSD is active (for logging only)
AT FSD      * EXECUTE NOTIFY-FSD

# When upsmon initiates shutdown
AT SHUTDOWN * EXECUTE NOTIFY-SHUTDOWN

##############################################################################
# Communication handling
##############################################################################

AT NOCOMM   * EXECUTE NOTIFY-NOCOMM
AT COMMBAD  * START-TIMER NOTIFY-COMMBAD 10
AT COMMOK   * CANCEL-TIMER NOTIFY-COMMBAD COMMOK

##############################################################################
# Informational events
##############################################################################

AT ONBATT   * EXECUTE NOTIFY-ONBATT
AT ONLINE   * EXECUTE NOTIFY-ONLINE
AT REPLBATT * EXECUTE NOTIFY-REPLBATT

/etc/nut/upssched-cmd

#!/bin/bash

##############################################################################
# NUT upssched command handler - PRIMARY / NETSERVER
##############################################################################

LOGGER_TAG="upssched-cmd"

case "$1" in

##############################################################################
# Grace period expired -> trigger coordinated shutdown
##############################################################################

    SHUTDOWN)
        logger -t $LOGGER_TAG "Grace period expired (600s) – triggering FSD"
        /usr/sbin/upsmon -c fsd
        ;;

##############################################################################
# Battery critically low -> immediate FSD
##############################################################################

    LOWBATT-FSD)
        logger -t $LOGGER_TAG "Battery LOW – forcing immediate FSD"
        /usr/sbin/upsmon -c fsd
        ;;

##############################################################################
# FSD notification
##############################################################################

    NOTIFY-FSD)
        logger -t $LOGGER_TAG "FSD active – coordinated shutdown in progress"
        ;;

##############################################################################
# upsmon shutdown stage
##############################################################################

    NOTIFY-SHUTDOWN)
        logger -t $LOGGER_TAG "upsmon is shutting down this server"
        ;;

##############################################################################
# Communication events
##############################################################################

    NOTIFY-NOCOMM)
        logger -t $LOGGER_TAG "UPS communication lost (NOCOMM)"
        ;;

    NOTIFY-COMMBAD)
        logger -t $LOGGER_TAG "UPS communication failure detected (COMMBAD)"
        ;;

    COMMOK)
        logger -t $LOGGER_TAG "UPS communication restored (COMMOK)"
        ;;

##############################################################################
# Power state events
##############################################################################

    NOTIFY-ONBATT)
        logger -t $LOGGER_TAG "UPS switched to battery power"
        ;;

    NOTIFY-ONLINE)
        logger -t $LOGGER_TAG "Utility power restored"
        ;;

##############################################################################
# Maintenance
##############################################################################

    NOTIFY-REPLBATT)
        logger -t $LOGGER_TAG "UPS battery replacement required"
        ;;

##############################################################################
# Fallback
##############################################################################

    *)
        logger -t $LOGGER_TAG "Unhandled command: $1"
        ;;

esac

exit 0

anschließend noch

chown nut:nut /etc/nut/upssched-cmd
chmod 750 /etc/nut/upssched-cmd

und

systemctl restart nut-monitor

jetzt ist der Server eingerichtet und Funktionsbereit, geprüft kann die Verbindung mit

upsc qnapups@10.0.10.5

Beispiel Ausgabe gekürzt

battery.charge: 100
battery.charge.low: 20
battery.runtime: 1206
battery.type: PbAc
device.mfr: EATON
device.model: Ellipse PRO 850

wen dort nichts angezeigt wird besteht ein Problem mit der Verbindung zur USV

Einstellungen für den Client

hier auch wieder mit apt das Paket installieren

apt install nut

/etc/nut/nut.conf

MODE=netclient

/etc/nut/upsmon.conf

werte anpassen und hinzufügen, alle anderen Default werte können unberührt bleiben

RUN_AS_USER root

SHUTDOWNCMD “/sbin/shutdown -P now”

MONITOR qnapups@10.0.10.5 1 admin supergeheimespasswort  slave
NOTIFYCMD /usr/sbin/upssched
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOCOMM SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC

/etc/nut/upssched.conf

CMDSCRIPT /bin/upssched-cmd auskommentieren und den Rest am ende einfügen, der wichtigste Parameter ist AT ONBATT * START-TIMER SHUTDOWN 180 , die 180 sind Sekunden wie lange im Batterie Modus gewartet werden soll bis heruntergefahren wird, der wert kann angepasst werden, bei LOWBATT sendet der Server sowiso FSD “Forced Shutdown” an alle Client

##############################################################################
# NUT upssched configuration - CLIENT / NETCLIENT
##############################################################################

CMDSCRIPT /etc/nut/upssched-cmd
PIPEFN /run/nut/upssched.pipe
LOCKFN /run/nut/upssched.lock

##############################################################################
# Grace period when power fails (3 minutes)
##############################################################################

AT ONBATT   * START-TIMER SHUTDOWN 180
AT ONLINE   * CANCEL-TIMER SHUTDOWN

##############################################################################
# If server sends FSD -> shutdown immediately
##############################################################################

AT FSD      * EXECUTE NOTIFY-FSD
AT SHUTDOWN * EXECUTE NOTIFY-SHUTDOWN

##############################################################################
# Informational
##############################################################################

AT LOWBATT  * EXECUTE NOTIFY-LOWBATT
AT NOCOMM   * EXECUTE NOTIFY-NOCOMM
AT COMMBAD  * START-TIMER NOTIFY-COMMBAD 10
AT COMMOK   * CANCEL-TIMER NOTIFY-COMMBAD COMMOK
AT ONBATT   * EXECUTE NOTIFY-ONBATT
AT ONLINE   * EXECUTE NOTIFY-ONLINE
AT REPLBATT * EXECUTE NOTIFY-REPLBATT

/etc/nut/upssched-cmd

#!/bin/bash

##############################################################################
# NUT upssched command handler - CLIENT / NETCLIENT
##############################################################################

LOGGER_TAG="upssched-cmd"
SHUTDOWN_CMD="/sbin/shutdown -P now"

case "$1" in

##############################################################################
# Grace period expired -> local shutdown
##############################################################################

    SHUTDOWN)
        logger -t $LOGGER_TAG "Battery runtime exceeded (180s) – shutting down client"
        $SHUTDOWN_CMD
        ;;

##############################################################################
# FSD received from server -> immediate shutdown
##############################################################################

    NOTIFY-FSD)
        logger -t $LOGGER_TAG "FSD received from server – shutting down immediately"
        $SHUTDOWN_CMD
        ;;

##############################################################################
# upsmon shutdown phase
##############################################################################

    NOTIFY-SHUTDOWN)
        logger -t $LOGGER_TAG "upsmon is shutting down this client"
        ;;

##############################################################################
# Power state events
##############################################################################

    NOTIFY-ONBATT)
        logger -t $LOGGER_TAG "UPS switched to battery"
        ;;

    NOTIFY-ONLINE)
        logger -t $LOGGER_TAG "Utility power restored"
        ;;

    NOTIFY-LOWBATT)
        logger -t $LOGGER_TAG "UPS battery low"
        ;;

##############################################################################
# Communication events
##############################################################################

    NOTIFY-NOCOMM)
        logger -t $LOGGER_TAG "UPS communication lost"
        ;;

    NOTIFY-COMMBAD)
        logger -t $LOGGER_TAG "UPS communication failure detected"
        ;;

    COMMOK)
        logger -t $LOGGER_TAG "UPS communication restored"
        ;;

##############################################################################
# Maintenance
##############################################################################

    NOTIFY-REPLBATT)
        logger -t $LOGGER_TAG "UPS battery replacement required"
        ;;

##############################################################################
# Fallback
##############################################################################

    *)
        logger -t $LOGGER_TAG "Unhandled command: $1"
        ;;

esac

exit 0

anschließend noch

chown nut:nut /etc/nut/upssched-cmd
chmod 750 /etc/nut/upssched-cmd

und

systemctl restart nut-monitor

jetzt ist der Client eingerichtet und Funktionsbereit, geprüft kann die Verbindung mit

upsc qnapups@10.0.10.5

Beispiel Ausgabe gekürzt

battery.charge: 100
battery.charge.low: 20
battery.runtime: 1206
battery.type: PbAc
device.mfr: EATON
device.model: Ellipse PRO 850

wen dort nichts angezeigt wird besteht ein Problem mit der Verbindung zur USV

Optional E-Mail Benachrichtigungen vom NUT Server

wen ein Event ausgelöst wird, wird eine E-Mail versendet

apt install msmtp msmtp-mta mailutils

/etc/msmtprc

Datei anlegen, Beispiel für Gmail

defaults
auth           on
tls            on
tls_starttls   on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        /var/log/msmtp.log

account        gmail
host           smtp.gmail.com
port           587
from           DEINEMAIL@gmail.com
user           DEINEMAIL@gmail.com
password       APP_PASSWORT_HIER_EINFÜGEN

account default : gmail

anschließend

chmod 600 /etc/msmtprc
chown root:root /etc/msmtprc

/etc/nut/upssched-cmd

#!/bin/bash

##############################################################################
# NUT upssched command handler - PRIMARY / NETSERVER
##############################################################################

LOGGER_TAG="upssched-cmd"
MAIL_TO="DEINEMAIL@gmail.com"
UPS_NAME="qnapups@localhost"

HOSTNAME="$(hostname)"
DATE="$(date '+%Y-%m-%d %H:%M:%S')"

##############################################################################
# UPS Werte abrufen
##############################################################################

get_ups_value() {
    upsc $UPS_NAME 2>/dev/null | grep "^$1:" | awk -F": " '{print $2}'
}

UPS_MODEL=$(get_ups_value ups.model)
BATTERY_CHARGE=$(get_ups_value battery.charge)
BATTERY_RUNTIME=$(get_ups_value battery.runtime)
UPS_LOAD=$(get_ups_value ups.load)
UPS_REALPOWER=$(get_ups_value ups.realpower)
UPS_STATUS=$(get_ups_value ups.status)
INPUT_VOLTAGE=$(get_ups_value input.voltage)
OUTPUT_VOLTAGE=$(get_ups_value output.voltage)

# Runtime in Minuten umrechnen
if [[ -n "$BATTERY_RUNTIME" ]]; then
    RUNTIME_MIN=$((BATTERY_RUNTIME / 60))
else
    RUNTIME_MIN="N/A"
fi

##############################################################################
# Mailfunktion
##############################################################################

send_mail() {

    SUBJECT="NUT Event [$HOSTNAME] - $1"

    BODY="Host:        $HOSTNAME
Event:       $1
Zeit:        $DATE

UPS Model:	 $UPS_MODEL
UPS Status:  $UPS_STATUS
Charge:      ${BATTERY_CHARGE:-N/A} %
Runtime:     ${RUNTIME_MIN} Minuten
Load:        ${UPS_LOAD:-N/A} %
Load Watt:   ${UPS_REALPOWER:-N/A} W
Input Volt:  ${INPUT_VOLTAGE:-N/A} V
Output Volt: ${OUTPUT_VOLTAGE:-N/A} V

Details:
$2
"

    echo -e "$BODY" | mail -s "$SUBJECT" "$MAIL_TO"
}

##############################################################################
# Event Handling
##############################################################################

case "$1" in

    SHUTDOWN)
        MSG="Grace period expired – triggering FSD"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "SHUTDOWN" "$MSG"
        /usr/sbin/upsmon -c fsd
        ;;

    LOWBATT-FSD)
        MSG="Battery LOW – forcing immediate FSD"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "LOWBATT-FSD" "$MSG"
        /usr/sbin/upsmon -c fsd
        ;;

    NOTIFY-LOWBATT)
        MSG="Battery low warning received"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-LOWBATT" "$MSG"
        ;;

    NOTIFY-FSD)
        MSG="FSD active – coordinated shutdown in progress"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-FSD" "$MSG"
        ;;

    NOTIFY-SHUTDOWN)
        MSG="upsmon is shutting down this server"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-SHUTDOWN" "$MSG"
        ;;

    NOTIFY-NOCOMM)
        MSG="UPS communication lost"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-NOCOMM" "$MSG"
        ;;

    NOTIFY-COMMBAD)
        MSG="UPS communication failure detected"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-COMMBAD" "$MSG"
        ;;

    COMMOK)
        MSG="UPS communication restored"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "COMMOK" "$MSG"
        ;;

    NOTIFY-ONBATT)
        MSG="UPS switched to battery power"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-ONBATT" "$MSG"
        ;;

    NOTIFY-ONLINE)
        MSG="Utility power restored"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-ONLINE" "$MSG"
        ;;

    NOTIFY-REPLBATT)
        MSG="UPS battery replacement required"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-REPLBATT" "$MSG"
        ;;

    NOTIFY-OVERLOAD)
        MSG="UPS overload detected"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-OVERLOAD" "$MSG"
        ;;

    NOTIFY-TRIM)
        MSG="Voltage trim active"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-TRIM" "$MSG"
        ;;

    NOTIFY-BOOST)
        MSG="Voltage boost active"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-BOOST" "$MSG"
        ;;

    NOTIFY-BYPASS)
        MSG="UPS is running on bypass"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "NOTIFY-BYPASS" "$MSG"
        ;;

    *)
        MSG="Unhandled command: $1"
        logger -t $LOGGER_TAG "$MSG"
        send_mail "UNKNOWN" "$MSG"
        ;;

esac

exit 0
systemctl restart nut-monitor