Featured image

The Silent Enemy of the Homelab Link to heading

Every now and then in my area they cut the power. Nothing dramatic, it just happens that while you’re working peacefully everything shuts down: the mini PC LED goes off, the router goes offline, and you realize that all the containers are doing an unexpected reboot.

Warning

Inconveniences of an Unexpected Shutdown

  • Possible filesystem corruption in LXC containers
  • Loss of unsaved data in databases
  • Occasional need for filesystem check on Proxmox
  • Manual restart of all services

So I decided to invest in a UPS (Uninterruptible Power Supply).

Network UPS Tools: The Bridge between Hardware and Software Link to heading

NUT is the standard software for UPS management on Linux systems. It allows you to:

  • Monitor UPS status in real-time
  • Configure automatic actions in case of events (blackout, low battery)
  • Share UPS information on the network (useful for shutting down multiple devices)
  • Integrate with monitoring systems like Grafana

Installing NUT on Proxmox Link to heading

We will install NUT directly on the Proxmox main node, not in an LXC container. This approach ensures that:

  • The UPS monitoring system remains active even if containers are shut down
  • Proxmox can manage the shutdown of all containers before shutting down itself
  • There are no circular dependencies (container depending on host to shut down)
  • USB communication with the UPS is direct and reliable
Info
Why Not in a Container? Although we could install NUT in an LXC container, installing it on the Proxmox host is the most robust choice: it ensures that the protection system is always operational and can orchestrate the shutdown of the entire homelab in a coordinated manner.

First of all, let’s install only the essential package on Proxmox:

apt update
apt install nut
Info

Simplified NUT Architecture

  • nut-driver: Communicates directly with the UPS via USB
  • nut-server (upsd): Shares UPS data on the network (optional for single setup)
  • nut-monitor (upsmon): Monitors and manages actions (shutdown)

For a simple homelab setup, we can use only driver + monitor, skipping the network server.

File 1: nut.conf - “How does NUT work?” Link to heading

Main file that defines the operating mode:

nano /etc/nut/nut.conf
MODE=standalone

What it means:

  • MODE=standalone: “Everything on this machine: driver, monitor, and physical UPS are here”
  • Possible alternatives: netserver (shares UPS on network) or netclient (uses remote UPS)

File 2: upsmon.conf - “When to shut down everything?” Link to heading

The brain of the system: decides when and how to shut down Proxmox:

nano /etc/nut/upsmon.conf
MONITOR epyc-ion@localhost 1 admin password master

SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
DEADTIME 15
POWERDOWNFLAG /etc/killpower

NOTIFYFLAG ONBATT SYSLOG+WALL
NOTIFYFLAG LOWBATT SYSLOG+WALL
NOTIFYFLAG ONLINE SYSLOG+WALL

Detailed explanation:

MONITOR epyc-ion@localhost 1 admin password master

  • epyc-ion@localhost: “Monitor the UPS named ’epyc-ion’ on this machine”
  • 1: “This UPS powers 1 system (this Proxmox)”
  • admin password: Credentials to access UPS data (local, basic security)
  • master: “This machine is the boss, decides when to shut down everything”

SHUTDOWNCMD “/sbin/shutdown -h +0”

  • “When you decide to shut down, execute this command”
  • -h +0: Immediate halt (without waiting)
Warning
Immediate vs Graceful Shutdown shutdown -h +0 shuts down the system immediately. Proxmox automatically handles graceful shutdown of LXC containers during the node shutdown process, so there’s no need to create complex scripts to shut down each container individually.

POLLFREQ 5

  • “Check UPS status every 5 seconds” (normal frequency)

DEADTIME 15

  • “If I don’t receive UPS data for 15 seconds, consider the UPS dead”

POWERDOWNFLAG /etc/killpower

  • “Create this file when shutting down to tell the system not to restart”

NOTIFYFLAG

  • ONBATT: “When going on battery, write to logs + screen message”
  • LOWBATT: “When battery is low, write to logs + screen message”
  • ONLINE: “When power returns, write to logs + screen message”
Info

Master vs Slave

  • Master: “I command, when I decide it’s time, I shut down everything”
  • Slave: “I listen to the master, I shut down when told”

In our case we are master because we are the only machine connected to the UPS.

UPS Identification and Permission Troubleshooting Link to heading

Before testing the driver, we need to correctly identify the UPS and resolve USB permissions.

Step 1: Identify the UPS Link to heading

lsusb

Look for a line similar to:

Bus 001 Device 003: ID 0764:0601 Cyber Power System, Inc. PR1500LCDRT2U UPS

