Synology + Proxmox + NUT UPS

The recent apocalyptic wind storms and fires in Colorado have given me a reason to finally suss out proper UPS (uninterruptible power supply) config in my homelab.

My environment consists of a primary rack, an 'annex' rack, a bunch of Ubiquity networking gear, three or so servers, a Synology NAS, and three different UPS units.  The servers are all running the Proxmox hypervisor, which doesn't have UI support for any UPS monitoring or management.

I had previously configured NUT to monitor a directly connected UPS from one of the Proxmox hosts itself, but was never happy with the configuration.

Techno Tim inspired me to go down the NUT rabbit hole again, and his guide is pretty spot on.  He did have a bug in his config that meant that the client host would go down even if a power failure was momentary.

Tim's guide also featured the upsstats console, which is served as an Apache CGI.  

I know, I know.  I haven't installed an Apache CGI in probably 10 years either, but that's OK.  It's worth it for the pretty pictures.

It took a bit of trickery to serve this old school interface up via a modern Traefik ingress.  Shout outs to Rugburn for help with this config.


http:
  routers:
    upsmon-cgi:
      entryPoints:
        - "https"
      rule: "Host(`upsmon.local.zanshindojo.org`)"
      middlewares:
        - default-headers
        - redirect-upsmon
      tls: {}
      service: upsmon-cgi
  services:
    upsmon-cgi:
      loadBalancer:
        servers:
          - url: "http://${INTERNAL_NUT}:80"    # nut-vm apache CGI
        passHostHeader: true    
  middlewares:
    redirect-upsmon:
      # redirect requests to / to the cgi, but not anything else
      redirectRegex:
        regex: "^https://upsmon.local\\.zanshindojo\\.org/(.){0}$"
        replacement: "https://upsmon.local.zanshindojo.org/cgi-bin/nut/upsstats.cgi"
traefik/config.yml

I also wanted to configure my Synology as a NUT client, which is only sort-of supported in the UI.  To get this working, you need to configure the Synology with the IP of the NUT server

You also need to configure your ups.conf on your NUT server to have a UPS called "ups". It can't be called anything else.  The Synology will refuse to connect otherwise.

You also need to create a user on the NUT server (in uspd.users) called 'admin' with password 'secret'.  I tried unsuccessfully to get the Synology to connect to the NUT server using a less guessable username and a complex password to no avail.

[monuser]
  password = secret
  admin master

[superuser]
  password = changeme
  superuser master
  actions = SET
  instcmds = ALL
/etc/nut/upsd.users

This is not as much of a security problem as you might think, as the 'admin' user has what seems to be read only access to the UPS.  I confirmed this using upscmd

Obviously we don't want any attacker on the L3 network to be able to shut down the UPS with simple creds.

The superuser account created above can in fact execute all those dangerous commands, but the Synology hard-coded account cannot.

The Synology will now successfully connect, but there's an issue somewhere in the guts of the Syno stuff that is prevent is from shutting down cleanly

2022-01-02T11:10:35-07:00 cygni upsmsg: UPS on battery.
2022-01-02T11:11:05-07:00 cygni upsmsg: [UPS] Check Boot Status.
2022-01-02T11:11:05-07:00 cygni upsmsg: [UPS] Server is going to Safe Mode. It will stop all services and umount all volumes.
2022-01-02T11:11:06-07:00 cygni synopoweroff: system_sys_init.c:202 synopoweroff: Failed to [/usr/syno/sbin/synoraidtool --method=set -m][255](Success)[0x2000 file_get_key_value.c:81]
2022-01-02T11:11:06-07:00 cygni synopoweroff: system_sys_init.c:215 synopoweroff: System is going to reboot