This opus describes how to properly configure CyberPower UPS on a TrueNAS Core to ensure that the power is only pulled when safe.

The problems

There are three issues with leaving everything at defaults.

  • Relying on a critical battery alarm to shut down the server is a non-starter: most UPS, especially when the battery deteriorates, do not provide enough runtime to safely shut down the server. We want to configure remaining battery percentage or runtime thresholds manually.
  • TrueNAS Core uses Network Ups Tools to manage the connected UPS. Unfortunately, this package was designed for linux shutdown behaviour, that by the time shutdown command is complete, has the filesystem synced and re-mounted read-only, and the system ready to have power pulled from under it. FreeBSD does not re-mount filesystem, and the kernel takes care of flushing caches and finalizing the filesystem after the shutdown command completes. So when NUT shuts down the UPS power as soon as shutdown command completes – this results in an unclean shutdown. There is parameter offdelay that defines a delay in seconds between the UPS kill command is issued and power is pulled. By default, it’s 20 seconds, and unfortunately, this is not enough for most servers.
  • CyberPower UPSes, in particular, treat the offdelay parameter differently. They divide it by 60, and round down. Hence, the default 20 second value in CyberPower’s world means zero. It must be overwritten to at least 60, to prevent the UPS from yanking power immediately.

As a result, in the default configuration, the power is yanked as soon as shutdown command completes, but at this point the system is not yet ready to power off. On the next boot the user sees the alert about “Unscheduled System Restart”

The solution

In the Services -> UPS configure the following:

The Shutdown Command

Don’t use power-off, if your hardware is set to resume in the last state on power return, which is default on most systems: otherwise, the system will stay shut down. Instead, use the halt command:

/sbin/shutdown -h now

Runtime threshold monitoring

Tell the driver to ignore the low battery state reported by the UPS and instead compute it based on runtime and state of charge. This goes to ups.conf section:

override.battery.charge.low = 20
override.battery.runtime.low = 300

In this example, we set 20% low battery charge, and 5 min remaining runtime, whichever is lower.

CyberPower-specific offdelay override

CyberPower UPS divides the value by 60 and then rounds down, and uses the resulting number of minutes as a delay. In addition, on some models, the ondelay parameter can only be set to zero to ensure proper power-up behaviour. These also go to ups.conf box.


These values result in 2 minute power off delay, and 10 seconds (internal UPS default, evidently, on my specific model) power-on delay, when power is restored.