Config Examples
Config Examples
Conguration Examples
Based on
Conforms to
i
This introduction is based on the Network UPS Tools (NUT) User Manual, the man pages and
the le config-notes.txt which do not carry explicit copyright notices, but which are part of the
NUT package which is GPL licensed.
Copyright © Russell Kroll, Arnaud Quette, Arjen de Korte, Charles Lepple and others
This program is free software; you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PUR-
POSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not,
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
http://www.fsf.org/licenses/old-licenses/gpl-2.0.html
©
Additional material:
Copyright Roger Price 2017, 2018, 2020, 2021, 2022, 2023
Distributed under the GPLv3. http://www.fsf.org/licenses/gpl.html
A
The source le for this document has been marked up by the editor in L TEX 2ε and rendered as
PDF le CongExamples.A5.pdf in a portrait A5 format, 131 pages with one page per sheet. Your
PDF viewer may be able to place two pages side by side on your big monitor.
The document is not only linear reading, but also hypertext. All chapters in the table of
contents, all chapter references, all line number references throughout the document, all man page
names and URL's are clickable. Such links are outlined in colour, for example man ups.conf. If
your mouse hovers over a clickable surface, your browser/PDF reader may tell you where the link
leads.
ii
Page dimensions
Dimension Design (A5) Actual pt Actual mm
\hoset -29.4mm -83.65106pt -29.39963 mm
\voset -29.4mm -83.65106pt -29.39963 mm
\pdfpageheight 240mm 682.86613pt 239.99718 mm
\pdfpagewidth 197.5mm 561.94193pt 197.49768 mm
\textheight 210mm 597.50787pt 209.99753 mm
\textwidth 177.5mm 505.03642pt 177.49791 mm
\linewidth 505.03642pt 177.49791 mm
\columnsep 15mm 42.67912pt 14.99982 mm
\LinePrinterwidth 145.5mm 413.9876pt 145.49829 mm
Changes:
2018-08-22 In chapter 3.1 added reference to issue #597 for multiple UPS units.
2021-05-16 Split Part 2 into two parts: new Part 2 for the shim daemons, and a new part 3
for the Python3 replacement for upsmon and upssched. The Appendix becomes Part 4.
2021-08-03 Claried that command upsmon -c fsd calls the command specied by declara-
tion SHUTDOWNCMD.
2022-08-02 Updated to NUT software version 2.8.0, protocol version 1.3 and RFC 9271. Re-
moved Part 3 UPSmon.py. Appendices become Part 3.
iii
Contents
iv
4.4 The shutdown story for a workstation . . . . . . . . . . . . . . . . . . . . . . . . 31
v
2 TLS support for upsd and clients 69
9 Introduction 69
9.1 Use of Python3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
9.1.1 No object orientation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
9.1.2 Lint-free code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
11 Encrypted connections 78
11.1 Additional conguration les . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
11.1.1 In the remote server gold . . . . . . . . . . . . . . . . . . . . . . . . . . 79
11.1.2 In each management client mgmt . . . . . . . . . . . . . . . . . . . . . . 79
11.2 Debugging: Sning port 3493 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
11.3 Testing the TLS setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3 Appendices 90
A Starting NUT 90
B Stopping NUT 92
B.1 Delayed UPS shutdown with NUT script . . . . . . . . . . . . . . . . . . . . . . . 92
B.2 Delayed UPS shutdown with a systemd service unit . . . . . . . . . . . . . . . . . 93
vi
D Using notify-send 96
D.1 What's wrong with notify-send? . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
D.2 Give user nut (upsd) the right to act as any user . . . . . . . . . . . . . . . . 97
D.3 Search for and notify logged in users . . . . . . . . . . . . . . . . . . . . . . . . . 98
D.4 Testing the notify-send-all setup . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
D.5 References for notify-send . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
vii
J UPSmon.py installation checklist 130
K Acknowledgments 131
List of Figures
1 Overview of NUT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2 Symbols used in ups.status maintained by upsd. . . . . . . . . . . . . . . . . . . . 3
3 Wall power has failed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
4 Symbols used to represent NOTIFY events maintained by upsmon. . . . . . . . . . 5
5 NUT terms changed by NUT 2.8.0 and the RFC. . . . . . . . . . . . . . . . . . . . 8
6 Server with no local users. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
7 Conguration le ups.conf, rst attempt. . . . . . . . . . . . . . . . . . . . . . . . 9
8 Conguration le upsd.conf. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
9 Conguration le upsd.users for a simple server. . . . . . . . . . . . . . . . . . . . 10
10 Conguration le upsmon.conf for a simple server, part 1 of 5. . . . . . . . . . . . . 11
11 Conguration le upsmon.conf for a simple server, part 2 of 5. . . . . . . . . . . . . 11
12 Conguration le upsmon.conf for a simple server, part 3 of 5. . . . . . . . . . . . . 12
13 Conguration le upsmon.conf for a simple server, part 4 of 5. . . . . . . . . . . . . 12
14 Flags declaring what upsmon is to do for NOTIFY events. . . . . . . . . . . . . . . 12
15 Conguration le upsmon.conf for a simple server, part 5 of 5. . . . . . . . . . . . . 12
16 Delayed UPS shutdown. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
17 openSUSE script for delayed UPS shutdown. . . . . . . . . . . . . . . . . . . . . . . 14
18 Conguration le ups.conf, improved. . . . . . . . . . . . . . . . . . . . . . . . . . 17
19 Server with multiple power supplies. . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
20 File ups.conf for multiple power supplies. . . . . . . . . . . . . . . . . . . . . . . . 21
21 Conguration le upsmon.conf for multiple power supplies, part 1 of 5. . . . . . . . 21
22 Experiment to show eect of lost UPS. Part 1, . . . . . . . . . . . . . . . . . . . . . 22
23 Experiment to show eect of lost UPS. Part 2, . . . . . . . . . . . . . . . . . . . . . 23
24 Workstation with local users. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
25 Conguration le upsmon.conf for a workstation, part 1 of 5. . . . . . . . . . . . . 26
26 Conguration le upsmon.conf for a workstation, part 2 of 5. . . . . . . . . . . . . 26
27 Conguration le upsmon.conf for a workstation, part 3 of 5. . . . . . . . . . . . . 27
28 Conguration le upsmon.conf for a workstation, part 4 of 5. . . . . . . . . . . . . 27
29 Conguration le upsmon.conf for a workstation, part 5 of 5. . . . . . . . . . . . . 27
viii
30 Conguration le upssched.conf for a Debian 11 workstation, Part 1. . . . . . . . 28
31 Conguration le upssched.conf for a Debian 11 workstation, Part 2. . . . . . . . 28
32 Conguration script upssched-cmd for a workstation. . . . . . . . . . . . . . . . . . 29
33 Secondary workstations take power from same UPS as primary. . . . . . . . . . . 32
34 Conguration le upsmon.conf for a secondary, part 1 of 5. . . . . . . . . . . . . . 33
35 Conguration le upsmon.conf for a secondary, part 2 of 5. . . . . . . . . . . . . . 33
36 Conguration le upsmon.conf for a secondary, part 3 of 5. . . . . . . . . . . . . . 34
37 Conguration le upsmon.conf for a secondary, part 4 of 5. . . . . . . . . . . . . . 34
38 Conguration le upsmon.conf for a secondary, part 5 of 5. . . . . . . . . . . . . . 35
39 Conguration le upssched.conf for a secondary. . . . . . . . . . . . . . . . . . . . 35
40 Conguration script upssched-cmd for a secondary. . . . . . . . . . . . . . . . . . . 36
41 Workstation with heartbeat. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
42 Conguration le ups.conf for workstation with heartbeat. . . . . . . . . . . . . . 39
43 Conguration le heartbeat.conf for workstation. . . . . . . . . . . . . . . . . . . 40
44 Conguration le upsmon.conf for a workstation with heartbeat. . . . . . . . . . . 40
45 Conguration le upssched.conf for a workstation with heartbeat. . . . . . . . . . 41
46 Conguration script upssched-cmd including heartbeat. . . . . . . . . . . . . . . . . 42
47 Heartbeat watcher. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
48 Workstation with timed shutdown. . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
49 Conguration le ups.conf for workstation with timed shutdown. . . . . . . . . . . 45
50 This is the conguration le heartbeat.conf for a workstation with timed shutdown. 46
51 Conguration le upsd.conf for workstation with timed shutdown. . . . . . . . . . 46
52 This is the conguration le upsd.users for a simple server. . . . . . . . . . . . . . 47
53 Conguration le upsmon.conf with timed shutdown, part 1 of 5. . . . . . . . . . . 47
54 Conguration le upsmon.conf with timed shutdown, part 2 of 5. . . . . . . . . . . 48
55 Conguration le upsmon.conf with timed shutdown, part 3 of 5. . . . . . . . . . . 49
56 Conguration le upsmon.conf with timed shutdown, part 4 of 5. . . . . . . . . . . 49
57 Conguration le upsmon.conf with timed shutdown, part 5 of 5. . . . . . . . . . . 50
58 Conguration le upssched.conf with timed shutdown, part 1. . . . . . . . . . . . 50
59 Conguration le upssched.conf with timed shutdown, part 2. . . . . . . . . . . . 51
60 Conguration script upssched-cmd for timed shutdown, 1 of 2. . . . . . . . . . . . . 52
61 Conguration script upssched-cmd for timed shutdown, 2 of 2. . . . . . . . . . . . . 53
62 Workstation with additional equipment. . . . . . . . . . . . . . . . . . . . . . . . . 56
63 File nut.conf for gold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
64 Files nut.conf for mgmt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
65 File ups.conf for gold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
66 File ups.conf for mgmt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
67 heartbeat.conf for mgmt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
68 File upsd.conf for gold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
69 File upsd.conf for mgmt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
70 File upsd.users for gold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
ix
71 File upsd.users for mgmt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
72 Conguration le upsmon.conf for mgmt , part 1 of 5. . . . . . . . . . . . . . . . . 60
73 Conguration le upsmon.conf for mgmt , part 2 of 5. . . . . . . . . . . . . . . . . 61
74 Conguration le upsmon.conf for mgmt , part 3 of 5. . . . . . . . . . . . . . . . . 62
75 Conguration le upsmon.conf for mgmt , part 4 of 5. . . . . . . . . . . . . . . . . 62
76 Conguration le upsmon.conf for mgmt , part 5 of 5. . . . . . . . . . . . . . . . . 63
77 Conguration le upssched.conf for mgmt . . . . . . . . . . . . . . . . . . . . . . . 64
78 User script upssched-cmd on mgmt , 1 of 5. . . . . . . . . . . . . . . . . . . . . . . . 65
79 User script upssched-cmd on mgmt , 2 of 5. . . . . . . . . . . . . . . . . . . . . . . . 66
80 User script upssched-cmd on mgmt , 3 of 5. . . . . . . . . . . . . . . . . . . . . . . . 66
81 User script upssched-cmd on mgmt , 4 of 5. . . . . . . . . . . . . . . . . . . . . . . . 67
82 User script upssched-cmd on mgmt , 5 of 5. . . . . . . . . . . . . . . . . . . . . . . . 67
83 File pylintrc, Changes to the default Python style. . . . . . . . . . . . . . . . . . . . 70
84 Command mkNETcert.py --help. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
85 Root certicate = private key and certicate. . . . . . . . . . . . . . . . . . . . . . 74
86 The client's PEM encoded public certicate. . . . . . . . . . . . . . . . . . . . . . . 75
87 The self-signed public certicate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
88 Encrypted connection to remote server. . . . . . . . . . . . . . . . . . . . . . . . . . 78
89 tcpdump of systemctl start nut-monitor.service without encryption. . . . . . 80
90 Unencrypted trac on port 3493 (nut). . . . . . . . . . . . . . . . . . . . . . . . . . 81
91 Encrypted trac on port 401. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
92 NUT 2.7.4 TLS support using shims upsdTLS.py and upsmonTLS.py. . . . . . . . . 82
93 Command upsdTLS.py --help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
94 Command upsmonTLS.py --help . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
95 Summary of upsdTLS.py and upsmonTLS.py options and default values. . . . . . . 86
96 systemd service unit nut-py-server-shim.service for upsdTLS.py. . . . . . . . . 87
97 systemd service unit nut-py-client-shim.service for upsmonTLS.py. . . . . . . . 87
98 Example of systemd service unit activity for NUT. . . . . . . . . . . . . . . . . . . . 89
99 Conguration le nut.conf. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
100 Daemons used by NUT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
101 UPS shutdown script nutshutdown. . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
102 UPS shutdown script nutshutdown for 2 of 3 UPS's. . . . . . . . . . . . . . . . . . . 92
103 UPS shutdown service unit nut-delayed-ups-shutdown.service. . . . . . . . . . . 93
104 Users and directories for NUT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
105 Example of a notication. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
106 Modications to le /etc/sudoers . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
107 Bash script notify-send-all . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
108 Log rotation for upsdTLS.py and UPSmon.py . . . . . . . . . . . . . . . . . . . . . 100
109 UPSmon.py requires TLS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
110 Actions provided by UPSmon.py. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
111 % substitutions available in messages. . . . . . . . . . . . . . . . . . . . . . . . . . . 103
x
112 Command UPSmon.py --help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
113 systemd service unit nut-py-monitor.service for UPSmon.py. . . . . . . . . . . . 106
114 Symbols used to represent events monitored by UPSmon.py. . . . . . . . . . . . . . 108
115 Additional status symbols generated by UPSmon.py. . . . . . . . . . . . . . . . . . 109
116 Additional events monitored by UPSmon.py. . . . . . . . . . . . . . . . . . . . . . . 109
117 System log urgency levels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
118 Alternative text bracketing characters. . . . . . . . . . . . . . . . . . . . . . . . . . 115
119 UPSmon.conf lexer tokens. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
120 UPSmon.conf lexer tokens. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
121 Representation of grammar production . . . . . . . . . . . . . . . . . . . . . . . . . 118
122 UPSmon.conf grammar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
123 UPSmon.conf grammar, continued. . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
124 UPSmon.conf grammar, nal part. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
125 Command mkUPSmonconf.py --help . . . . . . . . . . . . . . . . . . . . . . . . . . 121
126 Timed shutdown plan, part 1 of 4, the introduction. . . . . . . . . . . . . . . . . . . 123
127 Timed shutdown plan, part 2 of 4, the shutdown. . . . . . . . . . . . . . . . . . . . 124
128 Timed shutdown plan, part 3 of 4, warnings, . . . . . . . . . . . . . . . . . . . . . . 126
129 Conguration le heartbeat.conf . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
130 Addition to the le ups.conf for heartbeat.conf . . . . . . . . . . . . . . . . . . . 127
131 Timed shutdown plan, part 4 of 4, heartbeat. . . . . . . . . . . . . . . . . . . . . . 128
132 Standard shutdown plan dierences . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
133 Timed shutdown on MINSUPPLIES failure . . . . . . . . . . . . . . . . . . . . . . . . 129
134 upsd and UPSmon.py runtime processes . . . . . . . . . . . . . . . . . . . . . . . . 130
xi
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Part 1
Attachment Management
daemon daemon
upsd upsmon
overview-OL.svg
port [ONLINE]
Driver 3493/tcp
UPS-1 upsdrvctl (nut)
upsc
ups.status: [OL]
The acronym NUT stands for Network UPS Tools. It is a collection of GPL licensed software
written in K&R style C for managing power devices, mainly UPS units. It supports a wide range
of UPS units and can handle one or multiple UPS's of dierent models and manufacturers simul-
taneously in home, small business and larger professional installations. NUT replaces the software
which came with your UPS.
The NUT software is included as a package in most major distributions of Linux, and the source
code is available in a tarball for the others.
The NUT software includes complete technical documentation in the form of PDF manuals,
conguration notes such as le config-notes.txt, man pages, a web site http://networkupstools
.org and detailed comments in the sample conguration les supplied with the project. There is also
a FAQ on the project web site, and a nut-upsuser mailing list in which users may ask questions.
Page 1 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
NUT was already operating in its current form when it registered port 3493/TCP (nut) with IANA
in May 2002. Since then, the project has kept its principal characteristics which are the basis of its
success:
Simplicity The design of NUT is simple and straightforward. No additional tools or software
systems are needed to encode the messages sent between the attachment daemon and the
management daemon.
Resilience The ability to operate in a challenged environment. Such environments are now
receiving attention, for example the evolving vocabulary provided by RFC 7228 Terminology
for Constrained-Node Networks.
Aggregation The simultaneous handling of a wide variety of UPS-things with widely diering
capabilites. This is now known as the Internet of Things, and again is the subject of much
attention.
To make full use of your UPS you will need to congure the NUT software used to manage UPS
units. The technically complete documentation does not provide many examples; this introduction
is intended to ll the gap by providing fully worked examples for some frequently met congurations.
It is aimed at experienced Unix/Linux system administrators who are new to NUT. Pick the
conguration which corresponds most closely to your installation, get it working, and then adapt
it to your needs. If you have questions for the mailing list it is much easier to explain what you are
trying to do by referring to a well known example.
Figure 1 shows the basic components of the NUT software. upsd is a daemon which runs per-
manently in the box to which one or more UPS's are attached. It scans the UPS's through the
1 2
UPS-specic driver and maintains an abstracted image of the UPS in memory .
The various parts of the abstracted image have standardized names, and a key part is the
variable ups.status which gives the current status of the UPS unit. The current status is a string
of symbols. The principal symbols are shown in gure 2, but if you write software which processes
upsd symbols, expect to nd other values in exceptional UPS specic cases.
Some important status values are [ol] which means that the UPS unit is taking power from the
wall, and [ob lb] which means that wall power has failed, the UPS is supplying power from it's
battery, and that battery is almost exhausted.
Page 2 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Daemon upsd listens on port 3493/tcp (nut) for requests from its clients, which may be local or
remote. It is amusing to test this using a tool such as nc or netcat and a UPS called UPS-1.
1 rprice@maria:~> REQUEST="GET VAR UPS-1 battery.charge"
2 rprice@maria:~> echo $REQUEST | nc localhost 3493
3 VAR UPS-1 battery.charge "100"
Chapter 1.4.1 will show that this is best done with NUT utility program upsc.
Later chapters will discuss the conguration les ups.conf, upsd.conf and upsd.users with
the specic examples. For gory details, read man upsd, man upsd.conf, man upsd.users and man
ups.conf.
Page 3 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
3 Communication between upsd and each driver is through a socket which Debian 11 declares in directory /var/
run/nut . The following example shows the sockets to two drivers usbhid-ups and dummy-ups :
root@titan ls -alF /run/nut
drwxrwx- 2 root nut 140 Aug 7 15:57 ./
drwxr-xr-x 30 root root 880 Aug 7 16:01 ../
srw-rw 1 nut nut 0 Aug 7 15:57 dummy-ups-heartbeat=
-rw-rr 1 nut nut 5 Aug 7 15:57 dummy-ups-heartbeat.pid
-rw-rr 1 nut nut 5 Aug 7 15:57 upsd.pid
srw-rw 1 nut nut 0 Aug 7 15:57 usbhid-ups-Eaton=
-rw-rr 1 nut nut 4 Aug 7 15:57 usbhid-ups-Eaton.pid
Page 4 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Daemon upsmon has polled upsd, has discovered the status change and has generated the NOTIFY
event [onbatt].
For the gory details, read man upsmon and man upsmon.conf.
The NUT project provides this simple utility program to talk to upsd and retrieve details of the
UPS's. For example, What UPS's are attached to the local host?
4 rprice@maria:~> upsc -L
5 UPS-1: Example Mfg ASR 1500 USBS
6 heartbeat: Heart beat validation of NUT
Let's ask for the upsd abstracted image of a UPS:
Page 5 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Let's ask, using Bash syntax, for a list of the drivers used by upsd:
The components of NUT get their conguration from the following conguration les. The simpler
congurations do not use all these les.
NUT parses all the conguration les with a common state machine, which means they all have
the following characteristics.
First, most of the programs use an uppercase word to declare a conguration directive. This
may be something like MONITOR, NOTIFYCMD, or ACCESS. Case matters here. monitor won't be
recognized.
Next, the parser does not care about whitespace between words. If you like to indent things
with tabs or spaces, feel free to do so.
The keywords are often followed by values. If you need to set a value to something containing
spaces, it has to be contained within quotes to keep the parser from splitting the line, e.g.
Without the quotes, the parser would only see the rst word on the line. Let's say you really
need to embed a quote within your directive for some reason. You can do that too.
Page 6 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
The \ can be used to escape any character, but you only really need it for \, " , and # as they
have special meanings to the parser.
When using le names with space characters, you may end up having tricky things since you
need to write them inside "" which must be escaped:
25 identity = my#1ups
will turn into identity = my, since the # stops the parsing. If you really need to have a # in
your conguration, then escape it.
26 identity = my\#1ups
Much better.
The = character should be used with care too. There should be only one simple = character in
a line: between the parameter name and its value. All other = characters should be either escaped
or within quotes. Remember that the # character in a password must be escaped:
You can put a backslash at the end of the line to join it to the next one. This creates one virtual
line that is composed of more than one physical line.
Also, if you leave the "" quote container open before a newline, it will keep scanning until it
reaches another one. If you see bizarre behavior in your conguration les, check for an unintentional
instance of quotes spanning multiple lines.
Page 7 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
The NUT project oers a mailing list to assist the users. The web page for list administration is
https://lists.alioth.debian.org/mailman/listinfo/nut-upsuser.
As always in mailing lists, you get better results if you remember Eric Raymond's good advice
which you will nd in How To Ask Questions The Smart Way at http://www.catb.org/esr/faqs/
smart-questions.html.
The NUT mailing lists accept HTML formatted e-mails, but it's better to get into the habit of
sending only plain text, since you will meet mailing lists that send HTML to /dev/null.
If you want to quote conguration les, please remove comments and blank lines. A command
such as grep ^[^#] upsmon.conf will do the job. To save you some work, there is ready-made
script to prepare a report on a NUT conguration. See nut-report script available at http://
rogerprice.org/NUT/nut-report.
On August 8th, 2022, the IETF published RFC 9271 Uninterruptible Power Supply (UPS) Manage-
ment Protocol Commands and Responses which describes in detail the commands and responses
of the NUT protocol. The RFC follows changes in the technical terms used by the NUT Project
and listed in gure 5.
The RFC uses the term public power supply where this text refers to wall power.
Now that we have the basic ideas of NUT, we are ready to look at the rst simple conguration.
Page 8 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
upsmon
[ONLINE]
upsd
upsdrvctl port
3493/tcp
UPS-1 + driver upsc
(nut)
server.svg
ups.status: [OL] upsrw
upscom
Six conguration les specify the operation of NUT in the simple server.
1. The NUT startup conguration: nut.conf. Since this le is not strictly a part of NUT, and
is common to all congurations, it is discussed separately in appendix A.
6. The delayed UPS shutdown script. Since this le is common to all congurations, it is
discussed separately in appendix B.
31 # ups.conf, first attempt This conguration le declares your UPS units.
32 [UPS-1] The le described here will do the job, but we will
Figure 7: Conguration le ups.conf, names the UPS unit UPS-1. There will as many
sections as there are UPS units. Make sure this
rst attempt.
UPS name matches the name in upsmon.conf and
in upssched-cmd, which we will meet in later chap-
ters.
Page 9 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Line 33 species the driver that upsd will use. For the full list of drivers, see the Hardware
Compatibility list and the required drivers at http://www.networkupstools.org/stable-hcl.html.
Line 34 depends on the driver. For the usbhid-ups driver the value is always auto. For other
drivers, see the man page for that driver.
Line 35 provides a descriptive text for the UPS.
37 LISTEN 127.0.0.1 3493 upsd daemon will listen, and provides a basic ac-
Page 10 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
This conguration le declares how upsmon is to handle NOTIFY events. For good security, ensure
6
that only users nut and root can read and write this le.
43 # upsmon.conf
44 MONITOR UPS-1@localhost 1 nut-admin sekret primary
Figure 10: Conguration le upsmon.conf for a simple server, part 1 of 5.
On line 44
The UPS name UPS-1 must correspond to that declared in ups.conf line 32.
The power value 1 is the number of power supplies that this UPS feeds on this system.
primary means this system will shutdown last, allowing any secondaries time to shutdown
rst. Secondary systems will be discussed in chapter 5. There are no secondaries in this
simple conguration.
Line 45 declares the command that is to be used to shut down the server. A second instance of
the upsmon daemon running as root will execute this command. Multiple commands are possible,
for exampleSHUTDOWNCMD "logger -t upsmon.conf \"SHUTDOWNCMD calling /sbin/shutdown
to shut down system\" ; /sbin/shutdown -h +0" will also log the action of SHUTDOWNCMD. Note
that internal " have to be escaped.
Line 46 declares a le created by upsmon when running in primary mode when the UPS needs to
be powered o. It will be used in more complex congurations. See man upsmon.conf for details.
Lines 47-56 assign a text message to each NOTIFY event. Within each message, the marker %s
is replaced by the name of the UPS which has produced this event. upsmon passes this message
to program wall to notify the system administrator of the event. You can change the default
messages to something else if you like. The format is NOTIFYMSG event "message " where %s is
replaced with the identier of the UPS in question.
Lines 57-66 declare what is to be done at each NOTIFY event. The declarations, known as
ags are shown in table 14. You may specify one, two or three ags for each event, in the form
FLAG[+FLAG]*, however IGNORE must always be alone.
Note that if you have multiple UPS's, the same actions are to be performed for a given NOTIFY
event for all the UPS's. We will see later that this is not good news.
6 This is for Debian 11. See table 104 in appendix C for other user names.
Page 11 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
67 RBWARNTIME 43200
68 NOCOMMWARNTIME 300
69 FINALDELAY 5
Figure 15: Conguration le upsmon.conf for a simple server, part 5 of 5.
When a UPS says that it needs to have its battery replaced, upsmon will generate a [replbatt]
NOTIFY event. Line 67 say that this happens every RBWARNTIME = 43200 seconds (12 hours).
Page 12 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Line 68: Daemon upsmon will trigger a [nocomm] NOTIFY event after NOCOMMWARNTIME sec-
onds if it can't reach any of the UPS entries in conguration le upsmon.conf. It keeps warning
you until the situation is xed.
Line 69: When running in primary mode, upsmon waits this long after sending the [shutdown]
NOTIFY event to warn the users. After the timer elapses, it then runs your SHUTDOWNCMD as
specied on line 45. If you need to let your users do something in between those events, increase
this number. Remember, at this point your UPS battery is almost depleted, so don't make this too
big. Alternatively, you can set this very low so you don't wait around when it's time to shut down.
Some UPS's don't give much warning for low battery and will require a value of 0 here for a safe
shutdown.
For lots and lots of details, see man upsmon.conf. See also the le config-notes.txt in the
distribution.
Page 13 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
delayedUPSshutdown.svg
beep to be an action to send a message to the
beep UPS to tell it that some time later, it too
beep upsdrvctl upsd will shut down. Note that the UPS does
+ driver not shutdown at the same time as the sys-
tem it protects. The UPS shutdown is
UPS-1 ups.status:
delayed. By default the delay is 20 sec-
[OB LB]
onds. We will see in a later chapter how
to change this. (Line 77 if you're curious.)
offdelay = 20 x seconds
The delayed UPS shutdown command
seconds System shuts down may be from a shell script or a sys-
temd service unit but in all cases the
key element is the command upsdrvctl
UPS-1 shutdown.
UPS shuts down Figure 17 shows the shell script sup-
plied by NUT to be placed in a sys-
Figure 16: Delayed UPS shutdown. temd drop-in directory for scripts which
should be executed as late as possible dur-
ing a system shutdown. This script is used by openSUSE and Debian 11 and is placed in le /usr
/lib/systemd/system-shutdown/nutshutdown . systemd detects automatically that a script in
one of these drop-in directories needs to be executed. There is no need to enable the script.
70 #!/bin/sh
71 /usr/sbin/upsmon -K >/dev/null 2>&1 && /usr/sbin/upsdrvctl shutdown
Figure 17: openSUSE script for delayed UPS shutdown.
Page 14 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
We are now ready to tell the detailed story of how the server gets shut down when wall power fails,
and how it restarts when wall power returns.
1. Wall power on The system runs normally. In the attachment daemon the upsd status is
[ol]. No NOTIFY event.
2. Wall power fails The server remains operational running on the UPS battery. upsd polls
the UPS, and detects status change [ol]→[ob].
3. In the management daemon, upsmon polls upsd, receives [ob] and issues NOTIFY event
[onbatt]. As instructed by line 58, an [onbatt] message goes to syslog and to program
wall. The server is still operational running on the UPS battery.
Minutes go by...
5. upsmon polls upsd, receives [ob lb] and issues new NOTIFY event [lowbatt]. As instructed
by line 59 upsmon sends a [lowbatt] message to syslog and to program wall.
6. upsmon decides to command a system shutdown and generates NOTIFY event [shutdown].
It also sends command FSD to upsd to tell any secondaries that they must shut down. There
are no secondaries in this simple conguration.
7. upsmon uses command NUMATTACH7 to query the number of secondaries currently operational.
In this simple conguration, the reply is 1, there are no secondaries and the primary may
proceed to shut down.
11. We now enter the scenario described in gure 16. The operating system's shutdown process
takes over. During the system shutdown, the Bash script shown in gure 17 or equivalent
systemd service unit or some other equivalent runs the command upsdrvctl shutdown . This
tells the UPS that it is to shut down 20 seconds later.
12. The system powers down, hopefully before the 20 seconds have passed.
13. UPS shuts down 20 seconds have passed. With some UPS units, there is an audible
clunk. The UPS outlets are no longer powered. The absence of AC power to the protected
Page 15 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
system for a sucient time has the eect of resetting the BIOS options, and in particular the
option Restore power on AC return. This BIOS option will be needed to restart the box.
How long is a sucient time for the BIOS to reset? This depends very much on the box.
Some need more than 10 seconds. What if wall power returns before the sucient time
has elapsed? The UPS unit will wait until the time specied by the ondelay option in le
ups.conf. This timer, like the offdelay timer, starts from the moment the UPS receives the
upsdrvctl shutdown command. See line 78 in gure 18.
Minutes, hours, days go by...
14. Wall power returns Some time later, maybe much later, wall power returns. The UPS
reconnects it's outlets to send power to the protected system.
15. The system BIOS option Restore power on AC return has hopefully been selected and the
system powers up. The bootstrap process of the operating system begins.
16. The operating system starts the NUT daemons upsd and upsmon. Daemon upsd starts the
driver(s) and scans the UPS. The UPS status becomes [ol lb]. Daemon upsmon sends
8
command ATTACH to upsd to advise upsd that the primary is operational, i.e. the number of
attached systems is ≥ 1.
17. After some time, the battery charges above the battery.charge.low threshold and upsd
declares the status change [ol lb]→[ol]. We are now back in the same situation as state 1
above.
As we saw in gure 16, there is a danger that the system will take longer
than 20 seconds to shut down. If that were to happen, the UPS shutdown
would provoke a brutal system crash. To alleviate this problem, the next
chapter proposes an improved conguration le ups.conf.
Page 16 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Let's revisit this conguration le which declares your UPS units.
New line 77 increases from the default 20
72 # ups.conf, improved secs to 60 secs the time that passes between
73 [UPS-1] the upsdrvctl shutdown command and the
74 driver = usbhid-ups moment the UPS shuts itself down.
75 port = auto Line 78 increases the time that must pass
desc = "Example Mfg 1600"
76
between the upsdrvctl shutdown command
77 offdelay = 60
and the moment when the UPS will react to
78 ondelay = 70
the return of wall power and turn on the power
79 lowbatt = 33
to the system. Even if wall power returns ear-
Figure 18: Conguration le ups.conf, im- lier, the UPS will wait ondelay = 70 seconds
proved. before powering itself on. The default is 30
seconds.
The ondelay must be greater than the offdelay. See man ups.conf for more news about this
conguration le.
Additional line 79 sets the default value for battery.charge.low. Even if you use command
9
upsrw to set a value for battery.charge.low, usbhid-ups and some other drivers will restore the
default, so if you want a permanent change you must change the default. See also chapter 2.10.
What happens if power returns after the system shuts down but before the UPS delayed shutdown?
We pick up the story from state 6.
6. upsmon decides to command a system shutdown and generates NOTIFY event [shutdown].
It also sends command FSD to upsd to tell any secondaries that they must shut down. There
are no secondaries in this simple conguration.
7. upsmon uses command NUMATTACH to query the number of secondaries currently oerational.
In this simple conguration, the reply is 1, since there are no secondaries. The primary may
proceed to shut down.
11. We now enter the scenario described in gure 16. The operating system's shutdown process
takes over. During the system shutdown, the Bash script shown in gure 17 or equivalent
systemd service unit or some other equivalent runs the command upsdrvctl shutdown . This
tells the UPS that it is to shut down offdelay seconds later .
9 List needed
Page 17 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
12. The system powers down before offdelay seconds have passed.
13. Wall power returns before the UPS shuts down Less than offdelay seconds have
passed. The UPS continues it's shutdown process.
14. After offdelay seconds the UPS shuts down, disconnecting it's outlets. The beeping stops.
With some UPS units, there is an audible clunk.
15. After ondelay seconds the UPS turns itself on, and repowers it's outlets
16. The system BIOS option restore power on AC return has hopefully been selected and the
system powers up. The bootstrap process of the operating system begins.
Utility program upscmd is a command line program for sending commands directly to the UPS.
To see what commands your UPS will accept, type upscmd -l ups-name where ups-name is the
name of the UPS as declared in le ups.conf, line 32.
For example, to turn on the beeper, use command
upscmd -u nut-admin -p sekret UPS-1@localhost beeper.enable
where nut-admin is the user declared on line 40 and sekret is the l33t password declared on line 41
in le upsd.users.
Command upscmd can be dangerous. Make sure that le upsd.users can be read and written
by root only. See man upscmd for more detail.
Utility program upsrw is a command line program for changing the values of UPS variables. To see
which variables may be changed, type upsrw ups-name where ups-name is the name of the UPS
as declared in le ups.conf, line 32.
For example, at line 9 we saw that the battery.charge.low has been set to 50. We will change
this to something less conservative with command
upsrw -s battery.charge.low=33 -u nut-admin -p sekret UPS-1@localhost
where nut-admin is the user declared on line 40 and sekret is the password declared on line 41 in
le upsd.users. Now check that the value has been set with command
upsc UPS-1 battery.charge.low
which returns the value 33.
Once again, command upsrw can be dangerous. Make sure that le upsd.users can be read
and written by root only. See man upsrw for more detail.
Page 18 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Some drivers, for example usbhid-ups, reset battery.charge.low to the default value when
they start. To overcome this resistance, add the line lowbatt = 33 to the UPS denition in le
ups.conf as shown on line 79.
This chapter has described a basic conguration which is decient in several ways:
NUT messages are only available to those users who are constantly in front of text consoles
which display the output of the program wall. Systems with users of graphical interfaces
which do not display wall output will need stronger techniques.
Program wall has not been internationalised. It cannot display letters with accents or any
non-latin character.
Page 19 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
UPS-2: [LOWBATT]
UPS-2 upsdrvctl
+ driver
port
UPS-3: [NOCOMM]
47015 ups.status: [OB LB] 3493
UPS-4: [ONLINE]
upsdrvctl
UPS-3 + driver
ups.status: [ ]
47024 upsc
dual.svg
upsdrvctl upsrw
+ driver
UPS-4
ups.status: [OL]
upscom
47025
Six conguration les specify the operation of NUT in the server with multiple power supplies.
1. The NUT startup conguration: nut.conf. Since this le is not strictly a part of NUT, and
is common to all congurations, it is discussed separately in appendix A.
3. The upsd daemon access control; upsd.conf does not change, see chapter 2.2.
4. The upsd daemon user declarations: upsd.users do not change, see chapter 2.3.
6. The delayed UPS shutdown script. Since this le is common to all congurations, it is
discussed separately in appendix B.
We add additional sections to ups.conf to declare the additional UPS units but we need some way
of distinguishing them. Assuming the usbhid-ups driver, man usbhid-ups describes how this can
be done.
Page 20 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Driver usbhid-ups distinguishes multiple UPS units with some combination of the vendor,
product, serial and vendorid options that it provides. For other drivers, which do not provide
the ability to distinguish UPS units, or for UPS units which have no serial number, see the comment
by Charles Lepple in NUT issue #597 at https://github.com/networkupstools/nut/issues/597.
Let's assume that the UPS units used in this conguration are sophisticated products and
are capable of reporting their serial numbers. upsc UPS-1
You can check this with command
@localhost ups.serial . In lines 86, 92, 98 and 104 we use this information to distinguish UPS-1
with serial = 47014, UPS-2 with serial = 47015, etc.
See man ups.conf and man usbhid-ups.
This conguration le declares how upsmon is to handle NOTIFY events from the UPS units. For
10
good security, ensure that only users nut and root can read and write this le.
On lines 106-109
10 This is for Debian 11. See table 104 in appendix C for other user names.
Page 21 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
The UPS names UPS-1, UPS-2, etc. must correspond to those declared in ups.conf lines 81,
87. 93 and 99.
The power value 1 is the number of power supplies that each UPS feeds on this system.
primary means this system will shutdown last, allowing any secondaries time to shutdown
rst. Secondary systems will be discussed in chapter 5. There are no secondaries in this
conguration.
Line 110, MINSUPPLIES, declares that at least two power supplies must be operational, and that
if fewer are available, NUT must shut down the server. Figure 19 shows that currently two of
the four power supplies are operational. The [ob lb] of UPS-2, which would have caused a system
shutdown in the case of the simple server in chapter 2 is not sucient to provoke a system shutdown
in this case. UPS-3 has been disconnected and will be removed in order to paint the wall behind it.
(Have you ever worked for Big Business IT, or for Big Government IT?).
The remainder of upsmon.conf is the same as that for the simple server of chapter 2, gures
11-15.
The value of MINSUPPLIES is the key element in determining if a server with multiple power
supplies should shut down. When all the UPS units can be contacted, and when their ups.status
Page 22 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
values are known, then it is the count A of those that are active, that is without [lb], which is
determinant.
UPS-3: What is the value of A? The situation for those UPS units such as UPS-3 is
more delicate. If a UPS unit had been reporting the status [ol], then if communication is lost,
NUT assumes that the UPS is still operational. Command upsc UPS-3@localhost ups.status
will return the error message Error: Data stale, upsmon will raise the NOTIFY event [commbad]
and the sysadmin will receive the Communications lost message shown on line 54. However this
does not count as an [lb].
You can verify this yourself on a simple working conguration such as that of chapter 2 using
the Bash command shown on lines 111-114 in gure 22. Disconnecting the USB cable on a healthy
UPS does not cause a system shutdown.
However, as shown in gure 23, disconnecting the USB lead on a sick UPS causes a rapid system
shutdown. If a UPS unit had been reporting the status [ob], then if communication is lost, NUT
assumes that the UPS is about to reach status [ob lb] and calls for a immediate system shutdown.
So the value of A depends not only on the current situation, but also on how the system got
into that state.
The moral of our story is that NUT will play safe, but you must be very careful who has access
to your server room. We will see in later chapters that there are ways of reinforcing the feedback
to the sysadmin.
Page 23 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
This chapter has described a complex UPS conguration in isolation, but in practice such a
conguration would be just a part of a complete server room, and the use of NUT would have to be
integrated with the rest of the server room power management. The layered design of NUT makes
this integration possible.
11
A recent book for managers on disaster recovery discusses UPS units. On page 559 it says
We chose to have just one UPS do the paging ... We do it on low battery for one of the UPSes
that has a 15-minute run-time. Clearly they wanted a timed action, but the only way they could
get it was by running down a UPS until it reached [lb]. NUT is capable of doing a lot better, as
we will show in later chapters.
11 The Backup Book: Disaster Recovery from Desktop to Data Center by Dorian J. Cougias, E. L. Heiberger,
Karsten Koop, Schaser-Vartan Books, 2003, ISBN 0-9729039-0-9, 755 pages.
Page 24 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
We choose the latter since this introduces upssched, which will be needed later.
upsmon upssched
upsd NOTIFYCMD CMDSCRIPT
upsdrvctl port
+ driver
3493/tcp
UPS-1 (nut) upsc
ups.status: [OL]
upssched-cmd
upsrw ...
notify-send
upscom ...
workstation.svg
1. The NUT startup conguration: nut.conf. Since this le is not strictly a part of NUT, and
is common to all congurations, it is discussed separately in appendix A.
2. The upsd UPS declarations: The improved le ups.conf as given in chapter 2.7 does not
change.
3. The upsd daemon access control: File upsd.conf as given in chapter 2.2 does not change.
4. The upsd user declarations: File upsd.users as given in chapter 2.3 does not change.
8. The delayed UPS shutdown script. Since this le is common to all congurations, it is
discussed separately in appendix B.
Page 25 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
137 # upsmon.conf
138 MONITOR UPS-1@localhost 1 nut-admin sekret primary
139 MINSUPPLIES 1
Figure 25: Conguration le upsmon.conf for a workstation, part 1 of 5.
This conguration le declares how upsmon is to handle NOTIFY events. For good security,
12
ensure that only users nut and root can read and write this le.
Line 138 is the same as line 44 in the previous chapter.
On line 139, MINSUPPLIES sets the number of power supplies that must be receiving power to
keep this system running. Computers commonly have just one power supply, so the default value
of 1 is acceptable. See man upsmon.conf for more details.
Line 140, identical to line 45 declares the command to be used to shut down the server.
Line 141 says which program is to be invoked when upsmon detects a NOTIFY event agged as
EXEC. The directory/le /usr/sbin/upssched is for Debian 11. Sysadmins for other distributions
should check the directory used.
Line 142, POLLFREQ, declares that the upsmon daemon will poll upsd every 5 seconds.
Line 143, POLLFREQALERT, declares that the upsmon daemon will poll upsd every 5 seconds while
the UPS in on battery.
Line 144, HOSTSYNC will be used in primary-secondary13 cooperation, to be discussed in chapter
5.5. The default value is 15 seconds.
Line 145 species how long upsmon will allow a UPS to go missing before declaring it dead.
The default is 15 seconds.
Daemon upsmon requires a UPS to provide status information every few seconds as dened by
POLLFREQ and POLLFREQALERT. If the status fetch fails, the UPS is marked stale. If it stays stale
for more than DEADTIME seconds, the UPS is marked dead.
A dead UPS that was last known to be on battery [ob] is assumed to have changed to a low
battery condition [ob]→[ob lb]. This may force a shutdown. Disruptive, but the alternative is
12 This is for Debian 11. See table 104 in appendix C for other user names.
13 A secondary is a second, third, ... PC or workstation sharing the same UPS,
Page 26 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
barreling ahead into oblivion and crashing when you run out of power. See chapter 3.3 for more
discussion.
Lines 157-159 now carry the EXEC ag: this ag means that when the NOTIFY event occurs,
upsmon calls the program identied by the NOTIFYCMD on line 141.
Lines 160-166 do not change.
Page 27 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
The NOTIFY events detected by upsmon and agged as EXEC in upsmon.conf become events for
upssched when NOTIFYCMD points to upssched. The program upssched provides a richer set of
actions than upsmon.
The conguration le upssched.conf described here shows only a simple subset of what can be
done. We will see more later.
170 # upssched.conf
171 CMDSCRIPT /usr/bin/upssched-cmd
172 # PIPEFN LOCKFN suitable for Debian 11
173 PIPEFN /run/nut/upssched.pipe
174 LOCKFN /run/nut/upssched.lock
Figure 30: Conguration le upssched.conf for a Debian 11 workstation, Part 1.
On line 171 CMDSCRIPT points to a user script to be called for designated NOTIFY events. This
script will receive as argument a user chosen value. The specication /usr/bin/upssched-cmd is
for Debian 11. Sysadmins of other distributions should check the directory used.
Line 173 denes PIPEFN which is the le name of a socket used for communication between
upsmon and upssched. It is important that the directory be accessible to NUT software and
nothing else. I recommend that you use the same directory as is used for communication between
upsd and the drivers. Search for the directory which contains the le upsd.pid. You should see at
least one socket. See for example the footnote to section 1.3.1.
The value shown on line 173 is for the Debian 11 distribution which places upsd.pid in directory
/run/nut/ . As always, sysadmins for other distributions should check the directory used. You
should see an additional entry in the directory:
On line 174 the LOCKFN declaration is needed by daemon upsmon to avoid race conditions. The
directory should be the same as PIPEFN.
Line 176 introduces the very useful AT declaration provided by upssched.conf. This has the
form
Page 28 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
where
UPS-name can be the special value * to apply this handler to every possible value of UPS-
name. I strongly recommend that you do not use this wildcard, since in later chapters we
need distinct actions for distinct UPS's.
The command in this case is EXECUTE. In later chapters we will see other very useful com-
mands.
Line 176 says what is to be done by upssched for event [online]. The eld UPS-1@localhost
says that it applies to the UPS we are using, and the EXECUTE says that the user script specied by
CMDSCRIPT is to be called with argument online.
Lines 177 and 178 make similar declarations for NOTIFY events [onbatt] and [lowbatt].
When upssched was added to the NUT project, the user dened script was called upssched-cmd.
This is not the most elegant of names but if you use it, people in the NUT community will know
immediately what you mean. Ubuntu sysadmins sometimes use upssched-script which is better.
179 #!/bin/bash -u
180 # upssched-cmd
181 logger -i -t upssched-cmd Calling upssched-cmd $1
182 UPS="UPS-1"
183 STATUS=$( upsc $UPS ups.status )
184 CHARGE=$( upsc $UPS battery.charge )
185 CHMSG="[$STATUS]:$CHARGE%"
186 case $1 in
187 online) MSG="$UPS, $CHMSG - power supply has been restored." ;;
188 onbatt) MSG="$UPS, $CHMSG - power failure - save your work!" ;;
189 lowbatt) MSG="$UPS, $CHMSG - shutdown now!" ;;
190 *) logger -i -t upssched-cmd "Bad arg: \"$1\", $CHMSG"
191 exit 1 ;;
192 esac
193 logger -i -t upssched-cmd $MSG
194 notify-send-all "$MSG"
Figure 32: Conguration script upssched-cmd for a workstation.
Page 29 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Figure 32 shows a simple example of the script. Since NUT runs on a wide range of operating
systems and distributions, with dierent default scripting languages, it is wise to declare as on line
179 which scripting language is used.
Logging all calls to this script helps sysadmins to discover what went wrong after the catastrophic
failures which in theory should never occur, but which in practice do. Line 181 logs all calls to this
script.
Lines 183-185 prepare a Bash variable CHMSG which gives the current UPS status and battery
charge. This is to be included in messages, so we get a clearer idea of what is happening.
On line 186 the value of the Bash variable $1 is one of the EXECUTE tags dened on lines 176-178.
Lines 187-189 dene, for each possible NOTIFY event that upsmon passes on to upssched, a
message to be logged and put in front of users. Accented letters and non latin characters are
allowed.
Line 193 logs the upssched action, and line 194 calls program notify-send-all to put the message
in front of the users. For details of notify-send-all, see appendix D, Using notify-send. See also
notify-send --help. There is no man page.
It is important that script upssched-cmd be accessible to NUT software and nothing else. For
example the following restrictive ownership and permissions seen on a Debian 11 site:
Page 30 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
We are now ready to tell the detailed story of how the workstation gets shut down when wall power
fails, and how it restarts when wall power returns.
1. Wall power on The system runs normally. upsd status is [ol]. No NOTIFY event.
2. Wall power fails The server remains operational running on the UPS battery. upsd polls
the UPS, and detects status change [ol]→[ob].
3. upsmon polls upsd, receives status [ob] and issues NOTIFY event [onbatt]. As instructed
by line 158 an [onbatt] message goes to syslog, to program wall and to upssched. The server
is still operational, running on the UPS battery.
4. upssched ignores the message it receives and follows the instruction on line 177 to call the
user script upssched-cmd with parameter onbatt.
$1 = onbatt and on line 188 sets
5. User script upssched-cmd sees that Bash variable $MSG to
UPS-1, [OB DISCHRG]:99% - power failure - save your work!
6. On line 193, the message is logged, and on line 194 program notify-send-all noties the users.
Minutes go by...
8. upsmon polls upsd, receives status [ob lb] and issues new NOTIFY event [lowbatt]. As
instructed by line 159 upsmon sends a [lowbatt] message to syslog, to program wall and
to upssched.
The following upssched actions may not occur if the system shutdown is rapid.
9. upssched ignores the message it receives and follows the instruction on line 178 to call the
user script upssched-cmd with parameter lowbatt.
$1 = lowbatt and on line 189 sets Bash variable $MSG to
10. User script upssched-cmd sees that
UPS-1, [OB DISCHRG LB]:12% - shutdown now!
11. On line 193, the message is logged, and on line 194 program notify-send noties the users.
The shutdown story now continues as for the simple server in state 6.
Page 31 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
upsmon
upssched
upsd primary
CMDSCRIPT
NOTIFYCMD
upsdrvctl port
+ driver 3493/tcp upsc
(nut)
ups.status: [OL]
upsrw upssched-cmd
UPS-1 ...
upscom notify-send
Primary workstation ...
The secondary
upsmon
secondary upssched
workstations take
power from the NOTIFYCMD CMDSCRIPT
Figure 33: Secondary workstations take power from same UPS as primary.
In this conguration two or more workstations are powered by the same UPS unit. Only one,
the primary, has a control lead to the UPS. The other(s) do not have control leads to the UPS
and are known as secondaries.
Figure 33 shows the arrangement. The NUT conguration for the primary workstation is iden-
tical to that of chapter 4.
Five conguration les specify the operation of NUT in the secondary workstation.
1. The NUT startup conguration: nut.conf. Since there is no control lead to the UPS, there is
no need for upsd or a driver in the secondary. In nut.conf declare MODE=netclient since only
upsmon needs to be started. You will probably need to review your distribution's start-up
scripts to achieve this. If upsd is started but without any UPS specied, it usually does no
harm. See also appendix A.
5. The delayed UPS shutdown script. Since this le is common to all congurations, it is
discussed separately in appendix B.
Page 32 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
This conguration le declares how upsmon in the secondary is to handle NOTIFY events
14
coming from the primary. For good security, ensure that only users nut and root can read and
write this le.
On line 198
The UPS name UPS-1 must correspond to that declared in the primary ups.conf, line 32.
The fully qualied name UPS@host includes the network name of the primary workstation, in
this case primary.
The power value 1 is the number of power supplies that this UPS feeds on this system.
secondary means this system will shutdown rst, before the primary.
On line 199, MINSUPPLIES sets the number of power supplies that must be receiving power to
keep this system running. Normal computers have just one power supply, so the default value of 1
is acceptable. See chapter 3, and man upsmon.conf in the NUT documentation for more details.
Line 200, identical to line 45, declares the command to be used to shut down the secondary.
Line 201 says which program is to be invoked when upsmon detects a NOTIFY event agged
as EXEC. Debian administrators would probably specify /sbin/upssched .
Line 202, POLLFREQ, declares that the upsmon daemon will poll upsd in the primary every 5
seconds.
14 I've seen user upsd rather than nut in distributions. See table 104 in appendix C
Page 33 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Line 203, POLLFREQALERT, declares that the upsmon daemon will poll upsd in the primary every
5 seconds while the UPS in on battery.
Line 204, HOSTSYNC15 will be used as a safeguard for the primary-secondary shutdown sequence,
preventing the overall shutdown being blocked by an unresponsive secondary, as discussed in chapter
5.4. The default value is 15 seconds.
Line 205 species how long the secondary upsmon will allow a UPS to go missing before declaring
it dead. The default is 15 seconds.
Daemon upsmon requires a UPS to provide status information every few seconds as dened by
POLLFREQ and POLLFREQALERT. If the status fetch fails, the UPS is marked stale. If it stays stale
for more than DEADTIME seconds, the UPS is marked dead.
A dead UPS that was last known to be on battery [ob] is assumed to have changed to a low
battery condition [ob]→[ob lb]. This may force a shutdown. Disruptive, but the alternative is
barreling ahead into oblivion and crashing when you run out of power. See chapter 3.3 for more
discussion.
The message texts on lines 207-216 in gure 36 do not change from those in the primary.
15 The name HOSTSYNC is misleading. It would be clearer if the name were say MAXWAITSCNDRY.
Page 34 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Lines 217-219, which do not change from those in the primary, carry the EXEC ag: when the
NOTIFY event occurs, secondary upsmon calls the program identied by the NOTIFYCMD on line
201.
Lines 220-226 do not change from those in the primary.
The NOTIFY events detected by secondary upsmon and agged as EXEC in upsmon.conf become
events for upssched when NOTIFYCMD points to upssched. The program upssched provides a richer
set of actions than upsmon.
As with the primary in chapter 4, the conguration le upssched.conf described here shows
only a simple subset of what can be done. We will see more later.
On line 231, CMDSCRIPT points to a user script to be called for designated NOTIFY events. This
script will receive as argument a user chosen value.
Line 232 denes PIPEFN which is the le name of a socket used for communication between
upsmon and upssched. The value shown is for the Debian 11 distribution. For a detailed discussion
of PIPEFN, see chapter 4.2, line 173.
Daemon upsmon requires the LOCKFN declaration on line 233 to avoid race conditions. The
directory should be the same as PIPEFN.
Line 235 says what upssched should do for NOTIFY event [online]. The UPS-1@primary
says that it applies to the UPS controlled by the primary, and the EXECUTE says that the user script
specied by CMDSCRIPT is to be called with argument online.
Lines 236 and 237 make similar declarations for NOTIFY events [onbatt] and [lowbatt].
Page 35 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
When upssched was added to the NUT project, the user dened script was called upssched-cmd.
This is not the most elegant of names but if you use it, people in the NUT community will know
immediately what you mean.
It is important that script upssched-cmd be accessible to NUT software and nothing else.
238 #!/bin/bash -u
239 # upssched-cmd --secondary --
240 logger -i -t upssched-cmd Calling upssched-cmd $1
241 case $1 in
242 online) MSG="UPS-1 - power supply had been restored." ;;
243 onbatt) MSG="UPS-1 - power failure - save your work!" ;;
244 lowbatt) MSG="UPS-1 - shutdown now!" ;;
245 *) logger -i -t upssched-cmd "Bad arg: \"$1\""
246 exit 1 ;;
247 esac
248 logger -i -t upssched-cmd $MSG
249 notify-send-all "$MSG"
Figure 40: Conguration script upssched-cmd for a secondary.
Since NUT runs on a wide rage of operating systems and distributions, with dierent default
scripting languages, it is wise to declare as on line 238 which scripting language is used.
Logging all calls to this script helps sysadmins to discover what went wrong after the catastrophic
failures which in theory should never occur, but which in practice sometimes do. Line 240 logs all
calls to this script.
On line 241 the value of the Bash variable $1 is one of the EXECUTE tags dened on lines 235-237.
Lines 242-244 dene, for each possible NOTIFY event that upsmon passes on to upssched, a
message to be logged and put in front of users of the secondary. Accented letters and non latin
characters are allowed.
Line 248 logs the upssched action, and line 249 calls program notify-send-all to put the message
in front of the secondary users. For details of notify-send-all, see appendix D, Using notify-send.
See also notify-send --help. There is no man page.
Page 36 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
The daemon upsd maintains a count of the number of systems protected by a UPS unit. When a
primary or secondary is brought up, it sends command ATTACH to upsd which increases the count
by 1. When a system is shut down, it sends command DETACH to upsd and the count decreases by
1. In the conguration shown in gure 33 on page 32, during normal operation the count is 4. The
primary upsmon instance polls the number of protected systems using command NUMATTACH. During
a complete shutdown, the primary waits until the NUMATTACH value drops to 1 before shutting down
itself.
However there is a safeguard against excessive waiting for a non-responsive secondary provided
by the HOSTSYNC value declared on line 204.
5.5 Magic: How does the primary shut down the secondaries?
The primary commands the system shutdowns which may be due to an [lb], a timeout (chapter
7), or a sysadmin command. When there are secondaries to be shutdown as well, then the primary
expects them to shut down rst. But how do the secondaries know that they are to shut down?
When the primary makes the shutdown decision, it places a status symbol [fsd] in variable
ups.status in the abstract image of the UPS maintained by it's upsd. The secondary upsmon
daemons poll upsd every POLLFREQ seconds as delared on line 142, and when they see the [fsd]
symbol, knowing that they are a secondary, they shut down immediately, sending command DETACH
to upsd. The primary waits for the secondaries to react and shutdown by polling the NUMATTACH
value. The maximum waiting period is specied by HOSTSYNC16 on line 144. When NUMATTACH = 1,
or after the HOSTSYNC time has elapsed, the primary will shut down, even if there is a secondary
which has not yet completed it's shutdown. If you meet this problem, you may have to increase
the value of HOSTSYNC.
This HOSTSYNC value is also used to keep secondary systems from getting stuck if the primary
fails to respond in time. After a UPS becomes critical, e.g. status [ob lb], the secondary will wait
up to HOSTSYNC seconds for the primary to set the [fsd] ag. If that timer expires, the secondary
will assume that the primary is broken and will shut down anyway. See also man upsmon.conf.
16 The name HOSTSYNC is misleading. It would be clearer if the name were say MAXWAITSCNDRY.
Page 37 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
upsmon upssched
UPS-1 upsdrvctl upsd
NOTIFYCMD CMDSCRIPT
+ driver
port
ups.status: [OL]
3493/tcp
(nut) upsc
upsdrvctl upssched-cmd
10m + driver ups.status:
upsrw ...
How does it work? NUT program upssched runs permanently as a daemon managing an
11 minute timer. If this timer expires, NUT is broken, and upssched calls user script upssched-cmd
which issues wall messages, e-mails, notications, etc. Meanwhile a dummy (software) UPS is
programmed to generate a status change every 10 minutes. This works it's way through the NUT
daemons and protocols to reach user script upssched-cmd which then restarts the 11 minute timer.
As long as the 10 minute status changes are fully and correctly handled by NUT, the warning
message does not go out, but if something breaks, the 11 minute timer elapses.
Nine conguration les specify the operation of NUT in the workstation.
2. The upsd UPS declarations: ups.conf will be extended to include the heartbeat. See chapter
6.1.
3. New conguration le heartbeat.conf denes the dummy UPS which provides the heartbeat.
See chapter 6.2.
4. The upsd daemon access control: File upsd.conf as given in chapter 2.2 stays the same.
5. The upsd user declarations: File upsd.users as given in chapter 2.3 does not change.
Page 38 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
9. The delayed UPS shutdown script. Since this le is common to all congurations, it is
discussed separately in appendix B.
We extend this conguration le with an additional section to declare a new UPS unit.
258 [heartbeat]
259 driver = dummy-ups
260 port = heartbeat.conf
261 mode = dummy-loop
262 desc = "Watch over NUT"
Figure 42: Conguration le ups.conf for workstation with heartbeat.
Page 39 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Heartbeat denitions are not provided by NUT, you have to create them yourself. Create the
17
new le heartbeat.conf in the same directory as ups.conf. For security, only users nut and
root should have write access to this le.
The dummy UPS will cycle continuously through this script.
Lines 264 and 266 ip the ups.status value between [ol] and [ob].
Lines 265 and 267 place a 5 minute time interval between each status change. Remember that
2 × 300sec = 10min, the heartbeat period.
The conguration le upsmon.conf is the same as for the workstation in chapter 4, except for an
additional MONITOR declaration and a simpler NOTIFYFLAG to avoid ooding the logs.
268 # upsmon.conf
269 MONITOR UPS-1@localhost 1 nut-admin sekret primary
270 MONITOR heartbeat@localhost 0 nut-admin sekret primary
271 MINSUPPLIES 1
Figure 44: Conguration le upsmon.conf for a workstation with heartbeat.
The change is the addition of line 270 which declares that upsmon is to monitor the heartbeat.
Note that the power value is 0 because the heartbeat does not supply power to the workstation.
To avoid ooding your logs, remove the ags SYSLOG and WALL for the [online] and [onbatt]
NOTIFY events:
All the other declarations remain unchanged. This inability of upsmon to provide dierent
behaviours for dierent UPS's is a weakness, and is why we prefer to make use of upssched which
supports precise selection of the UPS in it's AT specication.
17 Some distributions have been known to use upsd. See table 104 in appendix C for other user names.
Page 40 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
274 # Restart timer which completes only if the dummy-ups heart beat
275 # has stopped. See timer values in heartbeat.conf
276 AT ONBATT heartbeat@localhost CANCEL-TIMER heartbeat-failure-timer
277 AT ONBATT heartbeat@localhost START-TIMER heartbeat-failure-timer 660
Figure 45: Conguration le upssched.conf for a workstation with heartbeat.
Remember that the very useful AT declaration provided by upssched.conf has the form
On line 276, when upssched receives an [onbatt] it executes the command which is CANCEL
-TIMER heartbeat-failure-timer. This kills the timer. upssched does not call the user script.
Immediately afterwards, on line 277, and for the same [onbatt] event, upssched executes the
command START-TIMER heartbeat-failure-timer 660 which restarts the heartbeat-failure
-timer which will run for 660 sec, i.e. 11 minutes. If the timer completes, upssched will call the
user script upssched-cmd with parameter heartbeat-failure-timer.
Make sure that there are no entries such as
which would be activated by an [online] or [onbatt] from the heartbeat UPS. Replace the "*"
with the full address of the UPS unit, e.g. UPS-1@localhost.
Page 41 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
280 #!/bin/bash -u
281 # upssched-cmd for workstation with heartbeat
282 logger -i -t upssched-cmd Calling upssched-cmd $1
283
288 UPS="UPS-1"
289 STATUS=$( upsc $UPS ups.status )
290 CHARGE=$( upsc $UPS battery.charge )
291 CHMSG="[$STATUS]:$CHARGE%"
292
293 case $1 in
294 (online) MSG="$UPS, $CHMSG - power supply had been restored." ;;
295 (onbatt) MSG="$UPS, $CHMSG - power failure - save your work!" ;;
296 (lowbatt) MSG="$UPS, $CHMSG - shutdown now!" ;;
297 (heartbeat-failure-timer)
298 MSG="NUT heart beat fails. $CHMSG" ;;
299 # Email to sysadmin
300 MSG1="Hello, upssched-cmd reports NUT heartbeat has failed."
301 MSG2="Current status: $CHMSG \n\n$0 $1"
302 MSG3="\n\n$( ps -elf | grep -E 'ups[dms]|nut' )"
303 echo -e "$MSG1 $MSG2 $MSG3" | /bin/mail -r "$EMAIL_FROM" \
304 -s "NUT heart beat fails. Currently $CHMSG" "$EMAIL_TO"
305 (*) logger -i -t upssched-cmd "Bad arg: \"$1\", $CHMSG"
306 exit 1 ;;
307 esac
308 logger -i -t upssched-cmd $MSG
309 notify-send-all "$MSG"
Figure 46: Conguration script upssched-cmd including heartbeat.
Lines 300-302 compose a message to the sysadmin which is sent on line 303. The message
includes the current state of those NUT kernel processes which are operational.
A true sysadmin should not be satised with just the heartbeat. What if the heartbeat dies
silently? We need a further independent check that the normally silent heartbeat is doing it's job.
Page 42 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
We want to check that the heartbeat is in progress. To do so we make use of the permanent presence
of a upssched process. Consider the following Bash script:
310 #!/bin/bash -u
311 NUT=nut # openSUSE: "upsd", Debian: "nut"
312 MSGERR="${HOSTNAME:-mybox}: NUT heartbeat fails"
313 MSGOK="${HOSTNAME:-mybox}: NUT heartbeat OK"
314 # Are the heartbeat timers keeping upssched busy?
315 ps -elf | grep "upssched UPS heartbeat" | grep $NUT > /dev/null
316 if [[ $? -ne 0 ]]
317 then wall $MSGERR # Tell sysadmin the bad news
318 echo -e "$MSGERR" | /bin/mail\
319 -r [email protected]\
320 -s "$MSGERR" [email protected]
321 notify-send-all "$MSGERR"
322 sleep 1s
323 else # Tell sysadmin that all is well
324 echo -e "$MSGOK" | /bin/mail\
325 -r [email protected]\
326 -s "$MSGOK" [email protected]
327 notify-send-all "$MSGOK"
328 fi
Figure 47: Heartbeat watcher.
Line 311 species who is the owner of the upssched process. See table 104 for a list of possible
owners.
Line 315 will succeed if there is a process managing the heartbeat.
Lines 317, 318 and 321 show three dierent ways of telling the sysadmin that all is not well with
the heartbeat process. Pick which one(s) suit you. See appendix D for a discussion of notify-send-all.
The Bash script requires something like line 329 in /etc/crontab:
In this example, line 329 declares that the Bash script is to be run at 08:01 hrs every day as
user nut. OpenSUSE might use upsd. See table 104 for a list of possible users. See also man
crontab(5).
This chapter has introduced the timers provided by upssched. We will see in the next chapter
that much more can be done with them.
Page 43 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
upsmon upssched
UPS-1 upsdrvctl upsd NOTIFYCMD CMDSCRIPT
+ driver
port
ups.status: [OL CHRG]
3493/tcp
upsdrvctl (nut) upsc upssched-cmd
+ driver
10m ups.status: upsrw shutdown-timer:
[OL] / [OB] / [OL] ...
upscom 2, 1, 0, shutdown
heartbeat.conf bad.svg
Nine conguration les specify the operation of NUT in a workstation with timed shutdown. In
this chapter we will give these conguration les in full to avoid excessive page turning.
1. The NUT startup conguration: nut.conf. Since this le is not strictly a part of NUT, and
is common to all congurations, it is discussed separately in appendix A.
3. Conguration le heartbeat.conf which denes the dummy UPS providing the heartbeat.
See chapter 7.2.
Page 44 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
9. The delayed UPS shutdown script. Since this le is common to all congurations, it is
discussed separately in appendix B.
This conguration le includes support for the heartbeat, and is unchanged from that discussed
in the previous chapter. See 6.1
Lines 331 and 338 begin a UPS-specic section, and name the UPS unit that upsd will manage.
The following lines provides details for each UPS. There will as many sections as there are UPS
units. Make sure this name matches the name in upsmon.conf and in upssched-cmd, which we will
meet later.
Lines 332 and 339 specify the driver that upsd will use. For the full list of drivers, see the
Hardware Compatibility list and the required drivers at http://www.networkupstools.org/stable-
hcl.html.
Lines 333 and 340 depend on the driver. For the usbhid-ups driver the value is always auto.
For the dummy-ups driver, the value is the address of the le which species the dummy UPS
behaviour. This le should be in the same directory as ups.conf. For other drivers, see the man
page for that driver.
Line 341 is needed by NUT 2.8.0 to specify that the program of work described by the le
heartbeat.conf is to be repeated endlessly. See man dummy-ups.
Lines 334 and 342 provide descriptive texts for the UPS.
For a detailed discussion of offdelay ondelay on lines 335-336, see chapter 2.7.
and
Additional line 337 sets the default value for battery.charge.low. Even if you use command
18
upsrw to set a value for battery.charge.low, usbhid-ups and some other drivers will restore the
default, so if you want a permanent change you must change the default. See also chapter 2.10.
18 List needed
Page 45 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Figure 51: Conguration le upsd.conf Line 350 declares that upsd is to listen on it's
for workstation with timed shutdown. prefered port for trac from the localhost. It is
possible to replace 127.0.0.1 by 0.0.0.0 which says
listen for trac from all sources and use your rewall to lter trac to port 3493.
If you do not have IPv6, remove or comment out line 351.
19 This is for Debian 11. See table 104 in appendix C for other user names.
Page 46 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
The previous chapters have repeatedly modied upsmon.conf so we provide here a complete de-
scription of the le, including all previous modications.
356 # upsmon.conf
357 MONITOR UPS-1@localhost 1 nut-admin sekret primary
358 MONITOR heartbeat@localhost 0 nut-admin sekret primary
359 MINSUPPLIES 1
Figure 53: Conguration le upsmon.conf with timed shutdown, part 1 of 5.
This conguration le declares how upsmon is to handle NOTIFY events. For good security,
21
ensure that only users nut and root can read and write this le.
On line 357
The UPS name UPS-1 must correspond to that declared in ups.conf line 331.
The power value 1 is the number of power supplies that this UPS feeds on this system.
20 This is for Debian 11. See table 104 in appendix C for other user names.
21 This is for Debian 11. See table 104 in appendix C for other user names.
Page 47 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
primary means this system will shutdown last, allowing any secondaries time to shutdown
rst. There are no secondaries in this simple conguration.
Line 360 declares the command to be used to shut down the server. A second instance of the
upsmon daemon running as root will execute this command. Multiple commands are possible,
for example SHUTDOWNCMD "logger -t upsmon.conf \"SHUTDOWNCMD calling /sbin/shutdown
to shut down system\" ; /sbin/shutdown -h +0" will also log the action of SHUTDOWNCMD. Note
that internal " have to be escaped. Note also that this command will be used in any call to upsmon
-c fsd. See line 429.
Line 361 says which program is to be invoked when upsmon detects a NOTIFY event agged
as EXEC. The example shown is for Debian 11, sysadmins for other distributions should check the
directory used.
Line 362, POLLFREQ, declares that the upsmon daemon will poll upsd every 5 seconds.
Line 363, POLLFREQALERT, declares that the upsmon daemon will poll upsd every 5 seconds while
the UPS in on battery.
Line 364, DEADTIME species how long upsmon will allow a UPS to go missing before declaring
it dead. The default is 15 seconds.
Daemon upsmon requires a UPS to provide status information every few seconds as dened by
POLLFREQ and POLLFREQALERT. If the status fetch fails, the UPS is marked stale. If it stays stale
for more than DEADTIME seconds, the UPS is marked dead.
A dead UPS that was last known to be on battery [ob] is assumed to have changed to a low
battery condition [ob]→[ob lb]. This may force a shutdown. Disruptive, but the alternative is
barreling ahead into oblivion and crashing when you run out of power. See chapter 3.3 for more
discussion.
Line 365, POWERDOWNFLAG declares a le created by upsmon when running in primary mode
when the UPS needs to be powered o. It will be used in more complex congurations. See man
upsmon.conf for details.
Page 48 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Lines 366-375 assign a text message to each NOTIFY event. Within each message, the marker %s
is replaced by the name of the UPS which has produced this event. upsmon passes this message to
program wall to notify the system administrator of the event. You can change the default messages
NOTIFYMSG event "message " where %s is replaced with
to something else if you like. The format is
the identier of the UPS in question. Note that program wall has not been internationalized and
does not support accented letters or non latin characters. When the corresponding NOTIFYFLAG
contains the symbol EXEC, upsmon also passes the message to the program specied by NOTIFYCMD
on line 361.
Lines 376-385 declare what is to be done at each NOTIFY event. The declarations, known as
ags are shown in table 14. You may specify one, two or three ags for each event, in the form
FLAG[+FLAG]*, however IGNORE must always be alone.
Lines 376-377 carry only the EXEC ag: Since the heartbeat induces a lot of [online] and
[onbatt] trac, the SYSLOG option would ood the log and WALL would put far too many useless
messages in xterm windows. When the NOTIFY event occurs, EXEC declares that upsmon should
call the program identied by the NOTIFYCMD on line 361.
Note that if you have multiple UPS's, the same actions are to be performed for a given NOTIFY
event for all the UPS's. Clearly this is not good news.
Page 49 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
When a UPS says that it needs to have its battery replaced, upsmon will generate a [replbatt]
NOTIFY event. Line 386 say that this happens every RBWARNTIME = 43200 seconds (12 hours).
Line 387: Daemon upsmon will trigger a [nocomm] NOTIFY event after NOCOMMWARNTIME
seconds if it can't reach any of the UPS entries in conguration le upsmon.conf. It keeps warning
you until the situation is xed.
Line 388: When running in primary mode, upsmon waits this long after sending the [shutdown]
NOTIFY event to warn the users. After the timer elapses, it then runs your SHUTDOWNCMD as
specied on line 360. If you need to let your users do something in between those events, increase
this number. Don't make this too big, even though the battery still has charge. Alternatively, you
can set this very low so you don't wait around when it's time to shut down.
For lots and lots of details, see man upsmon.conf. See also the le config-notes.txt in the
distribution.
The NOTIFY events detected by upsmon and agged as EXEC in upsmon.conf become events for
upssched when NOTIFYCMD points to upssched. The program upssched provides a richer set of
actions than upsmon, especially the management of timers.
On line 390 CMDSCRIPT points to a user script to be called for designated NOTIFY events. The
value shown is for Debian 11. Ubuntu sysadmins might see /usr/local/bin/upssched-script.
This script will receive as argument a user chosen timer name.
Line 391 denes PIPEFN which is the le name of a socket used for communication between
upsmon and upssched. It is important that the directory be accessible to NUT software and
nothing else. I recommend that you use the same directory as is used for communication between
upsd and the drivers. Search for the directory which contains the le upsd.pid. You should see at
least one socket. See for example the footnote to section 1.3.1.
The value shown on line 391 is for the Debian 11 distribution which places upsd.pid in directory
/run/nut/ . As always, sysadmins for other distributions should check the directory used. You
should see an additional entry in the directory:
Page 50 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Daemon upsmon requires the LOCKFN declaration on line 392 to avoid race conditions. The
directory should be the same as PIPEFN.
Line 394 introduces the very useful AT declaration provided by upssched.conf. This has the
form
where
UPS-name can be the special value * to apply this handler to every possible value of UPS-
name. We strongly recommend that you do not use this wildcard, since we need distinct
actions for distinct UPS's.
Line 394 says what is to be done by upssched for event [onbatt]. The eld UPS-1@localhost
says that it applies to the UPS we are using, and the START-TIMER says that upssched is to create
and manage a timer called two-minute-warning-timer which runs for 5 seconds. When this
timer completes, upssched calls the user script specied by CMDSCRIPT with argument two-minute
-warning-timer.
Lines 395 and 396 do the same thing for the 65 second timer one-minute-warning-timer and
the 125 second timer shutdown-timer.
Page 51 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Line 398 says what is to be done by upssched for event [online]. The eld UPS-1@localhost
says that it applies to the UPS we are using, and the CANCEL-TIMER says that upssched must cancel
the timer two-minute-warning-timer. The user script is not called.
Lines 399 and 400 do the same thing for the 65 second timer one-minute-warning-timer
and the 125 second timer shutdown-timer.
Line 401 command EXECUTE says that upssched is to call the user script immediately with the
argument ups-back-on-line.
On line 403, when upssched receives an [onbatt] it executes the command which is CANCEL
-TIMER heartbeat-failure-timer. This kills the timer. upssched does not call the user script.
Immediately afterwards, on line 404, and for the same [onbatt] event, upssched executes the
command START-TIMER heartbeat-failure-timer 660 which restarts the heartbeat-failure
-timer which will run for 660 sec, i.e. 11 minutes. If the timer completes, upssched will call the
user script upssched-cmd with parameter heartbeat-failure-timer.
405 #!/bin/bash -u
406 # upssched-cmd Workstation with heartbeat and timed shutdown
407 logger -i -t upssched-cmd Calling upssched-cmd $1
411 UPS="UPS-1"
412 STATUS=$( upsc $UPS ups.status )
413 CHARGE=$( upsc $UPS battery.charge )
414 CHMSG="[$STATUS]:$CHARGE%"
Figure 60: Conguration script upssched-cmd for timed shutdown, 1 of 2.
The user script upssched-cmd, the example is in Bash, manages the completion of the timers
two-minute-warning-timer, one-minute-warning-timer, shutdown-timer, ups-back-on-line
and heartbeat-failure-timer. Here is an complete example of what can be done. You will
probably need to modify this for your own use. Note that this script could be written in the
language of your choice, as long as the resulting program is able to receive the timer names as a
parameter, send e-mails and log and notify the users of messages. Bash has the advantage of being
widely available and is understood by many sysadmins.
On lines 409 and 410, change the e-mail addresses to something that works for you.
Lines 411-414 prepare a Bash variable CHMSG which gives the current UPS status and battery
charge. This is to be included in messages, so we get a clearer idea of what is happening.
Page 52 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
415 case $1 in
416 (heartbeat-failure-timer)
417 MSG="NUT heart beat fails. $CHMSG" ;;
418 MSG1="Hello, upssched-cmd reports NUT heartbeat has failed."
419 MSG2="Current status: $CHMSG \n\n$0 $1"
420 MSG3="\n\n$( ps -elf | grep -E 'ups[dms]|nut' )"
421 echo -e "$MSG1 $MSG2 $MSG3" | /bin/mail -r "$EMAIL_FROM" \
422 -s "NUT heart beat fails. Currently $CHMSG" "$EMAIL_TO" ;;
423 (two-minute-warning-timer)
424 MSG="Possible shutdown in 2 minutes. Save your work! $CHMSG" ;;
425 (one-minute-warning-timer)
426 MSG="Probable shutdown in 1 minute. Save your work! $CHMSG" ;;
427 (shutdown-timer)
428 MSG="Power failure shutdown: Calling upsmon -c fsd, $CHMSG"
429 /usr/sbin/upsmon -c fsd ;;
430 (ups-back-on-line)
431 MSG="Power back, shutdown cancelled. $CHMSG" ;;
432 (*) logger -i -t upssched-cmd "Bad arg: \"$1\", $CHMSG"
433 exit 1 ;;
434 esac
435 logger -i -t upssched-cmd $MSG
436 notify-send-all "$MSG"
Figure 61: Conguration script upssched-cmd for timed shutdown, 2 of 2.
Lines 416-422 introduce the heartbeat-failure-timer case into the case statement. Line 417
species a message to be logged with the current UPS status as dened on lines 411-414.
Lines 418-420 compose a message to the sysadmin which is sent on line 421. The message
includes the current state of those NUT kernel processes which are operational.
The cases at lines 423 and 425 specify warnings to be notied to the users when the two-minute
-warning-timer and one-minute-warning-timer complete.
Beginning at line 427 we prepare a message which the user may not see, since we call for an
immediate shutdown. The UPS may well be almost fully charged, but the shutdown is now, leaving
enough charge for further shutdowns in the near future.
Note on line 429 that we use upsmon to shut down the system. This automatically takes into
account any secondary systems which need to be shut down as well. The command upsmon -c fsd
will call the command specied by the SHUTDOWNCMD declaration on line 360.
Line 430 prepares a message that notify-send-all will put in front of the users to tell them to
get back to work since wall power has returned. See appendix D for a discussion of notify-send-all.
Page 53 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
We now tell the detailed story of how the workstation gets shut down when wall power fails, and
how it restarts when wall power returns.
1. Wall power on The system runs normally. upsd status is [ol]. No NOTIFY event.
2. Wall power fails The workstation remains operational running on the UPS battery. upsd
polls the UPS, and detects status change [ol]→[ob].
3. upsmon polls upsd, receives status [ob] and issues NOTIFY event [onbatt]. As instructed
by line 377 upsmon calls upssched, specied by NOTIFYCMD on line 361. Note that there is no
wall message and no logging by upsmon.
4. upssched matches the NOTIFY event [ONBATT] and the UPS name UPS-1@localhost with
AT specications on lines 394-396. Three timers start:
the three two-minute-warning-timer,
one-minute-warning-timer and shutdown-timer, managed in memory by upssched.
5 seconds go by...
5. two-minute-warning-timer completes, and upssched calls the user script upssched-cmd spec-
ied by CMDSCRIPT on line 390 with the timer name as argument. In the script, this matches
the case on line 423 which denes a suitable warning message in Bash variable MSG. Line 435
logs this message and line 436 puts it in front of the users. The workstation continues to
operate on battery power.
60 seconds go by...
6. one-minute-warning-timer completes, and upssched calls the user script upssched-cmd with
the timer name as argument. In the script, this matches the case on line 425 which denes a
stronger warning message in Bash variable MSG. Line 435 logs this message and line 436 puts
it in front of the users. The workstation continues to operate on battery power.
60 seconds go by...
7. shutdown-timer completes, and upssched calls the user script upssched-cmd with the timer
name as argument. In the script, this matches the case on line 427 which denes an ultimate
warning message in Bash variable MSG, and then calls upsmon for a system shutdown. Line
435 logs message MSG and line 436 puts it in front of the users. The workstation continues to
operate on battery power during the shutdown. If wall power returns, it is now too late to
call o the shutdown procedure.
Page 54 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
12. We now enter the scenario described in gure 16. The operating system's shutdown process
takes over. During the system shutdown, the Bash script shown in gure 17 or equivalent
systemd service unit or some other equivalent runs the command upsdrvctl shutdown . This
tells the UPS that it is to shut down offdelay seconds later as specied on line 335.
13. The system powers down, hopefully before the offdelay seconds have passed.
14. UPS shuts down offdelay seconds have passed. With some UPS units, there is an
audible clunk. The UPS outlets are no longer powered.
15. Wall power returns Some time later, maybe much later, wall power returns. The UPS
reconnects it's outlets to send power to the protected system.
16. The system BIOS option restore power on AC return has hopefully been selected and the
system powers up. The bootstrap process of the operating system begins.
17. The operating system starts the NUT daemons upsd and upsmon. Daemon upsd scans the
UPS and the status becomes [ol]. We are now back in the same situation as state 1 above.
18. We hope that the battery has retained sucient charge to complete further timed shutdown
cycles, but if it hasn't, then at the next power failure, upsd will detect the status [ob lb],
upsmon will receive status [ob lb] and issue a [lowbatt] and will begin the system shutdown
process used by the simple server of chapter 2. This system shutdown will override any
upssched timed process.
Page 55 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
3 UPS-3
00328
big.svg
upsdrvctl upsd mgmt upsmon upssched
UPS-1 + driver NOTIFYCMD CMDSCRIPT
port
ups.status: [OL] 3493/tcp
(nut) upsc
upsdrvctl upssched-cmd
heartbeat.conf
Figure 62: Workstation with additional equipment.
The conguration is for an industrial application in which some undisclosed industrial equipment
is protected by a UPS (UPS-3), and is also driven by a computer system having it's own UPS
(UPS-2). This equipment with the driving computer is at a remote site, code name gold . Overall
management is from a computer at a dierent, administrative site. We will call the management
system mgmt .
Computer mgmt is represented here as if it were a single machine, but it could well be duplicated
at dierent sites for reliability. Two (or more) mgmt systems may monitor a single gold production
machine.
Fourteen conguration les specify the operation of NUT in the production and management
machines.
Page 56 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
1. gold : The NUT startup conguration: nut.conf. This le is not strictly a part of NUT, and
is common to all congurations. See chapter 8.1 and appendix A.
3. gold : The upsd daemon access control upsd.conf: See chapter 8.3.
5. gold : The delayed UPS shutdown script. Since this le is common to all congurations, it is
discussed separately in appendix B. The shutdown script for the undisclosed device is beyond
the scope of this text.
6. mgmt : The NUT startup conguration: nut.conf. This le is not strictly a part of NUT,
and is common to all congurations. See chapter 8.1 also appendix A.
9. mgmt : The upsd daemon access control upsd.conf: See chapter 8.3.
10. mgmt : The upsd user declarations upsd.users: See chapter 8.4.
11. mgmt : The upsmon daemon conguration upsmon.conf: See chapter 8.5.
14. mgmt : The delayed UPS shutdown script. Since this le is common to all congurations, it
is discussed separately in appendix B.
Strictly speaking, this le is not for NUT, but for the process which starts NUT. The initial-
ization process is expected to source this le to know which parts of nut are to be started. Some
distributions, e.g. openSUSE, ignore this le and start the three NUT layers driver, upsd and
upsmon. They assume that MODE=standalone.
This is probably satisfactory for mgmt , but for gold you should review line 438 and the
init/systemd startup of the NUT software to ensure that only the upsd and driver daemons get
started. See appendix A. See also man nut.conf.
Page 57 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
gold : On lines 442-451 we oer specimen denitions for UPS-3 and UPS-2. You will need to
review these to take into account the UPS's you are using. Lines 452 and 443 specify the drivers
that upsd will use. For the full list of drivers, see the Hardware Compatibility list and the required
drivers at http://www.networkupstools.org/stable-hcl.html.
The offdelay and ondelay on lines 446-447 and 455-456 are given their default values. You
may need something dierent. See the discussion in chapter 2.5 of the delayed UPS shutdown.
In order to distinguish the two USB attached UPS units on gold , we specify their serial numbers
on lines 449 and 458. See man usbhid-ups.
mgmt : On lines 460-465 we oer a specimen denition for UPS-1 and on lines 474-477 we
propose the dummy UPS heartbeat discussed in chapter 6. The heartbeat requires the denition
le heartbeat.conf, lines 474-477, to be placed in the same directory as ups.conf.
Page 58 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
This conguration le declares on which ports the upsd daemon will listen, and provides a basic
access control mechanism. You will need a secure means of accessing gold from mgmt . This could
be for example through an SSH tunnel or over a VPN. The limited access dened by the LISTEN
directive is part of a defense in depth.
gold : Line 479 declares that upsd is to listen on a prefered port for trac from mgmt . The
example is for the tun0 interface of an OpenVPN secure network. See https://openvpn.net/ . It
is possible to specify 0.0.0.0 which says listen for trac from all sources and use your rewall to
lter trac to port 3493. You must modify lines 479 and 480 for your own needs.
mgmt : Line 482 declares that upsd is to listen on it's prefered port for trac from the localhost.
It is possible to replace 127.0.0.1 by 0.0.0.0 which says listen for trac from all sources and use
your rewall to lter trac to port 3493.
If you do not have IPv6, remove or comment out lines 480 and 483.
See man upsd.conf for more detail, and a description of the OpenSSL support.
This conguration le declares who has write access to the UPS. The user name used in these
22
les is independent of /etc/passwd. For good security, ensure that only users nut and root
can read and write this le. The conguration les for upsmon must match these declarations for
upsmon to operate correctly.
For lots of details, see man upsd.users.
gold : Line 485 declares the user name of the system administrator who has write access to
UPS-2 and UPS-3 managed by upsd. The upsmon client daemon in mgmt will use this name to
poll and command the UPS's.
Line 486 provides the password. You may prefer something better than sekret. Warning:
Avoid placing spaces U+0020 and quotation marks " U+0022 in passwords.
22 This is for Debian 11. See table 104 in appendix C for other user names.
Page 59 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Line 487 declares the type of relationship between the upsd daemon on gold and the upsmon
in mgmt which has the authority to shutdown gold . The declaration upsmon secondary would
allow monitoring but not shutdown. See man upsd.users. See also man upsmon section UPS
DEFINITIONS, but our conguration is not exactly what that man page refers to.
mgmt : Line 489 declares the user name of the system administrator who has write access to
UPS-1 and to the heartbeat managed by upsd.
Line 490 provides another uberl33t password.
Line 491 declares the type of relationship between the upsd daemon and upsmon which has the
authority to shutdown mgmt .
This conguration le declares how upsmon in mgmt is to handle NOTIFY events from gold
23
and from mgmt itself. For good security, ensure that only users nut and root can read and write
this le.
Line 493 species that upsmon on mgmt will monitor UPS-3 which supplies power to the undis-
closed device.
The UPS name UPS-3 must correspond to that declared in ups.conf line 456.
The power value 1 is the number of power supplies that this UPS feeds on the local system.
A power value of 0 means that the UPS-3 does not supply power to mgmt .
primary means this system will shutdown last, allowing any secondaries time to shutdown
rst. There are no secondaries on gold .
Line 494 species that upsmon on mgmt will also monitor UPS-2 which supplies the gold
computer.
23 This is for Debian 11. See table 104 in appendix C for other user names.
Page 60 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Line 495 species that upsmon on mgmt will monitor UPS-1 which supplies power to mgmt
itself. Note the power value of 1.
Line 496 declares that upsmon is also to monitor the heartbeat.
On line 497, MINSUPPLIES sets the number of power supplies that must be receiving power to
keep the mgmt system running. A lot of computers have just one power supply, so the default value
of 1 is acceptable. See man upsmon.conf and le big-servers.txt in the NUT documentation for
more details.
Line 498 declares the command to be used to shut down mgmt . A second instance of the upsmon
daemon running as root on mgmt will execute this command. Multiple commands are possible,
for example SHUTDOWNCMD "logger -t upsmon.conf \"SHUTDOWNCMD calling /sbin/shutdown
to shut down system\" ; /sbin/shutdown -h +0" will also log the action of SHUTDOWNCMD. Note
that internal " have to be escaped. Note also that any calls of the command upsmon -c fsd will
also execute this command. See line 576.
The shutdown command for gold is not specied in upsmon.conf. It appears in the user script
upssched-cmd in chapter 8.7.
Line 499 says which program is to be invoked when upsmon detects a NOTIFY event agged
as EXEC.
Line 500, POLLFREQ, declares that the upsmon daemon will poll upsd in gold and in mgmt
every 5 seconds.
Line 501, POLLFREQALERT, declares that the upsmon daemon will poll the upsd daemons every
5 seconds while any UPS in on battery.
Line 502, DEADTIME species how long upsmon will allow a UPS to go missing before declaring
it dead. The default is 15 seconds.
Daemon upsmon requires a UPS to provide status information every few seconds as dened by
POLLFREQ POLLFREQALERT. If the status fetch fails, the UPS is marked stale. If it stays stale
and
for more than DEADTIME seconds, the UPS is marked dead.
A dead UPS-1 that was last known to be on battery [ob] is assumed to have changed to a
low battery condition [ob]→[ob lb]. This may force a shutdown of mgmt . Disruptive, but the
alternative is barreling ahead into oblivion and crashing when you run out of power. See chapter
3.3 for more discussion.
Line 503, POWERDOWNFLAG declares a le created by upsmon when running in primary mode
when UPS-1 needs to be powered o. See man upsmon.conf for details.
Page 61 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
Lines 504-513 assign a text message to each NOTIFY event. Within each message, the marker
%s is replaced by the name of the UPS which has produced this event. On mgmt upsmon passes
this message to program wall to notify the system administrator of the event. You can change
the default messages to something else if you like. The format is NOTIFYMSG event "message "
where %s is replaced with the identier of the UPS in question. Note that program wall has
not been internationalized and does not support accented letters or non latin characters. When
the corresponding NOTIFYFLAG contains the symbol EXEC, upsmon also passes the message to the
program specied by NOTIFYCMD on line 499.
Lines 514-523 declare what is to be done at each NOTIFY event. The declarations, known as
ags are shown in table 14. You may specify one, two or three ags for each event, in the form
FLAG[+FLAG]*, however IGNORE must always be alone.
Lines 514-515 carry only the EXEC ag: Since the heartbeat induces a lot of [online] and
[onbatt] trac, the SYSLOG option would ood the log and WALL would put far too many useless
messages in xterm windows. When the NOTIFY event occurs, EXEC declares that upsmon should
call the program identied by the NOTIFYCMD on line 499.
Note that if you have multiple UPS's, the same actions are to be performed for a given NOTIFY
event for all the UPS's. Once again, we see that this is not good news.
Page 62 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
When a UPS says that it needs to have its battery replaced, upsmon will generate a [replbatt]
NOTIFY event. Line 524 say that this happens every RBWARNTIME = 43200 seconds (12 hours).
Line 525: Daemon upsmon will trigger a [nocomm] NOTIFY event after NOCOMMWARNTIME
seconds if it can't reach any of the UPS entries in conguration le upsmon.conf. It keeps warning
you until the situation is xed.
Line 526: When running in primary mode, upsmon waits this long after sending the [shutdown]
NOTIFY event to warn the users. After the timer elapses, it then runs your SHUTDOWNCMD as
specied on line 498. If you need to let your users do something in between those events, increase
this number. Don't make this too big, even though the battery still has charge. Alternatively, you
can set this very low so you don't wait around when it's time to shut down.
For lots and lots of details, see man upsmon.conf. See also the le config-notes.txt in the
distribution.
Daemon upsmon in mgmt detects the NOTIFY events due to status changes in gold and in mgmt ,
and for those agged as EXEC in upsmon.conf calls upssched as indicated by the NOTIFYCMD directive.
The program upssched provides a richer set of actions than upsmon, especially the management of
timers.
On line 528 CMDSCRIPT points to a user script to be called for designated NOTIFY events. This
script will receive as argument the user chosen timer name.
Line 530 denes PIPEFN which is the le name of a socket used for communication between
upsmon and upssched. It is important that the directory be accessible to NUT software and
nothing else. For line 530 the Debian distribution uses /var/run/nut/upssched.pipe.
Daemon upsmon requires the LOCKFN declaration on line 531 to avoid race conditions. The
directory should be the same as PIPEFN.
Lines 533 and 534 say what is to be done by upssched for a NOTIFY event [onbatt] due to
UPS-3 on gold . On line 533 the START-TIMER says that upssched is to create and manage a timer
called UPS-3-two-minute-warning-timer which runs for 5 seconds. When this timer completes,
upssched calls the user script specied by CMDSCRIPT with argument UPS-3-two-minute-warning
-timer. Line 534 does a similar thing for the 125 second timer UPS-3-shutdown-timer.
Hopefully the back-up generator starts, and power returns before 2 minutes have gone by. Lines
535-537 say what is to be done by upssched for NOTIFY event [online]. The CANCEL-TIMER
Page 63 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
declarations say that upssched must cancel the timers UPS-3-two-minute-warning-timer and
UPS-3-shutdown-timer. The user script is not called.
Line 537 command EXECUTE says that upssched is to call the user script immediately with the
argument UPS-3-back-on-line.
UPS-2 on gold is handled in exactly the same way as UPS-3. Lines 539 and 540 dene the timers
which start when upssched receives a NOTIFY event [onbatt], and lines 541 and 542 cancel those
timers when hopefully upssched receives NOTIFY event [online].
Line 543 command EXECUTE says that upssched is to call the user script immediately with the
argument UPS-2-back-on-line.
Page 64 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
UPS-1 on mgmt is also handled in exactly the same way as UPS-3. Lines 545 and 546 dene the
timers which start when upssched receives a NOTIFY event [onbatt], and lines 547 and 548 cancel
those timers when hopefully upssched receives NOTIFY event [online], however if power does not
return before two minutes have gone by, the timer UPS-1-shutdown-timer will complete and
upssched will call the user script with the parameter UPS-1-shutdown-timer .
Line 549 command EXECUTE says that upssched is to call the user script immediately with the
argument UPS-1-back-on-line.
On line 551, when daemon upssched receives an [onbatt] it executes the command CANCEL-TIMER
heartbeat-failure-timer. This kills the timer. upssched does not call the user script.
Immediately afterwards, on line 552, and for the same [onbatt] event, upssched executes
command START-TIMER heartbeat-failure-timer 660 which restarts the heartbeat-failure
-timer which will run for another 660 sec, i.e. 11 minutes. If the timer completes, upssched will
call the user script upssched-cmd with parameter heartbeat-failure-timer.
553 #!/bin/bash -u
554 # upssched-cmd -- mgmt --
555 logger -i -t upssched-cmd Calling upssched-cmd $1
556
UPS-3
The user script upssched-cmd, the example we show is in Bash, manages the completion of
-two-minute-warning-timer, UPS-2-two-minute-warning-timer, UPS-1-two-minute-warning
-timer, UPS-3-shutdown-timer, UPS-2-shutdown-timer, UPS-1-shutdown-timer, UPS-3-back
-on-line, UPS-2-back-on-line, UPS-1-back-on-line and heartbeat-failure-timer.
There is no such thing as a single script which ts all industrial situations, but here is an example
of what can be done. You will probably need to modify this for your own use. Note that this script
could be written in the language of your choice, as long as the resulting program is able to receive
Page 65 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
the timer names as a parameter, send e-mails and log and notify the users of messages. Bash has
the advantage of being widely available and is understood by many sysadmins.
In gure 78, on lines 558 and 559, change the e-mail addresses to something that works for you.
Lines 561-562 declare a function which prepares a Bash variable STCH which gives the current
UPS status and battery charge. This is to be included in messages, so we get a clearer idea of what
is happening.
The bulk of the user script is a case statement beginning at line 563 covering all the possible
parameter values (timer names) that the user script may expect.
In gure 79, lines 564-570 cover the events associated with UPS-3 on gold . When an [onbatt]
occurs the sysadmin receives wall and notify warnings that power to the undisclosed device has
failed, and that unless alternative power becomes available in two minutes, the undisclosed device
will be shut down. These warnings contain the text assembled in Bash variable MSG. Additionally,
when the [onbatt] occurs upssched begins a two minute timer UPS-3-shutdown-timer. If no
alternative power appears, and this timer expires, the installation specic code on line 568 will
shut down the undisclosed device attached to gold . This code might for example be based on the
saltstack remote management tools.
In gure 80, lines 572-578 cover the events associated with UPS-1 on mgmt . When an [onbatt]
occurs the sysadmin receives wall and notify warnings that power to the management workstation
has failed, and that unless alternative power becomes available in two minutes, the workstation will
be shut down. These warnings contain the text assembled in Bash variable MSG. Additionally, when
Page 66 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
the [onbatt] occurs upssched begins a two minute timer UPS-1-shutdown-timer. If no alternative
power appears, and this timer expires, the command upsmon -c fsd on line 576 will shut down
the workstation by executing the command specied by SHUTDOWNCMD on line 498.
In gure 81, lines 579-585 cover the event associated with heartbeat on mgmt . The heartbeat
technique is discussed in detail in chapter 6. If the heartbeat-failure-timer completes then
something is wrong with NUT, and lines 581, 582 and 583 prepare a message for the sysadmin
in Bash variables MSG1, MSG2 and MSG3. Lines 584-585 e-mail the message to the sysadmin. The
message includes the current state of those NUT kernel processes which are operational.
In gure 82, lines 586-587 cover any unexpected parameter values, and lines 589-590 log the
message and pass it to the system notication.
Page 67 of 131
NUT 2.8.0 CongExamples 3.0 AT X run 2023-03-20
L E
UPS-3 on gold : If UPS-3 detects that power has failed, and takes over the supply to the undisclosed
device, then the NUT setup will advise the system administrator on the mgmt workstation. If the
backup generator comes on automatically before two minutes, then the sysadmin on mgmt will
be informed, but if power does not re-appear, then script upssched-cmd in mgmt will remotely
command the shutdown of the undisclosed device. A complete shutdown may be impossible, and
all that can be done for some equipment is to put it into a quiescent state. The management
workstation mgmt is not shut down.
UPS-2 on gold : If UPS-2 detects that its own power supply has failed, and that it is now
powering gold , then the NUT setup of this chapter will advise the system administrator on the
mgmt workstation. With the example conguration, if power is not restored in two minutes then an
action in the script upssched-cmd will shut down both gold and the undisclosed device. Workstation
mgmt is not shut down.
UPS-1 on mgmt : If UPS-1 detects that its own power supply has failed, and the workstation
management is now on battery power, then we enter the scenario described in detail in chapter 7.
There is no need to shutdown the undisclosed device or gold . A backup workstation on a dierent
site could take over the management of UPS-3 and UPS-2.
Page 68 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
Part 2
9 Introduction
The description of the Python3 scripts in this Part supposes that you have some experience as a
system administrator and that you are already familiar with NUT, it's component daemons and
conguration les as described in Part 1.
The Python language was originally designed in the apparent belief that all would be OO, but this
24
is now weakening as one writer put it in order to attract a larger audience .
The Python3 scripts are not object oriented (OO). NUT itself is a process control application
and is event oriented, not object oriented. The Python scripts of part 2 are similarly event
oriented, and the design will be evident to those familiar with the NUT C code.
The Python scripts proposed for NUT provide a set of functions, and a main program written in
an imperative style very similar to the NUT C programs. The coding syntax itself is inuenced
by the OO origins of Python. For example the concatenation of two strings a and b is written
.join([a, b]). In OO parlance the class of the empty string provides the method join with
a list of parameters. However no OO skill or conviction is needed to read the proposed scripts.
The Python3 scripts described in this documentation are lint free as determined by the pylint pro-
gram which follows the PEP 8 style guide for Python code. Since the Python3 programs described
here are a contribution to NUT rather than the general Python ecosystem, changes have been made
Page 69 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
to allow NUT characteristics to be freely expressed. These changes to the default Python style are
dened by le pylintrc, and shown in gure 83.
The PEP 8 style guide for Python code requires that no line include trailing spaces. To remove
trailing spaces using emacs, try command M-x replace-regexp RET +$ RET RET where is a
space. How does vim do this? The l33t use commnd :%s/\s\+$//e
Page 70 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
SSL and the TLS that has replaced SSL are a quagmire of technical terms many of which are out-
25
of-date, confusing or incorrectly used. The OpenSSL project has produced a Swiss Army Knife
of utilities which are the best known tools for work in this area. Anyone venturing into this mess
has to do a lot of reading. Here is a very short list.
The Network UPS Tools User Manual, chapter 9, Notes on securing NUT.
Ivan Risti¢'s A Short Guide to the Most Frequently Used OpenSSL Features and Commands
available at web site feistyduck.com OpenSSL Cookbook.
Web site digitalocean.com, OpenSSL Essentials: Working with SSL Certicates, Private Keys
and CSRs.
Web site zytrax.com, Survival guides - TLS/SSL and SSL (X.509) Certicates.
Here is a short summary of technical terms used in this chapter, see also this post.
Certicate A le containing the public key used by clients to communicate with the server, pos-
sibly with additional information. For public keys we use le names of the form
mybox -client.cert.pem where mybox is the name of the upsd server.
Page 71 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
Certicate Authority (CA) Commercial businesses and others who want their customers to feel
safe using their sites have their TLS certicates veried by a Certicate Authority (CA). You
apply with a Certicate Signing Request (CSR), pay and receive a copy of your certicate
linked to a trusted root certicate, for some meaning of trust.
Where does NUT stand? We are our own Certicate Authority and the certicate we create
is itself the root certicate. We do nut use CSRs. We trust ourselves. In a closed industrial
context where few people have access to the systems, this provides better security than the
commercial oerings used on the web. Quoting from RFC 5280, section 3.2:
(a) Certication paths start with a public key of a CA in a user's own domain,
or with the public key of the top of a hierarchy. Starting with the public key of
a CA in a user's own domain has certain advantages. In some environments, the
local domain is the most trusted.
Root certicate A Certifying Authority takes the private key and provides a certicate of authen-
ticity known as a root certicate. However in the commercial world intermediaries appear
and get paid to add their certicates, thus forming a chain of trust. NUT does not have
such a chain. The root certicate is the only one. In NUT's self-signed world, the upsd server
26
uses as private key a le which contains the private key and then the root certicate . For
the private key we use a le name of the form mybox.cert.pem where mybox is the name of
the upsd server. The clients will use just the root certicate which contains the public key.
PEM PEM is an encoding 27 format for a certicate which is already ASN1 encoded and which
allows it to be included in ascii base 64 les. If you are curious, the three letters PEM stand
for Privacy-enhanced Electronic Mail. We use le type .cert.pem for these certicate les,
but you will also nd such certicates with just the pem extension.
CSR A Certicate Signing Request contains the private key and the additional information needed
to build the public key certicate. A CSR is needed for public sites for which an expensive
external service will sign the certicate as authentic and valid (for some value of authentic
and valid). Since UPS units are not a public matter, we sign our own certicates. NUT does
not use CSR's.
Page 72 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
The script has many options, but in general few and in some simple cases none at all are needed.
To see the options and their default values enter command mkNUTcert.py --help
--clientcertfile <filename> , -c <filename> File path and name for the client's certicate.
mkNUTcert.py tries to guess where to put things. Lucky Debian users might see /etc/nut/
mybox -client.cert.pem . All the clients of the upsd server use this certicate.
--countryName <ISO 3166 two letters> , -C <ISO 3166 two letters> Please feel free to
specify your 2 digit ISO 3166 Country Codes. The default is FR.
-O <name> , --organisationName <name> The proud default for organisation name is Network
UPS Tools. You probably don't have to change this.
-OU <unit name> , --organisationUnitName <unit name> The default value for the Organisa-
tion Unit name is mkNUTcert.py version 1.1. Again, you probably don't have to change
this.
--subjectAltName <list of server names> , -SAN <list of server names> You may well
want to change this option. It denes a space separated list of names of the upsd server. The
default is mybox localhost 10.218.0.19 mybox.example.com where mybox is the name
of the machine on which you have run mkNUTcert.py. In earlier releases of SSL/TLS the
option CN (Common Name) was used to specify the server name. This is now deprecated in
favour of SAN (subjectAltName).
Page 73 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
--notBefore <integer> The validity start time is seconds from the moment you run the program.
The default is 0, i.e. now. You probably don't have to change this.
-v, --version Show mkNUTcert.py, Python and SSL/TLS versions, then exit.
The private key and public keys, known as certicates) provided by mkNUTcert.py are in the form
of PEM encoded les:
The server's root certicate, i.e. private key with a self-signed certicate, PEM encoding can be
seen with command shown on line 596 in gure 85:
If you attempt to display the contents of the root certicate using the command. openssl x509
-text -noout -in /etc/nut/titan.cert.pem then only the certicate is displayed, as shown in
gure 87.
Page 74 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
Details of the certicate can be seen with the command shown on line 610 in gure 87 which
shows a self-signed public certicate:
1. The certicate is certied directly by the server's root certicate and there are no intermediate
certicates. NUT acts as it's own certifying authority. For tightly controlled situations such
as UPS management, this provides better security.
2. The certicate is self-signed. The issuer on line 616 is also the subject on line 620 as required
by RFC 5280 para 4.1.2.4 last sentence.
3. The value Dec 31 23:59:59 9999 GMT on line 619 is dened by RFC 5280 para 4.1.2.5.
5. There is no Authority Key Identier which is obligatory for Web certicates. This omission
is specic to self-signed certicates, see RFC 5280 para 4.2.1.1.
28 A public key certicate provides a safe way for an entity to pass on its public key to be used in asymmetric
cryptography. The public key certicate avoids the following situation: if Charlie creates his own public key and
private key, he can claim that he is Alice and send his public key to Bob. See techtarget.com.
Page 75 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
Page 76 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
1. Before running the script, check the shebang #! in the rst line. The default value is
#!/usr/bin/python3 -u . Check that you have a suciently recent version of Python3
at that address. If your version is not suciently recent, you will receive an error message
from mkNUTcert.py. How do I know if I have a suciently recent version of Python3? Try
running the script. If it runs, you're ok. Otherwise you will need to upgrade your Python
installation.
2. Run command mkNUTcert.py --help to see the default values. Pay extra attention to the
following:
The script also attempts to guess the owner:group for the two output les. You should review
that choice.
3. When you run the command mkNUTcert.py you will be reminded of the proposed le paths and
le names for the certicates. Enter yes to conrm and anything else to exit immediately.
If you continue, mkNUTcert.py will report:
638 Writing private key with self-signed certificate for server to file ...
639 This file must be protected. E.g. do not make it world readable.
640 Current owner is nut:nut with permissions 0o600.
641
4. Ensure that the private key and the root certicate are properly protected. Only root and
the user designated to run upsd should have access to the private key. No-one else.
The root certicate is given restrictive permissions 600. If you attempt to run the script a
second time it may well refuse if there is already a root certicate at the same address with
such restrictive permissions. You have to remove the old root certicate yourself as user root.
Take care!
Page 77 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
11 Encrypted connections
The congurations we have seen so far assume that the connection between the NUT client and
the NUT server is either in the same machine or over a local, well protected network. The client's
password is transmitted in clear text to the server. This may be a reasonable risk locally, but is
not acceptable if client and server are connected by a public network or by a network deemed to
be at risk. This chapter looks at the technique for encrypting the trac between client and server
made possible by TLS 1.3 support in NUT 2.8.0.
Chapter 12 discusses the use of TLS shims to provide the same encryption for NUT 2.7.4.
MIIjQw....
-----END PRIVATE KEY----- -----BEGIN CERTIFICATE-----
MIIfHd....
-----BEGIN CERTIFICATE----- -----END CERTIFICATE-----
MIIfHd....
-----END CERTIFICATE-----
See chapter 10.1 for a very short introduction to the quagmire of technical terms many of which
are confusing or incorrectly used.
This chapter will continue the habit of chapter 8 of referring to the server to which the UPS is
connected as gold and the management client as mgmt .
Page 78 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
In addition to the conguration les discussed in previous chapters, the following conguration les
are also needed for encrypted communication between remote NUT server gold and management
client mgmt .
645 # upsd.conf
646 ...
647 DISABLE_WEAK_SSL true
648 CERTFILE /etc/nut/titan.cert.pem
Line 647 prevents use of insecure early versions of SSL/TLS by restricting upsd to use TLSv1.2
or better.
On line 648 the upsd daemon access control upsd.conf needs the private key generated by
29
mkNUTcert.py. The CERTFILE declaration declares the le containing the root certicate, i.e. the
private key and the certicate in PEM format. See chapter 10.3.1.
649 # upsmon.conf
650 ...
651 CERTVERIFY 1
652 CERTPATH /etc/nut/titan-client.cert.pem
Line 651 makes upsmon verify all connections with certicates. Without this, there is no guar-
antee that the upsd is the right host. Enabling this greatly reduces the risk of man-in-the-middle
attacks. This eectively forces the use of SSL, so don't use this unless all of your upsd hosts are
ready for SSL and have their certicates in order.
In line 652 CERTPATH points to a le containing a certicate in PEM format, used to verify the
server certicate presented by the upsd server.
29 The name CERTFILE is a poor choice since it is a private key not a public key. A name such as KEYFILE
would have been better. Normally it is public keys that are referred to as certicates.
Page 79 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
Testing is essential to achieve the required level of security, and a key part of this testing is sning
the network to ensure that the connections to port 3493 on the NUT server gold are indeed
encrypted.
We use tcpdump on Debian for this testing. Other network sning software is available. The
rst test is to see the clear text nature of the non-encrypted communication.
1. In the server, gold , or in the management client mgmt , run the command tcpdump -A port
nut as root.
2. In the management client mgmt , stop upsmon, and then restart it with the command
systemctl restart nut-monitor.service.
3. tcpdump will display the trace shown in gure 89 which has been edited to make it easier
to read. Line 657 shows the client mgmt attempting to begin an encrypted session which is
refused by server gold on line 659. Line 663 shows the password transmitted in clear text .
Let this be a warning to you.
Lines 669-672: Client mgmt then makes a plain text request every 5 seconds for the status
of UPS-3 which the server gold then answers in plain text.
653 listening on wlan0, link-type EN10MB (Ethernet), capture size 262144 bytes
654 IP mgmt.33656 > gold.nut:
655 IP gold.nut > mgmt.33656:
656 IP mgmt.33656 > gold.nut:
657 IP mgmt.33656 > gold.nut: STARTTLS
658 IP gold.nut > mgmt.33656:
659 IP gold.nut > mgmt.33656: ERR FEATURE-NOT-CONFIGURED
660 IP mgmt.33656 > gold.nut:
661 IP mgmt.33656 > gold.nut: USERNAME upsmaster
662 IP gold.nut > mgmt.33656: OK
663 IP mgmt.33656 > gold.nut: PASSWORD sekret
664 IP gold.nut > mgmt.33656: OK
665 IP mgmt.33656 > gold.nut: LOGIN UPS-3
666 IP gold.nut > mgmt.33656: OK
667 IP mgmt.33656 > gold.nut: MASTER UPS-3
668 IP gold.nut > mgmt.33656: OK MASTER-GRANTED
669 IP mgmt.33656 > gold.nut: GET VAR UPS-3 ups.status
670 IP gold.nut > mgmt.33656: VAR UPS-3 ups.status "OL"
671 IP mgmt.33658 > gold.nut:
672 IP mgmt.33656 > gold.nut: GET VAR UPS-3 ups.status
673 IP gold.nut > mgmt.33656: VAR UPS-3 ups.status "OL"
Figure 89: tcpdump of systemctl start nut-monitor.service without encryption.
Page 80 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
This test was done using a hybrid setup in which a version 2.8.0 upsmon talks to a version 2.7.4
upsd equipped with a shim upsdTLS.py. As shown in gure 92 upsd listens on customary port
3493 (nut), but the shim is listening on port 401.
First we trace the unencrypted trac on port 3493 (nut). The trace has been edited to make it
easier to read:
Page 81 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
Command flow
401/tcp (ups)
upsd
3493/tcp (nut)
beep 3493/tcp (nut) upsmon
beep upsdTLS.py upsmonTLS.py
upsdrvctl 2.7.4 upsc
+ driver upsrw
TLS TLS
UPS-1 upscmd
ups.status: [OB]
...
upsdTLS.svg
Figure 92: NUT 2.7.4 TLS support using shims upsdTLS.py and upsmonTLS.py.
NUT 2.7.4 did not support the latest versions of TLS. This prevented NUT 2.7.4 from using
TLS since TLS strongly deprecates use of earlier versions which are no longer considered secure.
To overcome this diculty, Python script upsdTLS.py provides a shim to help upsd work with the
latest, and most secure, versions of TLS. upsdTLS.py runs as a daemon alongside upsd receiving
TLS encrypted trac from it's companion shim upsmonTLS.py or from a TLS enabled client
such as UPSmon.py and passing on that trac to local upsd using an unencrypted socket. The
script's status is "experimental", and is intended for demonstration and experiment. It must run
on the same machine as upsd. The license is GPL v3 or later at your choice, with support in the
nut-upsuser mailing list.
The script has no conguration les, but has many options. In general few and in some simple
cases none at all are needed. To see the options and their default values you can enter command
upsdTLS.py --help .
Let's look at these optional arguments in more detail. XXX
--backlog <integer> Maximum incoming message backlog, default value 5. You should not usu-
ally need to change this.
Page 82 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
-D, --debug Increase the debugging level, may be repeated but then you get more than any human
can read. Debugging output is written into the NUT log le.
--listentimeout <float> Socket timeout for exchanges on the port specied by --listen. The
default is 5.0 seconds.
-l <file>, --logfile <file> The log le, with default /var/log/NUT.log . Progress and error
messages and the copious stu generated by option -D go into this le. See chapter E for an
extension to logrotate to cover this le.
--maxconn <integer> Maximum number of incoming connections, the default is 10. Strictly
speaking, the maximum number of sockets the daemon process may have open, where getconf
OPEN_MAX gives system le maximum. You should not usually need to change this.
--PIDfile <file> The child PID is written into this le, for the greater pleasure of systemd.
The default for upsdTLS.py is /run/nut/upsdTLS.pid . Do not change this unless you know
what you are doing. You should also review the systemd service unit.
-s <file>, --servercertfile <file> The le path and le name of the server's private key.
upsdTLS.py tries to guess where to put things. The default on Debian systems is /etc/
nut/mybox.cert.pem . OpenSUSE sysadmins would probably use /etc/ups/... See table
104 for a list of possible directories.
-u <user>, --user <user> After launch as root, run as this user. upsdTLS.py tries to guess the
user. OpenSUSE admins would probably see upsd, whereas Debian admins would see nut.
See table 104 for a list of possible users.
--upsdport <integer> Relay incoming commands to this upsd port, and (no surprise) the default
relay port to upsd is 3493. upsd is assumed to be running on llocalhost.
Page 83 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
--upsdtimeout <float> Socket timeout for exchanges with upsd. The default is 5.0 seconds.
-v, --version Show program, Python and SSL/TLS versions, then exit.
The script has no conguration les, but lots of options. In general few and in some simple
cases none at all are needed. To see the options and their default values you can enter command
upsmonTLS.py --help .
Let's look at these optional arguments in more detail.
--backlog <integer> Maximum incoming message backlog, default value 5. You should not usu-
ally need to change this.
-c <file>, --clientcertfile <file> The le path and le name of the client's certicate (pub-
lic key). upsmonTLS.py tries to guess where to put things. The default on Debian systems
is/etc/nut/mybox -client.cert.pem . OpenSUSE sysadmins would probably use /etc/
ups/... See table 104 for a list of possible directories.
-D, --debug Increase the debugging level, may be repeated but then you get more than any human
can read. Debugging output is written into the NUT log le.
--listen <IPv4_address> upsmonTLS.py listens to the client such as upsmon or upsc on this
interface and port, with the default '127.0.0.1' 3493.
--listentimeout <float> Socket timeout for exchanges on the port specied by --listen. The
default is 5.0 seconds.
-l <file>, --logfile <file> The log le, with default /var/log/NUT.log . Progress and error
messages and the copious stu generated by option -D go into this le. See chapter E for an
extension to logrotate to cover this le.
Page 84 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
--maxconn <integer> Maximum number of incoming connections, the default is 10. Strictly
speaking, the maximum number of sockets the daemon process may have open, where getconf
OPEN_MAX gives system le maximum. You should not usually need to change this.
--PIDfile <file> The child PID is written into this le, for the continuing pleasure of systemd.
The default for upsmonTLS.py is /run/nut/upsmonTLS.pid Do not change this unless you
know what you are doing. You should also review the systemd service unit.
-u <user>, --user <user> After launch as root, run as this user. upsdTLS.py tries to guess the
user. OpenSUSE admins would probably see upsd, whereas Debian admins would see nut.
See table 104 for a list of possible users.
--upsdname <domain> Relay incoming commands from the client to the system running the shim
upsdTLS.py. For example --updsname "bigserver.example.com". The default name is
localhost.
--upsdport <integer> Relay incoming commands from upsmon, upsc, etc. to this upsd/shim
port. The default relay port for upsmonTLS.py is 401 which the companion script upsdTLS.py
listens to by default. Temporarily, we squat IANA 401/tcp (ups). Setting a port number <
1024 requires starting the daemon as root.
--upsdtimeout <float> Socket timeout for exchanges with upsd. The default is 5.0 seconds.
-v, --version Show program, Python and SSL/TLS versions, then exit.
Page 85 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
upsmonTLS.py only
--clientcertfile <file> /etc/nut/mybox -client.cert.pem
--listen <IPv4> <port> 127.0.0.1 3493
--PIDfile <file> /run/nut/upsmonTLS.pid
--upsdname <domain> localhost
--upsdport <port> 401
Figure 95: Summary of upsdTLS.py and upsmonTLS.py options and default values.
The daemons upsdTLS.py and upsmonTLS.py usually start with user root and fork to run as the
same user as upsd.
If you use systemd to manage your boxes, then you will need to create new service units, since
systemd is unable to start two forking services from the same unit. See man systemd.service(5).
There can only be one Type=forking per unit.
/usr/lib/systemd/
In the box running upsd create a new le by copying the service unit le
system/nut-server.service to /etc/systemd/system/nut-py-server-shim.service and mod-
ify the new le as shown in gure 96. where lines 694-696 and 698-699 have been changed.
Page 86 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
693 [Unit]
694 Description=Network UPS Tools - nut-server TLS shim support daemon
695 After=local-fs.target network.target nut-server.service
696 Before=nut-py-client.service
697 [Service]
698 ExecStart=/usr/sbin/upsdTLS.py
699 PIDfile=/run/nut/upsdTLS.pid
700 Type=forking
701 [Install]
702 WantedBy=multi-user.target
Figure 96: systemd service unit nut-py-server-shim.service for upsdTLS.py.
/usr/lib/systemd/system/nut-monitor.
In the box running upsmon copy the service unit le
service to /etc/systemd/system/nut-py-client-shim.service and modify the new le as
shown in gure 97 where lines 704-706 and 708-709 have been changed.
The PIDfile declarations are there to help systemd nd the daemon since upsdTLS.py and
upsmonTLS.py do not keep the parent process running when they fork. Note that systemd service
units in /etc take precedence over those in /usr/lib. See man systemd.unit(5).
703 [Unit]
704 Description=Network UPS Tools - TLS shim support daemon for nut clients
705 After=local-fs.target network.target nut-server.service\
nut-py-server-shim.service
706 Before=nut-client.service
707 [Service]
708 ExecStart=/usr/sbin/upsmonTLS.py
709 PIDfile=/run/nut/upsmonTLS.pid
710 Type=forking
711 [Install]
712 WantedBy=multi-user.target
Figure 97: systemd service unit nut-py-client-shim.service for upsmonTLS.py.
You may choose to place the upsdTLS.py and upsmonTLS.py scripts in directory /usr/sbin or
make /usr/sbin/upsdTLS.py and /usr/sbin/upsmonTLS.py links to wherever you put the Python
scripts. After you have made the changes, you should run the command systemctl daemon-reload
See man systemctl(1).
Page 87 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
Before running the shims the rst time, you will need to run the command
systemctl daemon-reload
to make any changes to the service unit available to systemd.
upsdTLS.py and upsmonTLS.py should start automatically when the system starts, but they
can also be stopped and started manually with the systemctl commands.
Serious errors will prevent the shims from starting and you can read about them in the NUT log
and in the system log. After starting the shims, check the NUT log for warnings and other error
messages.
Page 88 of 131
TLS Support CongExamples 3.0 AT X run 2023-03-20
L E
During the debugging of the shims, I saw a summary of the NUT systemd service unit activity on
a Debian 11 (NUT 2.7.4) system with the command:
Page 89 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
Part 3
Appendices
A Starting NUT
729 # nut.conf This chapter discusses the techniques used to start
730 # No spaces around the "=" the NUT software. Each distribution has it's own
Page 90 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
Conguration le nut.conf species which of these daemons the operating system should start,
but distributions often ignore the le. The distribution choice is normally correct for a standalone
workstation protected by a single UPS, but for more complex situations, you need to review what
your distribution does. See chapter 8.1 and man nut.conf.
Strictly speaking, this le is not for NUT, but for the process which starts NUT. The initial-
ization process is expected to source this le to know which parts of nut are to be started. Some
distributions, e.g. openSUSE, ignore nut.conf and start the three NUT layers driver, upsd and
upsmon. They assume that MODE=standalone. Note that there is no space around the = since it
is assumed that shell scripts such as Debian's /sbin/upsd source this le.
The possible MODE values are:
MODE=none Indicates that NUT should not get started automatically, possibly because it is
not congured or that an Integrated Power Management or some external system, is used to
start up the NUT components. If you enable nut-server.service Debian 30 will display the
message:
upsd disabled, please adjust the conguration to your needs. Then set MODE to
a suitable value in /etc/nut/nut.conf to enable it.
31
Enabling nut-monitor.service will produce a similar message .
MODE=standalone This is the most common situation in which line 731 in gure 99 declares
that NUT should be started in the standalone mode suitable for a local only conguration,
with 1 UPS protecting the local system. This implies starting the 3 NUT layers, driver, upsd
and upsmon and reading their conguration les.
MODE=netserver Like the standalone conguration, but may possibly need one or more
specic LISTEN directive(s) in upsd.conf. Since this MODE is open to the network, a special
care should be applied to security concerns. Debian accepts starting upsmon in this mode.
MODE=netclient When only upsmon is required, possibly because there are other hosts
MODE should be set to netclient. If you enable
that are more closely attached to the UPS, the
Debian's systemd service unit nut-server.service with this mode, then you will get the
same message as for MODE=none.
However these alternate modes are merely wishful thinking if your distribution ignores le
nut.conf. There are other options, see man nut.conf.
Page 91 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
B Stopping NUT
B.1 Delayed UPS shutdown with NUT script
We saw in chapter 2, line 45, that the upsmon.conf SHUTDOWNCMD directive species the command
to be used to shut down the system, but what about the UPS which must keep supplying power
while the system shuts down? Does the UPS also shut down?, and if so, how?
Chapter 2.5 The shutdown story for a simple server explains that somewhere in your distri-
bution, as part of the system shutdown process, there needs to be an action to send a message to
the UPS to tell it that some time later, it too will shut down. The notion of shutdown for a UPS
unit is subtle. What shuts down is usually the supply of power to the power outlets. The UPS unit
cuts o the equipment for which it provides battery backup. When this happens you may hear the
audible clunk of the relays. The unit may also act as a power strip with surge protection, but
those outlets are not covered by the protection aorded by the battery.
Note that the UPS does not shutdown at the same time as the system it protects. The UPS
shutdown is delayed. By default the delay is 20 seconds. See line 77 if you want to change this.
The delayed UPS shutdown command may be from a shell script or a systemd service unit, but
in all cases the key element is the command upsdrvctl shutdown.
The NUT project provides a sample script, which is to be placed in a directory of things to be
done at the end of the system shutdown. This depends on the distribution.
The Debian 11 distribution places the delayed shutdown script provided by NUT and shown in
gure 101 in le /usr/lib/systemd/system-shutdown/nutshutdown . The openSUSE distribution
does the same.
732 #!/bin/sh
733 /usr/sbin/upsmon -K >/dev/null 2>&1 && /usr/sbin/upsdrvctl shutdown
Figure 101: UPS shutdown script nutshutdown.
On line 733 the call to upsmon with option -K checks the POWERDOWNFLAG dened by line 46.
The upsmon daemon creates this le when running in primary (master) mode whenever the UPS
needs to be powered o. See man upsmon.conf for details. If the check succeeds, we are free to call
upsdrvctl to shut down the UPS's. Note that if you have multiple UPS's, the command upsdrvctl
shutdown will shut them all down. If you have say three UPS's, UPS-1, UPS-2 and UPS-3, and you
want to shut down just UPS-2 and UPS-3, then you should specify those UPS's as shown in line
735. See also man upsdrvctl
734 #!/bin/sh
735 /usr/sbin/upsmon -K >/dev/null 2>&1\
&& /usr/sbin/upsdrvctl shutdown UPS-2\
&& /usr/sbin/upsdrvctl shutdown UPS-3
Figure 102: UPS shutdown script nutshutdown for 2 of 3 UPS's.
Page 92 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
The script provided by the NUT project in chapter B.1 is executed very late in the shutdown
sequence, when it is no longer possible to log the action. If you think that power management is
a critical operation and that all critical operations should be logged, then you will need to call for
the delayed UPS shutdown earlier in the system shutdown sequence when logging is still possible.
This can be done using the systemd service unit shown in gure 103.
736 # nut-delayed-ups-shutdown.service
737 [Unit]
738 Description=Initiate delayed UPS shutdown
739 Before=umount.target
740 DefaultDependencies=no
741 [Service]
742 Type=oneshot
743 ExecStart=/usr/bin/logger -t nut-delayed-ups-shutdown\
"upsdrvctl shutting down UPS"
744 ExecStart=/usr/sbin/upsdrvctl shutdown # Debian
745 [Install]
746 WantedBy=final.target
Figure 103: UPS shutdown service unit nut-delayed-ups-shutdown.service.
The ExecStart directive on line 744 will shutdown 32 all the UPS units managed by this system.
The code given is for Debian: other distributions put upsdrvctl elsewhere. If you have say three
UPS's, UPS-1, UPS-2 and UPS-3, and you want to shut down just UPS-2 and UPS-3, then instead
of line 744 you should specify the required UPS's as shown in lines 747-748.
Note that this service unit does not perform the upsmon -K test for the POWERDOWNFLAG.
The position of this service unit may vary from one distribution to another, see section unit le
load path in man systemd.unit(5). For example in the openSUSE and Debian distributions, /etc
/systemd/system is for a user's scripts, and /usr/lib/systemd/system-shutdown is for system
scripts. You might use the /etc/systemd/system directory if your script is not part of an ocially
distributed product.
If you install or change this service unit, run command systemctl --system reenable /etc/
systemd/system/nut-delayed-ups-shutdown.service . Maybe your distribution oers a graph-
ical manager to do this.
For gory details see the systemd documentation. There are over 200 man pages starting with
an index. For details of the directories used, see section unit le load path in man systemd.unit.
32 The upsdrvctl program is normally a frontend to the drivers, but in the case of the shutdown option upsdrvctl
does not use the existing driver; it creates a new driver for itself.
Page 93 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
Page 94 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
Notes:
1. The OpenBSD user may be _ups which is an OpenBSD convention for identifying unprivi-
leged users. Most OpenBSD add-on software uses unprivileged usernames beginning with an
underscore.
2. If NUT is built without specifying the user, then the user is nobody:nobody.
3. FreeNAS identies itself in /etc/os-release as FreeBSD.
4. The IPFire wiki suggests user nutmon for upsmon but makes no mention of upsd.
Page 95 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
D Using notify-send
The program wall used by NUT to put notications in front of the users is now well past it's
best-before date and hardly t for purpose. It has not been internationalized, does not support
accented letters or non-latin characters, and is ignored by popular desktop environments such as
Xfce, Gnome and KDE. It's apparent replacement notify-send gives the impression that it has never
been tested in any other than the simplest cases, and that it is not ready for industrial strength
use. Getting notify-send to work with NUT is not immediately evident, so although notify-send is
not a part of NUT, we discuss this problem here.
The program notify-send is part of a set of programs which implement the Gnome Desktop Noti-
cations Specication. The introduction says:
This is a draft standard for a desktop notications service, through which appli-
cations can generate passive popups to notify the user in an asynchronous manner of
events. ... Example use cases include:
Scheduled alarm
From this introduction it would seem that desktop notications are exactly what is needed to
present [ol]→[ob] and [ob]→[ob lb] warnings to the users, but unfortunately, things are not that
simple.
Program notify-send is a utility which feeds message objects to a message server, such as
notifyd. Taking the Xfce desktop environment as an example, Xfce provides it's message server
called xfce4-notifyd. See man xfce4-notifyd-config, man notify-send and the Desktop No-
tications Specication. There is also an xfce4-notifyd web page.
Experience shows that just calling notify-send in the script upssched-cmd does not work. The
message simply disappears. Closer examination on the openSUSE distribution with command ps
-elf | grep ups shows that if daemon upsmon running as user upsd calls notify-send to present
a message, the notify daemon is launched with the same userid upsd as the caller. In Debian,
NUT runs as user nut and the notify daemon is launched with the name userid nut. Users such
as upsd and nut do not have access to the desktop environment.
Page 96 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
If the caller is the upsmon daemon which has no access to the desktop environment, then neither
will the corresponding notication daemon. This is surprising. One would expect a design closer to
that of the printer daemon cupsd which runs permanently in the background receiving les to be
printed. There is only one daemon cupsd and that daemon isolates the user from needing to know
how to drive printers.
To get the message to show on the user's screen appears to require two actions:
1. Give user upsd (nut on Debian) the right to act as any user,
2. Search for logged in users, and for each user construct the user's environment variable DISPLAY,
and call utility notify-send as that user to notify the user.
D.2 Give user nut (upsd) the right to act as any user
To improve security in NUT, the upsd and upsmon daemons is not executed as root, but rather as
a non-root userid. This userid is typically called nut or upsd. See table 104 for a list of possible
users. We will use the name nut. nut is not a regular user and does not have the access to the
X-server needed to display data. This is a problem for the notication service, which we now x.
Add the following lines to the le /etc/sudoers
749 # Host alias specification
750 Host_Alias LAN = 10.218.0/255.255.255.0,127.0.0.1,localhost,gold
751
Line 750 corresponds to the editor's system and should be adapted to your setup.
On line 752 the directive SETENV: is needed for openSUSE but optional for Debian.
The le /etc/sudoers contains the following warning:
This le MUST be edited with the 'visudo' command as root. Failure to use 'visudo'
may result in syntax or le permission errors that prevent sudo from running.
Seeman sudoers and man visudo. The un-l33t do not have to use vi. Luckily, the command
VISUAL=/usr/bin/emacs visudo -f /etc/sudoers also does the job.
Page 97 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
Figure 107 shows a Bash script notify-send-all which can be used in place of notify-send to send
messages from upssched-cmd to all the X display users currently logged in. Script notify-send-all
accepts as argument the message to be displayed. The message will be displayed indenitely as
critical. The editor places the script in le /usr/local/bin/notify-send-all.
753 #! /bin/bash -u
754 # notify-send-all sends notifications to all X displays
755 # Assumes /etc/sudoers allows caller to sudo as any user.
756 # E.g. nut LAN = (ALL) NOPASSWD:SETENV: /usr/bin/notify-send
757 # Call with text to be displayed as argument.
758 XUSERS=( $( who | grep -E "\(:[0-9](\.[0-9])*\)" \
759 | awk '{print $1$NF}' | sort -u ) )
760 for XUSER in $XUSERS # E.g. jschmo(:0)
761 do NAME=(${XUSER/\(/ }) # Insert space, make NAME an array
762 DISPLAY=${NAME[1]/)/} # E.g. :0
763 sudo -u ${NAME[0]} DISPLAY=${DISPLAY} \
764 /usr/bin/notify-send -t 0 -u critical "$@"; RC=$?
765 if [[ $RC -ne 0 ]]; then exit $RC; fi
766 done
Figure 107: Bash script notify-send-all
Line 758 produces a Bash array of all the users identied by who who have X displays. Each
item in the array corresponds to a logged in user with an X display and is of the form jschmo(:0).
For each user logged in with an X display, line 761 creates a Bash array containing the user
name and the X display number in the form jschmo :0).
Line 762 extracts the X display number :0 and on line 763 calls notify-send to notify the user
as if user nut (upsd on openSUSE) was that logged in user. Note that environment variable
DISPLAY is set for that user.
See the discussion Show a notication across all running X displays on the stackexchange site.
A simple way of testing the use of notify-send if you are using the chapter 4 conguration is to
simply disconnect the wall power for 10 seconds. This is sucient to provoke upsmon into calling
upssched-cmd which in turn calls notify-send-all as shown at line 194.
While wall power is disconnected, use a command such as ps -elf | grep -E "ups[dms]|nut"
to nd the programs running as user nut (upsd on openSUSE):
Page 98 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
Lines 767-772 are due to NUT activity, and lines 773-776 are due to the use of notify-send. Note
on line 775 that the xfce4-notifyd daemon is running as user nut !
1. For a suggestion of how to send notications on an Apple Mac, see the posting by Robbie van
der Walle, Sun Jun 11 11:27:55 UTC 2017, in the nut-upsuser mailing list.
2. For a discussion of how to send notications to all running X-server users, see stackexchange
question 2881.
3. The Gnome Desktop Notications Specication is still a very long way from being RFC
quality.
These techniques have been tested with the Xfce desktop environment on openSUSE and Debian.
The editor would be pleased to hear of any successful adoption of the techniques on Fedora, Arch
or Ubuntu based systems, using other desktop environments such as Cinnamon, KDE or Gnome.
Page 99 of 131
Appendices CongExamples 3.0 AT X run 2023-03-20
L E
Line 788 calls for a log rotation every month, and line 787 requires keeping 12 previous months'
logs, so in all there will be one year's records.
Line 789 creates a le with owner nut:nut suitable for Debian. You should adapt this for your
distribution. See table 104.
Part 4
Part 1 of this documentation discussed the way in which UPS activity reported by upsd can be
monitored using the monitoring software provided with NUT 2.8.0. This part 4 covers the use of
Python3 scripts and openSSL/TLS to monitor the same UPS activity.
This Part provides descriptions of Python3 scripts UPSmon.py and mkUPSmonconf.py. The
script UPSmon.py requires a helper script to create TLS certicates. The script mkNUTcert.py is
described in part 2 chapter 10.
The scripts and their SHA1 check sums may be downloaded from http://rogerprice.org/NUT
beep
upsdTLS 401
beep
upsdrvctl 2.7.4 UPSmon.py
+ driver .py
EVENT
UPS-1 TLS TLS OL->OB
ups.status: [OB]
UPSmon.svg
beep
beep upsd UPSmon.py
hic sunt dragones
3493
beep
upsdrvctl 2.8.0
+ driver TLS EVENT
TLS OL->OB
UPS-1 ups.status: [OB]
UPSmon-OB.svg
UPSmon.py is a Python3 script which replaces upsmon, upssched and upssched-cmd. The congura-
tion les upsmon.conf and upssched.conf are replaced by a single conguration le UPSmon.conf.
The current version 1.2 of UPSmon.py is experimental, intended for experiment and demonstra-
tion.
1. UPSmon.py is written in Python3 rather than K&R C. It is hoped that this use of a well
known higher level language will encourage further experimentation. The script is in one
single le rather than the many separate les used in NUT C code. Like the NUT C code,
the script is not object oriented. To assist further development, the script provides 116 error
and warning messages, and the -D and -Y debug options provide a detailed walk-through of
the script's operations.
2. Unlike upsmon, UPSmon.py does not retain the parent process when forking to a non-
privileged user. This improves security, but implies that the non-privileged user such as
nut has sudo rights for programs wall, notify-send and shutdown.
3. UPSmon.py assumes that it will be managing a large number of physical and virtual UPS
and other power supply units. The management may be of the type primary or secondary,
known formerly as master or slave, or simply as an observer with the primary/secondary
shutdown decisions taken elsewhere.
4. The UPS units, real and virtual, are collected into groups. Every UPS must be in exactly one
group. upsmon does not support groups.
5. All UPS's must be individually identied. Unlike NUT, there are no wildcard UPS's. Each
UPS has a formal fully qualied name which is of the form group :ups @host :port , for
example HB:heartbeat@bigbox:3493 , although shortened forms are used where there is no
ambiguity.
6. The conguration le UPSmon.conf is read by PLY, Python Lex and Yacc. This implies a
slightly slower start-up than NUT but allows freer formats and many possibilities for future
expansion.
8. All communication between UPSmon.py and upsd is TLS encrypted. The version of OpenSSL
used is too recent to be compatible with nut 2.7.4, so a shim front end for upsd called
upsdTLS.py is provided to accept TLS encrypted commands from UPSmon.py and then relay
that trac to the local upsd. Part 2 describes upsdTLS.py. The options chosen for TLS
call for the latest version with full checking of the certicates. Use of the earlier and now
deprecated SSL is excluded.
9. UPSmon.py supports two loggers: the system log and a text based NUT-specic log.
10. UPSmon.py does not require a supplementary program such as upssched or a script such as
upssched-cmd. The functions of those programs are available in UPSmon.py. NUT's upsmon
Action Eect
STARTTIMER name value Start timer with the given name and value in seconds.
CANCELTIMER name Cancel timer with the given name.
EMAIL FROM text
TO text
Send email.
SUBJECT text
MESSAGE text
WALL text Send text to local wall.
NOTIFY text Place text on screens of all logged-in local accounts.
PRINT text Send text to STDOUT.
EPRINT text Send text to STDERR.
NUTLOG text Send text to NUT-specic logger.
SYSLOG text Send text to system logger.
SETFSD name Send fsd to upsd for UPS name.
SHUTDOWN option when Shutdown the system, e.g. with
/usr/sbin/shutdown -h now .
DEBUG level Turn on/o the debugging output to the NUT log.
provides three NOTIFYFLAG options: SYSLOG, WALL and EXEC, UPSmon.py replaces these with
the more complete set of actions shown in gure 110.
11. Texts to be included in messages may be given names, and may incorporate other named
messages. The upsmon NOTIFYMSG % substitution is extended to provide the substitutions
shown in table 111.
12. The low battery status [lb] provided by upsd is supplemented by three further low battery
statuses [lb1], [lb2] and [lb3] for which the trip levels may be set in UPSmon.conf.
13. When the sum of the POWERVALUE in a group with status [ol] does not meet the group's
MINSUPPLIES requirement, UPSmon.py raises status [ls]. In upsmon this is implicit in the
client's logic.
UPSmon.py can be run at the same time and in the same machine as upsmon. UPSmon.py does
not interfere with direct access to upsd port 3493. Command line utility programs such as upsc
still function normally.
The script has a conguration le, and many options. In general few options and in some simple
cases none at all need be changed. To see the options and their default values you can enter
command UPSmon.py --help
--command fsd|reload|stop Send command to UPSmon.py process and exit. Valid commands
are fsd, reload, stop.
-c <file>, --config <file> The conguration le. UPSmon.py tries to guess where you put
this. Debian sysadmins might see /etc/nut/UPSmon.conf . OpenSUSE admins might see
/etc/ups/... See table 104 for a list of possible directories.
-D, --debug Increase the debugging level, may be repeated but then you get more than any human
can read. Debugging output is written into a NUT log le. This option does not cover Lex
and Yacc.
-Y, --debugYacc Increase the debugging level for Lex and Yacc. No human being should ever be
required to read this stu. Debugging output is written into a NUT log le.
-l <file>, --logfile <file> The log le, with default /var/log/NUT.log . Progress and er-
ror messages and the stu generated by options -D and -Y go into this le. Note that if
upsdTLS.py and UPSmon.py are running in the same machine they will write into the same
log. See chapter E for an extension to logrotate to cover this le.
--shell <file> The shell that will process the SHELLCMD actions. The default is /bin/bash -c
--sudo <executable> Authorise user to execute code as another user. The default is /usr/bin/
sudo . Use of sudo assumes that le /etc/sudoers allows the caller to sudo as the required
user. For example
nut LAN = (ALL) NOPASSWD:SETENV: /usr/bin/notify-send, /usr/bin/wall
nut LAN = (ALL) NOPASSWD:SETENV: /usr/sbin/shutdown
where LAN is dened by a declaration such as
Host_Alias LAN = 10.218.0/255.255.255.0, 127.0.0.1, localhost
To update /etc/sudoers , use visudo , for example VISUAL=/usr/bin/emacs visudo -f
/etc/sudoers .
-K <executable>, --testSHUTDOWNflag Test the SHUTDOWN ag. Not implemented.
--upsdtimeout <float> Socket timeout for exchanges with upsd. The default is 5.0 seconds.
-u <user>, --user <user> After launch as root, run as this user. UPSmon.py tries to guess the
user. OpenSUSE admins would probably see upsd, whereas Debian admins would see nut.
See table 104 for a list of possible users.
-v, --version Show program, Python and SSL/TLS versions, then exit.
It is possible, in a simple installation, to run the daemon UPSmon.py in the same machine as upsd.
However the design is for remote monitoring of one or more upsd servers across a hostile network.
UPSmon.py assumes that the server(s) is/are already running and ready to receive the STARTTLS
command.
If you use systemd to manage your box, then you will need to create a new service unit, since
man systemd.service(5).
systemd is unable to start two forking services from the same unit. See
Type=forking per unit.
There can only be one
Copy the le /usr/lib/systemd/system/nut-monitor.service to /etc/systemd/system/
nut-py-monitor.service and modify the new le shown in gure 113. Lines 799, 801 and 802
have been changed.
797 [Unit]
798 Description=Network UPS Tools - Python - power device monitor
799 After=local-fs.target network.target
800 [Service]
801 ExecStart=/usr/sbin/UPSmon.py
802 PIDfile=/run/nut/UPSmon.pid
803 Type=forking
804 [Install]
805 WantedBy=multi-user.target
Figure 113: systemd service unit nut-py-monitor.service for UPSmon.py.
You may choose to place the UPSmon.py script in directory /usr/sbin/ or make /usr/sbin/
UPSmon.py a link to wherever you put the Python script. Note that systemd service units in
/etc/ take precedence over those in /usr/lib/. See man systemd.unit(5). After you have made
the changes, you should run the command systemctl daemon-reload . See man systemctl(1).
Before running upsdTLS.py the rst time, you will need to run the command
systemctl daemon-reload to make any changes to the service unit available to systemd.
systemctl start nut-py-monitor.service to start UPSmon.py. Note that this will not erase
the log le. If you want to clear the log le then you need to do that yourself. See also chapter
E for a discussion of log rotation.
UPSmon.py should start automatically when the system starts, but it can also be stopped and
started manually with the systemctl commands.
Serious errors will prevent UPSmon.py from starting and you can read about them in the NUT
log and in the system log. After starting UPSmon.py, check the NUT log for warnings and other
error messages. Look for the reports beginning Sanity checks for this configuration ....
33
UPSmon.py, like NUT's upsmon is an example of a client of upsd . Just as upsmon does, it
runs permanently as a daemon in a local or remote box, polling the status changes of the UPS
unit. It is able to react to changes in the UPS state for example by emitting warning messages, or
shutting down the box. The actions are specied in the conguration le UPSmon.conf which will
be discussed in specic examples.
As the state of a UPS evolves, each status change, called an EVENT, is identied with the
symbols shown in gure 114. (These correspond to the NOTIFY events, also known as a notifytype
in NUT.)
For example, gure 109 shows what happens when wall power fails. Daemon upsd has polled
the UPS, and has discovered that the UPS is supplying power from it's battery. The ups.status
changes to [ob]. Daemon UPSmon.py has polled upsd, has discovered the status change and has
generated the ol->ob event.
In addition to the events based on upsd status changes, UPSmon.py also generates further
statuses and status changes based on its monitoring of upsd. See gure 115. Changes in these
additional statuses give rise to additional events shown in gure 116.
There is just one conguration le for UPSmon.py which replaces upsmon.conf, upssched.conf
and upssched-cmd. The formal grammar for this conguration le is in chapter H. The le contains:
1. Comments and blank lines. A comment begins with a # character found outside a quoted
text, and continues up the the end-of-line.
The following technical terms are used in the descriptions of the conguration le:
34
quotation mark One of the following ve styles of text marker. See chapter G for help in
typing the characters which may not be on your keyboard.
name Names for groups, timers, UPS's, messages. The name begins with [a-zA-Z_] and
continues with as many of [a-zA-Z0-9._%+-] as you like. E.g. UPS31.a-BIG_BOX.
ups-name All UPS's must be individually identied. Unlike NUT, there are no wildcard
UPS's. Each UPS has a formal fully qualied name which is of the form group :ups @host :port
for example HB:heartbeat@bigbox:3493 , although shortened forms are used where there is
no ambiguity.
34 I couldn't decide which ones to use so I kept them all. Ed.
SMTPSERVER quotetext PORT number USER quotetext PASSWORD quotetext If you want
to send e-mails, you must provide details of your e-mail service provider. For example
SMTPSERVER 'mail.gandi.net' PORT 465 USER '[email protected]' PASSWORD 1234 .
Connections with the SMTP server are always TLS encrypted.
LET name = quotetexts Provide a name for one or more quotetext. This saves a lot a typ-
ing. For example LET banner = [%(b)s] UPS=%(u)s charge=%(c)s event=%(e)s . The
named message LET hostname = hostname is built in. There may be multiple LET declara-
tions, and each may make use of names declared in previous LETs.
MAXNOTIFY number This limits the number of on-screen notications, and was needed during
early debugging when things often exploded. It will probably be removed in the future. The
default is 20.
POLLFREQ number This is the polling period for all UPS units managed by this UPSmon.py in-
stance. The default, which is the recommended value, is 5 seconds. See also man upsmon.conf
POLLFREQALERT number This is the polling period for all UPS units managed by this UPSmon.py
instance when any one of them is in status [OB]. The default is 5 seconds.
Each group in a sequence of groups begins with a GROUP declaration header followed by other
declarations described in this section.
Within a group, a condition is either empty or has the form IF old-status -> new-status .
The condition has the value True if in the sequence of events from the given UPS, that UPS now
has status new-status. For example the expression IF OB -> OL is True if the UPS currently has
status [OL] and False if the UPS has status [OB]. Note that old-status -> new-status must be a
valid event as listed in chapter F.5.
The GROUP declaration header is as follows:
GROUP name HOST name PORT number CERTFILE name/quotetext One or more UPS units
share the same HOST, PORT and TLS CERTFILE. E.g. GROUP LOCAL HOST localhost PORT
401 CERTFILE /etc/nut/gold-client.cert.pem . The UPS units attached to this host are
grouped together and each is specied by a MONITOR declaration in this group.
LET name = quotetexts Further named texts. Note that there is only one name space shared
by all LET declarations. It's up to you to avoid clashes.
The name battery.charge.low.i for i = 1..3 is a special case in which the quotetexts must be
quoted integer. The eect is to assign the integer value as the battery charge level at which the
events None->LBi and LBi->None will occur. For example LET battery.charge.low.2 =
'33' The level is set for the most recently dened UPS, i.e. MONITOR declaration.
the previous
The default levels are lb1=50, lb2=25 and lb3=12.
MONITOR ups-name POWERVAL number UPSDUSER name PASSWORD quotetext TYPE name
Each UPS unit to be managed must be declared. The ups-name must match the name in
the ups.conf declaration. See for example line 32. The POWERVAL is the number of power
supplies that this UPS feeds.The UPSDUSER is the user declared in upsd.users. See
line 40. PASSWORD is the value declared in upsd.users. See line 41. The TYPE value
The
must be primary or secondary. The earlier values master, slave are accepted. In NUT's
upsmon.conf primary means this system will shutdown last, allowing any secondaries time
to shutdown rst. The declaration is included here to facilitate interworking with upsmon
but in UPSmon.py, it is merely a declaration of intention, since the logic is decided by the
declared actions.
E.g. MONITOR ups1 POWERVAL 1 UPSDUSER leboss PASSWORD 'sekret' TYPE primary
MINSUPPLIES number
Declare for each GROUP the number of power supplies which must be operational, and that if
fewer are available, NUT must shut down the server. The default value is 1 if this declaration
is omitted. See chapter 3.2
The sequence old-status ->new-status denes a status change, i.e. an event. The valid events
are listed in chapter F.5.
When the event specied for this UPS is detected, the actions will be executed. For example
WHEN ups1 REPORTS None->LB : actions Let's hope those actions do something useful.
condition DEBUG 0/1/2 Initiate or terminate debugging output. Note that since a set
of actions is executed in random order, you should not rely on a DEBUG in the same set
of actions as the action you wish to trace.
condition EMAIL FROM quotetext
TO quotetext
SUBJECT quotetext
MESSAGE quotetexts
Send an email via the mail server declared in the introduction by SMTPSERVER. E.g.
condition STARTTIMER timer-name number Declare and start a timer with the given
name, and the given value in seconds. It is up to you to avoid name conicts between
timers and with other names. E.g. STARTTIMER final-delay 5
condition EPRINT quotetexts Send the quotetexts to STDERR. When UPSmon is
daemonized, EPRINT is ignored. Use NUTLOG instead.
condition NOTIFY quotetexts Place the quotetexts in an on-screen notication for all
logged-in users. If UPSmon.py is run as a non-privileged user, which is usually the case,
than that user, for example nut, must be given access to program notify-send in le
/etc/sudoers . See chapter D.2 for details of how to do this. See also man sudo(8) for
lots and lots of brain-damaging detail.
condition NUTLOG quotetexts Write the quotetexts into the NUT log le specied by
option --logfile. The quotetexts will be prepended with a timestamp and a reminder
of the source program and line number. For example action NUTLOG Hello World
might add the following line to the log le:
condition PRINT quotetexts Send the quotetexts to STDOUT. When UPSmon is dae-
monized, PRINT is ignored. Use NUTLOG instead.
condition SETFSD ups-name This action sets the forced shutdown ag on each sec-
ondary (slave) UPS when the primary (master) plans to power it o. This is done so
that secondary (slave) systems will know about the power loss and shut down before
the UPS power disappears. UPSmon.py, like upsmon, in primary (master) mode is the
primary user of this function.
Setting this ag makes [FSD] appear for this UPS. This [FSD] should be treated just
like a [OB LB]. To use this action, you need upsmon primary in upsd.users, or FSD
action granted in upsd.users. See man upsd.users.
Note that [FSD] in upsd is currently a latch - once set, there is no way to clear it short
of restarting upsd. This may cause issues when upsd is running on a system that is not
shut down due to the UPS event.
See the Network UPS Tools Developer Guide, Network protocol information
condition SHELLCMD quotetexts Call on the shell dened by the option --shell to
execute the command given by the quotetexts. For example
condition SHUTDOWNCMD quotetexts Call for a system shutdown using the command
specied by the quotetexts. For example, SHUTDOWNCMD /sbin/shutdown -h 0. If
UPSmon.py is run as a non-privileged user, which is usually the case, than that user,
for example nut, must be given access to program shutdown in le /etc/sudoers . See
chapter D.2 for details of how to do this. See also man sudo(8) for lots of detail.
condition SYSLOG quotetexts Write the quotetexts into the system log. The system
log provides 8 levels of urgency. They are shown, in order of decreasing importance, in
table 117. If your quotetexts are prexed with one of these urgency indicators, your mes-
sage will be logged at the required level e.g. SYSLOG [debug] UPS %(u)s burning
. The default level is [info].
condition WALL quotetexts Place the quotetexts in a console message for all logged-in
users. If UPSmon.py is run as a non-privileged user, which is usually the case, than that
user, for example nut, must be given access to program wall in le /etc/sudoers . See
chapter D.2 for details of how to do this. See also man sudo(8) for details. Note that
wall does not support UTF-8.
" U+0022 Keyboard " Keyboard " quotation mark (Used left and right)
' U+0027 Keyboard ' Keyboard ' apostrophe (Used left and right)
U+00AB AltGr{ or AltGr{ or left-pointing double angle quotation
Ctl-q 00ab Ctl-v u00ab mark
U+00BB AltGr} or AltGr} or right-pointing double angle quotation
Ctl-q 00bb Ctl-v u00bb mark
d U+23A1 Ctl-q 23a1 Ctl-v u23a1 left square bracket upper corner
c U+23A6 Ctl-q 23a6 Ctl-v u23a6 right square bracket lower corner
U+2E22 Ctl-q 2e22 Ctl-v u2e22 top left half bracket
U+2E25 Ctl-q 2e25 Ctl-v u2e25 bottom right half bracket
The conguration le is assumed to be encoded in UTF-8, and contains comments, tokens (keywords
and symbols), numbers and quoted text interspersed with white space.
Whitespace Whitespace is any combination of the characters space, tab and newline. Whitespace
serves only to separate the other components of a conguration le.
Comments The character # outside a quoted text begins a comment which continues up to the
end of the line. The comment is ignored by the parser. A # inside a quoted text does not begin
a comment. This is the same comment style as upsmon.conf and many other conguration
les.
Names Names are labels which identify UPS units, timers, named messages, ... They are not
quoted and are made up of the 67 characters a-zA-Z0-9._%+- . The leading character must
be one of the 53 characters a-zA-z_ .
Numbers Numbers are non-negative and may be oating point. They are not quoted. E.g. 5.5 .
Tokens The tokens are names given to every piece of input that is recognisable by the lexer. They
are shown in gure 120. The tokens are presented in the order in which they are tested by
the lexer.
Quoted text Text is always quoted. The possible quotation marks are shown in gure 118. E.g.
"text", 'text', text, dtextc and text . A quoted text may not contain a newline or
it's terminating quote character. E.g. text is an error as is te
xt.
None ALARM BOOST BYPASS CAL CHRG
Statuses The lexer recognises the following UPS statuses:
DEAD DISCHRG FSD LB COMM OB OFF OL OVER RB TEST TICK TOCK TRIM
Events An event is a transition from one status to another, and is seen by the lexer as STATUS
RARR STATUS, e.g. None->LB .
PASSWORD Keyword
POLLFREQALERT Keyword
POLLFREQ Keyword
PORT Keyword
POWERVAL Keyword
PRINT Keyword
QUOTETEXT1 'text'
QUOTETEXT2 "text"
QUOTETEXT3 text
QUOTETEXT4 dtextc
QUOTETEXT5 text
The grammar shows the logical structure of the conguration le. There is no separate yacc
grammar le. The productions are represented by functions such as the one shown in gure 121.
Line 806 declares the function providing the grammar production seen in line 807 for the
configuration production. The result is tagged with a 3-tuple seen in line 808 giving the identity,
line number and column number, and forms the basis for the abstract syntax tree AST. The values
for p[1] and p[2] in line 809 are provided by functions p_intros and p_groups.
Production Notes
configuration : intros groups Start here
continued ...
... continued
... continued
I UPSmon.py conguration
A conguration le UPSmon.conf must be created to tell UPSmon.py how to handle the status
changes coming from upsd. As with upsmon.conf, this can be done manually, but for simple
cases, probably the majority, in which upsd and UPSmon.py run in the same machine, UPSmon.py
provides a Python3 tool mkUPSmonconf.py, to create a complete fully functioning conguration
le. You can either use the output of this tool or take it as the starting point for a customised
conguration.
mkUPSmonconf.py is a Python3 script which will build a simple conguration le UPSmon.conf
for UPSmon.py. The script proposes a possible conguration le based on it's built-in default values
and asks for your approval. Here is a fanciful example.
817 $ mkUPSmonconf.py
818 Here are your chosen values:
819 --configurationfile /etc/nut/UPSmon.conf
820 --clientcertfile /etc/nut/titan-client.cert.pem
821 --emailfrom "<[email protected]>"
822 --emailto "Big Joe <[email protected]>"
823 --plan timed
824 --smtpserver "mailbox@mailserver,com"
825 --smtpport 465
826 --smtpuser jschmo
827 --smtppass qwertyuiop
828 --ups UPS-123
829 --upsdname localhost
830 --upsdport 401
831 --upsduser nut-admin
832 --upsdpass sekret
833 If this configuration is correct, enter yes to proceed, anything else to exit:
If the proposed conguration values are satisfactory, you reply yes, but if they are not right for
you, you hit Enter and rerun the script using the options to specify your preferred values.
The status is experimental. The script is intended for demonstration and experiment. The
license is GPL v3 or later at your choice, with support in the nut-upsuser mailing list.
Let's look at these arguments in more detail.
--clientcertfile <filename> The le which holds the client's public TLS certicate required
to access the server upsd, possibly with upsdTLS.py. E.g. A Debian sysadmin might use
/etc/nut/bigbox-client.cert.pem
--emailfrom <string> The email address from which messages will be sent.
E.g. "<[email protected]>" Note the email convention of placing the address in angle
brackets, and the double quotes needed to prevent Bash from interpreting the angle brackets.
--emailto <string> The email address of the person to whom messages will be sent.
E.g. "Big Joe <[email protected]>" Note the email convention of placing the address in
angle brackets, and the double quotes needed to prevent Bash from interpreting the angle
brackets.
--plan standard|timed Specify standard or timed shutdown plan. Valid options are standard
or timed.
--smtppass <string> The password for your account on the e-mail server. E.g. qwertyuiop
. This denitely needs changing.
--smtpport <integer> Your e-mail server's TLS port. E.g. 465 . Communication with the
mail server is always TLS encrypted.
--ups <name> The name of your UPS, for example UPS_123. If you have more than one UPS
unit then create a conguration le for the rst, and then extend it using copy/paste of the
actions for the second.
--upsdname <name> The name of the system on which upsd runs. E.g. localhost if UPSmon.py
and upsd run on the same machine.
--upsdpass <string> The password for this upsd user, as given in upsd.users.
Do you remember the password = sekret on line 41?
--upsdport <integer> The TLS port used by upsd possibly with shim upsdTLS.py. E.g.
401
--upsduser <name> User for this UPS, as given in upsd.users. E.g. nut-admin on line 40
839 # All groups share the same POLLFREQ and POLLFREQALERT and e-mail relay
840 POLLFREQ 5.0 POLLFREQALERT 5.0
841 SMTPSERVER mail.gandi.net PORT 465
842 USER [email protected] PASSWORD qwertyuiop
2. The POLLFREQ and POLLFREQALERT on line 840 are the same as upsmon. See chapter 4.1.
3. On line 841 the PORT number corresponds to a TLS port. Communication with the email
service provider is always TLS encrypted.
4. On lines 841-842 the ... is added automatically by the mkUPSmonconf.py script. You do
not have to do this.
5. Line 850 corresponds to a Debian installation. See table 104 for a list of possible directories.
1. Line 852 introduces the notion of GROUP. In general a group is a set of UPS units which are
attached to the same upsd server. In NUT's upsmon.conf the MONITOR system declaration
identies the upsd host system and the port. See man upsmon.conf. UPSmon.conf transfers
the host system and port identication to a named group, and adds the CERTFILE declaration.
2. Line 853 resembles the upsmon.conf declaration, but with the inclusion of additional keywords
for clarication. UPS-1 declares the UPS name, the HOST and PORT have already been
declared. The UPS name should correspond to the name specied in ups.conf. See line 32.
3. Since this is the timed plan rather than the standard plan, we need additional messages which
are declared on lines 855-856.
4. When event ol->ob arrives, lines 857-858 call for the on battery message to be put on-
screen and in the NUT log le. The actions also declare the timers two-min and one-min and
start them.
5. When timer one-min runs out, lines 859-863 place warnings on screen, in the NUT log le
and on all logged in terminals. The actions also send an email to the administrator.
6. When timer two-min runs out, lines 864-865 place warnings on-screen, in terminals and in
the NUT log le. A short final-delay timer is declared and started. This timer corresponds
to FINALDELAY in upsmon.conf.
7. What happens if power returns before the shutdown? If event ob->ol arrives, lines 866-867
notify the user, place a message in the NUT log le and turn o all the timers.
8. Whether the plan is standard or timed the local system must be shutdown on event None
->lb. This happens on lines 870-871. Users receive a nal on-screen warning, a message goes
into the NUT log le and the action declares and starts a short final-delay timer.
9. When the final-delay timer runs out, line 872 calls for a system shutdown.
1. Some UPS units are capable of reporting that the battery needs replacement. On line 874,
when event None->rb arrives, messages are placed on-screen and in the NUT log le. Line
876 sends an email to the sysadmin. The upsmon RBWARNTIME behaviour is reproduced by
dening and starting an rbwarntime timer.
37
2. Line 880 species that when the rbwarntime timer runs out, an on-screen message appears
and also goes into the NUT log le. The action also restarts the timer. It will continue to
loop until the status [rb] disappears with event rb-> None on line 881
882 # Warning that UPSmon has lost UPS UPS-1. Shut down on NOCOMM when OB.
883 WHEN UPS-1 REPORTS COMM->NOCOMM : STARTTIMER nocommwarntime 300
884 IF OL->OB NOTIFY Msg-shutdown
885 IF OL->OB NUTLOG Msg-shutdown
886 IF OL->OB WALL Msg-shutdown
887 IF OL->OB STARTTIMER final-delay 5
888 WHEN UPS-1 TIMEOUT nocommwarntime : NUTLOG Msg-NOCOMM NOTIFY Msg-NOCOMM
889 WHEN UPS-1 REPORTS NOCOMM->COMM : CANCELTIMER nocommwarntime
NUTLOG Msg-COMM NOTIFY Msg-COMM
Figure 128: Timed shutdown plan, part 3 of 4, warnings,
3. The statuses [comm] and [nocomm] are not due to upsd. They are generated internally by
UPSmon.py when it has problems talking to upsd. The standard and timed congurations
discussed here have been tested with upsd and UPSmon.py running in the same machine, but
in general this is not the case, and network problems become more apparent when upsd and
UPSmon.py are separated.
The event comm->nocomm starts a timer which will later place a warning message in front
of users and in the NUT log le. This follows the upsmon logic. Additionally, and again
following upsmon logic, a shutdown procedure will begin if the system is currently running on
battery. See lines 884-887. Note that the condition must be attached to each of the actions.
Note the subtle dierence between upsmon and UPSmon.py. See gure 15. On line 68
daemon upsmon will trigger a [nocomm] NOTIFY event after NOCOMMWARNTIME seconds if it
can't reach any of the UPS entries in conguration le upsmon.conf. UPSmon.py does this
for each UPS individually. The dierence is slight if there is only one UPS :-)
4. On line 889 the timer nocommwarntime is cancelled and suitable messages send to the users38
and the NUT log le.
Figure 129: Conguration le Heartbeat denitions are not provided by NUT, you
heartbeat.conf have to create them for yourself. Create the new le
heartbeat.conf as shown in gure 129 in the same di-
rectory as ups.conf. As called for by line 899, the heartbeat will cycle continuously through this
script.
For good security, only users upsd/nut and root should have write access to this le.
896 [heartbeat] Lines 892 and 894 ip the ups.status value be-
898 port = heartbeat.conf Lines 893 and 895 place a 10 minute time interval
899 mode = dummy-loop between each status change. 2 × 600sec = 20min, the
900 desc = "Watch over NUT" heartbeat period.
You must also declare to upsd that it is to generate
Figure 130: Addition to the le
the heartbeat. Add the declaration shown in gure 130
ups.conf for heartbeat.conf
to le ups.conf. In line 897 we see the driver used to
generate the heartbeat. This driver is also used for debugging. You can amuse yourself by adding
further status changes and observing their eect.
1. On line 904 a group HB is declared to contain the heartbeat UPS. The HOST, PORT and
CERTFILE are the same as for the physical UPS.
3. Other than the POWERVAL of 0, the MONITOR declaration on line 907 is the same as for the
physical UPS.
4. Line 908 says that the heartbeat does not require electrical energy. This zero declaration also
circumvents certain sanity checks that real UPS's must pass.
5. Lines 909 and 912 manage the timers which watch over the [tick] and [tock] coming from
upsd. The timer is longer than the expected interval between status arrivals. If this timer
expires we assume that the heartbeat has failed.
6. If you uncomment the logging of the None->tick on line 911 then your log will grow rapidly
with a message every 20 minutes.
7. Line 914 is a form of goto so all the heartbeart error logging is in one place.
8. Lines 915-919 send heartbeat failure messages to the system administrator and to the NUT
log le.
The only dierences between the standard plan and the timed shutdown plan are that the standard
plan removes lines 854-868 and replaces then with lines 922-923. These actions send a warning
message to the users and to the NUT log le.
Please see section 3 and sections Power values and Redundant power supplies in man upsmon.
The upsmon logic is built into the code rather than the conguration le and follows the spirit of
the standard shutdown plan preferred by upsmon.
UPSmon.py allows the system administrator to customise the logic using the conguration le.
The conguration for a timed shutdown plan for redundant power supplies is very similar to a None
->ob timed shutdown : the status [ls] meaning Low Supplies replaces the status [ob]. [ls] says
that within a given group, the total powervalue of the UPS units with status [ol] is not sucient
to meet the MINSUPPLIES criterion.
Shutting down a redundant system using the upsmon logic of waiting for [lb] is left as as exercise
for the reader. If that's what you really want, why not go on using upsmon?
1. Check that you have Python 3.6, or more recent, running. No? You will need to install it.
4. Review the shebangs at the top of the Python3 scripts. Modify if needed to meet the local
situation. The shebangs that come with the scripts are those used by the editor. Yours may
well be dierent.
5. Create symlink from /usr/sbin/UPSmon.py to wherever you put the Python3 scripts. Create
similar links for upsdTLS.py, mkNUTcert.py and mkUPSmonconf.py.
9. Run mkUPSmonconf.py to create the UPSmon.py conguration le. See section I.1.
11. Check that heartbeat.conf is installed in the upsd machine and that ups.conf contains a
[heartbeat] declaration.
12. Stop and disable the nut-monitor service unit.
13. Run systemctl daemon-reload and enable the nut-py-server-shim service unit and the
nut-py-monitor service unit. Start the nut-py-server-shim and then the nut-py-monitor
service units.
14. Check output of command ps -elf | grep -E "nut|upsd" which on an openSUSE machine
gives the output shown in gure 134.
Part 5
The End
K Acknowledgments
Editor: As one of the many who have used the work of the NUT project as part of their system
setup, I would like to express my gratitude and my appreciation for the software that the NUT
project has made available to system administrators through contributions by Charles Lepple, Arjen
de Korte, Arnaud Quette, Jim Klimov, Russell Kroll, and many others in the nut-upsuser mailing
list.
I would also like to thank those who commented on earlier versions of this text: M.B.M.