diff --git a/nut/README.md b/nut/README.md new file mode 100644 index 0000000..e3dcce2 --- /dev/null +++ b/nut/README.md @@ -0,0 +1,41 @@ +# NUT configuration + +Reference copies of `/etc/nut` for a host that owns a USB UPS and serves it to +other machines — in particular to a Synology, whose DSM client connects with +"UPS Type: Synology UPS Server". + +`setup-nut-synology.sh` in the repo root generates all of these automatically by +detecting the UPS with `nut-scanner`. **Prefer running that.** These files are +here to document the target state and to hand-configure a host where you would +rather not run the script. + +Install by copying each file to `/etc/nut/` without the `.example` suffix, then: + + chown root:nut /etc/nut/*.conf /etc/nut/upsd.users + chmod 0640 /etc/nut/*.conf /etc/nut/upsd.users + systemctl enable --now nut-server nut-monitor + systemctl restart nut-driver@ups.service + +## What DSM requires + +DSM's client cannot be configured, so three things are fixed: + +- the UPS must be named exactly `ups` — the `[ups]` section name in `ups.conf` +- it logs in as `monuser` with the password `secret`, both hardcoded +- `upsd` must listen on an address the Synology can reach + +`monuser` / `secret` are therefore published constants, not credentials. The +`upsmon secondary` role only permits reading status and receiving shutdown +notifications; it cannot command the UPS. + +## What you must change + +The `[admin]` password is a real secret and appears in two files that must +agree: `upsd.users` and the `MONITOR` line of `upsmon.conf`. Both ship here as +`CHANGEME`. Generate one with: + + openssl rand -base64 18 | tr -d '/+=' | cut -c1-20 + +`ups.conf` is pinned to a specific unit by `serial` and `product`. Re-run +`setup-nut-synology.sh` after swapping hardware, or drop those two lines to match +any UPS of the same model. diff --git a/nut/nut.conf.example b/nut/nut.conf.example new file mode 100644 index 0000000..74a93f4 --- /dev/null +++ b/nut/nut.conf.example @@ -0,0 +1,3 @@ +# Install as /etc/nut/nut.conf (root:nut, 0640). +# netserver: run a driver locally and serve it to other machines over the network. +MODE=netserver diff --git a/nut/ups.conf.example b/nut/ups.conf.example new file mode 100644 index 0000000..525f7d6 --- /dev/null +++ b/nut/ups.conf.example @@ -0,0 +1,28 @@ +# Install as /etc/nut/ups.conf (root:nut, 0640). +# +# The section name is what clients ask for. Synology DSM only ever requests +# "ups", so renaming this section will stop DSM from finding the UPS. +# +# The values below are an example from a CyberPower CP1500PFCLCDa. Get the ones +# for your own unit with: +# +# nut-scanner -U -q +# +# Do not copy its bus, device or busport lines: those pin the entry to a physical +# USB port and break on replug. port = "auto" scans the bus instead. +# +# vendorid and productid identify the model; product and serial pin the entry to +# one specific unit. Drop those two if you want the config to survive swapping in +# a different UPS of the same model. + +maxretry = 3 + +[ups] + desc = "CyberPower CP1500PFCLCDa" + driver = "usbhid-ups" + port = "auto" + vendorid = "0764" + productid = "0601" + product = "CP1500PFCLCDa" + serial = "CXXPS0000000" + vendor = "CPS" diff --git a/nut/upsd.conf.example b/nut/upsd.conf.example new file mode 100644 index 0000000..17b3080 --- /dev/null +++ b/nut/upsd.conf.example @@ -0,0 +1,4 @@ +# Install as /etc/nut/upsd.conf (root:nut, 0640). +# Must be reachable by the Synology. 0.0.0.0 listens on every interface; +# narrow it to a specific address if the host is multi-homed. +LISTEN 0.0.0.0 3493 diff --git a/nut/upsd.users.example b/nut/upsd.users.example new file mode 100644 index 0000000..6f27188 --- /dev/null +++ b/nut/upsd.users.example @@ -0,0 +1,18 @@ +# Install as /etc/nut/upsd.users (root:nut, 0640). +# +# admin: used by this machine's own upsmon, which owns the UPS. +# Replace CHANGEME, and use the same value in the MONITOR line of upsmon.conf. +# openssl rand -base64 18 | tr -d '/+=' | cut -c1-20 +[admin] + password = CHANGEME + upsmon primary + actions = SET + instcmds = ALL + +# monuser: for Synology DSM, which hardcodes both the username and the password +# and cannot be configured to use anything else. These are published constants +# rather than credentials. The secondary role only permits reading status and +# receiving shutdown notifications, not commanding the UPS. +[monuser] + password = secret + upsmon secondary diff --git a/nut/upsmon.conf.example b/nut/upsmon.conf.example new file mode 100644 index 0000000..18b8f74 --- /dev/null +++ b/nut/upsmon.conf.example @@ -0,0 +1,20 @@ +# Install as /etc/nut/upsmon.conf (root:nut, 0640). +# +# This machine owns the UPS, so it is the primary: it shuts down last, after +# secondaries such as the Synology have been told to go. +# +# Replace CHANGEME with the [admin] password from upsd.users. The two must match +# or upsmon cannot log in to its own upsd. + +RUN_AS_USER nut + +MONITOR ups@localhost 1 admin CHANGEME primary + +MINSUPPLIES 1 +SHUTDOWNCMD "/sbin/shutdown -h +0" +POLLFREQ 5 +POLLFREQALERT 5 +HOSTSYNC 15 +DEADTIME 15 +POWERDOWNFLAG /etc/killpower +FINALDELAY 5