The numbers 0764:0601 are the vendorid and productid of your UPS.

Step 2: Configure File 3: ups.conf for Epyc ION UPS Link to heading

For Epyc ION UPS (which identify as Cyber Power System), use the HID driver:

nano /etc/nut/ups.conf
[epyc-ion]
    driver = usbhid-ups
    port = auto
    desc = "Epyc Ion"
Info
HID vs Serial Driver Epyc ION UPS use HID (Human Interface Device) interface, not serial. For this reason the correct driver is usbhid-ups, not nutdrv_qx. The HID driver automatically recognizes the UPS without needing to specify vendorid/productid.

Step 3: Verify NUT Version Link to heading

Epyc ION UPS require NUT 2.8.0 or higher. Check your version:

upsdrvctl -V

If you have an earlier version (2.7.x), upgrade:

# Only if necessary - for Proxmox/Debian
apt update
apt install nut/bullseye-backports

# Or add updated NUT repository
Warning
Version Compatibility NUT 2.7.x does not properly support Epyc ION UPS. With NUT 2.8+ they work automatically without special permission configurations.

Testing UPS Driver Link to heading

Now let’s test the driver:

# Start the driver
upsdrvctl start epyc-ion

If everything goes well, you should see:

Network UPS Tools - Generic HID driver 0.52 (2.8.1)
USB communication driver (libusb 1.0) 0.46
Using subdriver: CyberPower HID 0.8

If you get “connection refused”, start all NUT services in the correct order:

# Stop everything to start clean
systemctl stop nut-monitor
systemctl stop nut-server
upsdrvctl stop

# Start in order: Driver → Server → Monitor
upsdrvctl start epyc-ion
systemctl start nut-server
systemctl start nut-monitor

# Enable at Proxmox boot
systemctl enable nut-server
systemctl enable nut-monitor

Verify the communication:

# Check UPS data
upsc epyc-ion

You should see output similar to:

battery.charge: 100
battery.voltage: 13.70
input.voltage: 230.0
ups.load: 25
ups.status: OL
Info
NUT Architecture The flow is: Driver (communicates with UPS) → nut-server (shares data) → nut-monitor (manages shutdown). If upsc gives “connection refused”, it means the driver works but the server is not started.

Complete Verification Link to heading

Verify that everything works:

# Check UPS status
upsc epyc-ion

# Verify monitoring configuration
upsmon -D

If everything works, you should see UPS information:

battery.charge: 100
battery.voltage: 13.70
input.voltage: 230.0
ups.load: 25
ups.status: OL
Info

Main Status Codes

  • OL: Online (normal power)
  • OB: On Battery (running on battery)
  • LB: Low Battery (battery low)

Shutdown Test (Optional) Link to heading

To test automatic shutdown without risks:

# Simulate "low battery" event
upsmon -c fsd

This will force a controlled shutdown. Use this only if you’re sure you want to test the complete shutdown.

Warning
Real Test The safest test is to unplug the UPS power for a few seconds and verify that the system shuts down automatically when the battery is low.

With this minimal configuration, Proxmox will automatically shut down when the UPS signals low battery, protecting data without complex configurations.

Container Management during Shutdown Link to heading

A legitimate question: do you need to manually shut down each container before shutting down Proxmox?

Short answer: No.

Proxmox automatically handles graceful shutdown of all LXC containers when it receives the shutdown command. The process is:

  1. NUT detects low battery
  2. upsmon executes shutdown -h +0
  3. Proxmox receives shutdown signal
  4. Proxmox sends SIGTERM to all containers
  5. Containers execute internal graceful shutdown
  6. Proxmox waits for a timeout (default 60s) for slow containers
  7. Proxmox forces stop if necessary
  8. System shuts down completely
Info
Why Proxmox Does It Well Proxmox is designed to manage VMs and containers as a professional hypervisor. It knows how to shut down everything in an orderly manner without losing data, just like VMware or Hyper-V.

If you have particularly critical containers with complex databases, you can create a custom script, but for a standard homelab Proxmox’s default behavior is more than sufficient.

Conclusions Link to heading

Implementing NUT on Proxmox transforms a simple UPS into an intelligent protection system for our homelab. The configuration is simple and once set up it works automatically, ensuring safe shutdowns relying on Proxmox’s native management.

Tip

Next Steps

  • Test periodically by unplugging power for a few seconds
  • Monitor logs to verify that everything works as expected
  • Document the real autonomy times of your setup

A modest investment that can avoid many future headaches.