So I found myself in a situation where I had to run 2 UPS's due to larger plugs not being able to fit if the adjacent socket was occupied. Obviously having 2 UPS's with the ability to control the server is a bad idea and typically the driver only accounts for one UPS at any one time.

This takes about 5-10 mins to setup and seems to work as expected.
Both UPS's are APC, a 1050VA and a 700ES. Both are connected to the server via USB. The driver is apcupsd.
Make sure both UPS's are powered on and connected via USB.
Make a note of the Bus / Device.
# lsusb
...
Bus 001 Device 004: ID 051d:0002 American Power Conversion Uninterruptible Power Supply
Bus 001 Device 005: ID 051d:0002 American Power Conversion Uninterruptible Power Supply
...
Let's make sure udev sees them.
# udevadm info --attribute-walk --name=/dev/bus/usb/001/004 | egrep 'manufacturer|product|serial'
ATTR{manufacturer}=="APC"
ATTR{product}=="Back-UPS ES 700G FW:871.O3 .I USB FW:O3 "
ATTR{serial}=="#########1 "
ATTRS{manufacturer}=="Linux 6.12.17-gentoo xhci-hcd"
ATTRS{product}=="xHCI Host Controller"
ATTRS{serial}=="0000:00:14.0"
# udevadm info --attribute-walk --name=/dev/bus/usb/001/005 | egrep 'manufacturer|product|serial'
ATTR{manufacturer}=="American Power Conversion"
ATTR{product}=="Back-UPS BE1050G2 FW:497200G -497300G "
ATTR{serial}=="##########2"
ATTRS{manufacturer}=="Linux 6.12.17-gentoo xhci-hcd"
ATTRS{product}=="xHCI Host Controller"
ATTRS{serial}=="0000:00:14.0"
Let's create a rule.
# vim /etc/udev/rules.d/ups.rules
# Main UPS
SUBSYSTEM=="usb", ATTR{manufacturer}=="American Power Conversion", ATTR{serial}=="########1 ", OWNER="root", SYMLINK+="ups-server"
# Secondary UPS
SUBSYSTEM=="usb", ATTR{manufacturer}=="APC", ATTR{serial}=="#######2", OWNER="root", SYMLINK+="ups-devices"
Note: The older of the 2 had spaces at the end of the serial number, so I kept them'
Reload Udev
# udevadm control --reload
Now let's check them udev rules.
# udevadm trigger -v -attr-match=serial="########1 "
# udevadm trigger -v -attr-match=serial="########2"
# ls -l /dev
You should see:
/dev/ups-devices -> bus/usb/001/004
/dev/ups-server -> bus/usb/001/005
Install the driver.
# emerge -av apcupsd
# systemctl stop apcupsd
# systemctl disable apcupsd
# cd /etc/apcupsd/
# mkdir apcupsd-devices
# mkdir apcupsd-server
# cp apcupsd.conf apcupsd-devices.conf apcupsd-server.conf
Modify as required:
apcupsd-server.conf
UPSNAME 1050VA
UPSCABLE usb
UPSTYPE usb /dev/ups-server
DEVICE
POLLTIME 60
LOCKFILE /run/apcupsd/
SCRIPTDIR /etc/apcupsd/apcupsd-server
PWRFAILDIR /etc/apcupsd/apcupsd-server
NOLOGINDIR /etc
ONBATTERYDELAY 6
BATTERYLEVEL 5
MINUTES 3
TIMEOUT 0
ANNOY 300
ANNOYDELAY 60
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 127.0.0.1
NISPORT 3551
EVENTSFILE /var/log/apcupsd-server.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 0
STATFILE /var/log/apcupsd-server.status
LOGSTATS off
DATATIME 0
apcupsd-devices.conf
UPSNAME 700ES
UPSCABLE usb
UPSTYPE usb /dev/ups-devices
POLLTIME 60
SCRIPTDIR /etc/apcupsd/apcupsd-devices
PWRFAILDIR /etc/apcupsd/apcupsd-devices
ONBATTERYDELAY 6
BATTERYLEVEL -1
MINUTES -1
TIMEOUT 0
ANNOY 0
ANNOYDELAY 0
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 127.0.0.1
NISPORT 3552
EVENTSFILE /var/log/apcupsd-devices.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 0
STATFILE /var/log/apcupsd-devices.status
LOGSTATS off
DATATIME 0
There needs to be 2 versions of the daemon running on different ports. The devices config does not allow for server control.
Copy the following scripts into the script directory specified in the configs.
apccontrol
changeme
commfailure
commok
offbattery
onbattery
safe.apccontrol
Startup Daemon (systemd)
Copy the systemd unit file for each daemon.
# cp /usr/lib/systemd/system/apcupsd.service /usr/lib/systemd/system/apcupsd-server.service
# cp /usr/lib/systemd/system/apcupsd.service /usr/lib/systemd/system/apcupsd-devices.service
Adjust each unit file accordingly:
[Service]
ExecStart=/sbin/apcupsd -b -f /etc/apcupsd/apcupsd-server.conf -P /run/apcupsd/apcupsd-server.pid
[Service]
ExecStart=/sbin/apcupsd -b -f /etc/apcupsd/apcupsd-devices.conf -P /run/apcupsd/apcupsd-devices.pid
Enable and start the services.
# systemctl --now enable apcupsd-server
# systemctl --now enable apcupsd-devices
If all went to plan, you should now see both daemons running.
# systemctl status apcupsd-server
● apcupsd-server.service - APC UPS Monitor
Loaded: loaded (/usr/lib/systemd/system/apcupsd-server.service; enabled; preset: disabled)
Active: active (running) since Sun 2025-03-09 20:58:55 GMT; 23h ago
Invocation: bea2f2a029de4384ba3b9fdb62dccc27
Main PID: 18929 (apcupsd)
Tasks: 3 (limit: 38270)
Memory: 2M (peak: 6.6M)
CPU: 2.669s
CGroup: /system.slice/apcupsd-server.service
└─18929 /sbin/apcupsd -b -f /etc/apcupsd/apcupsd-server.conf -P /run/apcupsd/apcupsd-server.pid
Mar 09 20:58:55 hostname systemd[1]: Started APC UPS Monitor.
Mar 09 20:58:55 hostname apcupsd[18929]: apcupsd 3.14.14 (31 May 2016) gentoo startup succeeded
Mar 09 20:58:55 hostname apcupsd[18929]: NIS server startup succeeded
Mar 09 21:02:13 hostname apcupsd[18929]: Communications with UPS restored.
# systemctl status apcupsd-devices
● apcupsd-devices.service - APC UPS Monitor
Loaded: loaded (/usr/lib/systemd/system/apcupsd-devices.service; enabled; preset: disabled)
Active: active (running) since Sun 2025-03-09 20:58:48 GMT; 23h ago
Invocation: 6079648a84d74eda9d48aa43e31aaf14
Main PID: 18820 (apcupsd)
Tasks: 3 (limit: 38270)
Memory: 408K (peak: 4.8M)
CPU: 2.662s
CGroup: /system.slice/apcupsd-devices.service
└─18820 /sbin/apcupsd -b -f /etc/apcupsd/apcupsd-devices.conf -P /run/apcupsd/apcupsd-devices.pid
Mar 09 20:58:48 hostname systemd[1]: Started APC UPS Monitor.
Mar 09 20:58:48 hostname apcupsd[18820]: apcupsd 3.14.14 (31 May 2016) gentoo startup succeeded
Mar 09 20:58:48 hostname apcupsd[18820]: NIS server startup succeeded
Mar 09 21:02:13 hostname apcupsd[18820]: Communications with UPS restored.
With this setup, I get an email should there be any interruption on either UPS or when the battery requires replacing.
Go on, give them a test and cut the power ;)