One approach was proposed in discussion with Lennart Poettering of systemd
fame, that operating system concepts constructed with (immutable) run-time
images are actually layered like onions, with code in another file system
(usually an initrd) picking the run-time image to use and chroot'ing into
it… and possibly regaining control when the run-time operating environment
exits. Sort of like containers, where the operating system which you interact
with is the inside of the container, and you do not directly see its hypervisor.
The problem is that while NUT services can run as part of the run-time image
and decide to power-off or power-cycle the UPS in case of trouble, there is
no space for classic NUT approach to do this in the end-game of that run-time
image (calling upsmon -K to detect the POWERDOWNFLAG file, and launching
some new instance of the driver to talk to the UPS itself) "after the filesystem
was remounted read-only", because that life-cycle concept has no such spot in
the state machine of the run-time image — its storage is to be completely
unmounted.
Instead, the proposed idea was to have a build of NUT included also into that
"managing" initrd image, with perhaps a /run (or similar) location passed
(bind-mounted?) from the initial environment into the launched run-time system.
Into such a location both the POWERDOWNFLAG file can be written and, as part
of NOTIFYCMD handling, the most-recent copies of NUT configuration files
which may be managed in the interactively accessible operating environment.
When the run-time image exits and the logic in initrd image which launched it
regains control, it can check for existence of the POWERDOWNFLAG file and
call its own copies of NUT drivers to talk to the UPS, and/or implement the
long sleep and reboot to avoid a power race condition, if needed.
See also: https://github.com/networkupstools/nut/issues/2836