> For the complete documentation index, see [llms.txt](https://dvt-homestaker.stakesaurus.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dvt-homestaker.stakesaurus.com/automation-tools/automated-power-on-off/network-ups-tools-nut.md).

# Network UPS Tools (NUT)

## NUT Server

> **Pre-requisites:** The [Wake-on-LAN setup](/automation-tools/automated-power-on-off/wake-on-lan-wol.md) must be completed in order to fully use this guide

{% hint style="warning" %}
You will need a UPS with a USB port for this setup.
{% endhint %}

Plug your Raspberry Pi into the UPS power socket and connect them via a USB cable.

Install the Network UPS Tools server package on your Raspberry Pi.

```
sudo apt update
sudo apt install nut nut-server
```

Inspect the NUT folder.&#x20;

```
sudo ls -l /etc/nut
```

You should see the following configuration files which we will be customising in this guide.

```
nut.conf ups.conf  upsd.conf  upsd.users  upsmon.conf  upssched.conf
```

Identify key information about your UPS.

```
sudo nut-scanner
```

**Example output:**

```
Scanning USB bus.
No start IP, skipping SNMP
Scanning XML/HTTP bus.
No start IP, skipping NUT bus (old connect method)
Scanning IPMI bus.
[nutdev1]
	driver = "blazer_usb"
	port = "auto"
	vendorid = "0665"
	productid = "5161"
	product = "USB to Serial"
	vendor = "INNO TECH"
	bus = "003"
```

**Back up the exiting `ups.conf` file as a copy and edit the main file.**&#x20;

<pre><code><strong>sudo cp /etc/nut/ups.conf /etc/nut/ups.conf.example
</strong><strong>sudo nano /etc/nut/ups.conf
</strong></code></pre>

Replace the file contents by matching the output from the `nut-scanner` output above. Use `CTRL+T` and then `CTRL+V` to clear all file contents. **This defines the user and driver information of your UPS.**

**Example:**

```
[nutdev1]
    driver = blazer_usb
    port = auto
    desc = "USE PRODUCT OR VENDOR HERE"
    vendorid = 0665
    productid = 5161
```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

**Back up the exiting `upsd.conf` file as a copy and edit the main file.**

<pre><code><strong>sudo cp /etc/nut/upsd.conf /etc/nut/upsd.conf.example
</strong><strong>sudo nano /etc/nut/upsd.conf
</strong></code></pre>

Replace the file contents with the following. Use `CTRL+T` and then `CTRL+V` to clear all file contents. **This will enable your other devices (NUT clients) to talk to your NUT server for shutdown/power-on signals.**

```
LISTEN 0.0.0.0 3493
```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

**Back up the exiting `nut.conf` file as a copy and edit the main file.**

<pre><code><strong>sudo cp /etc/nut/nut.conf /etc/nut/nut.conf.example
</strong><strong>sudo nano /etc/nut/nut.conf
</strong></code></pre>

Replace the file contents with the following. Use `CTRL+T` and then `CTRL+V` to clear all file contents. **This sets your Raspberry Pi to the NUT `server` mode.**

```
MODE=netserver
```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

**Back up the exiting `upsd.users` file as a copy and edit the main file.**

<pre><code><strong>sudo cp /etc/nut/upsd.users /etc/nut/upsd.users.example
</strong><strong>sudo nano /etc/nut/upsd.users
</strong></code></pre>

Replace the file contents with the following. Use `CTRL+T` and then `CTRL+V` to clear all file contents. **This sets the credentials for the NUT user.**

```sh
[monuser]
  password = secret
  upsmon master
#"monuser", "secret", and "master" need to match the contents of the upsd.users
# to be set below
```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

**Back up the exiting `upsmon.conf` file as a copy and edit the main file.**

<pre><code><strong>sudo cp /etc/nut/upsmon.conf /etc/nut/upsmon.conf.example
</strong><strong>sudo nano /etc/nut/upsmon.conf
</strong></code></pre>

***Add the following as new lines** to the bottom of the existing file content. **This defines the actual power monitoring activities and consequent actions upon detecting a power restoration.***&#x20;

```sh
MONITOR nutdev1@localhost 1 monuser secret master
#"monuser", "secret", and "master" need to match the contents of the upsd.users set above
NOTIFYFLAG ONLINE SYSLOG+EXEC+WALL
NOTIFYCMD /etc/nut/online.sh # we will create this shell script later
```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

**Create the `online.sh` shell script** which tells all your devices to power up when it detects that power supply to your UPS has been restored following a power outage.

{% hint style="info" %}
***Note:** I am using a simple script to handle the automated power on sequence because I can't get my NUT to work as intended. Let me know if anyone managed to get yours working.*
{% endhint %}

```sh
sudo nano /etc/nut/online.sh
```

Paste the following content.&#x20;

```sh
#!/bin/bash
# Log the start of the script
logger "NUT: Checking UPS status for ONLINE event"

# Fetch the UPS status
status=$(upsc nutdev1@localhost ups.status)

# Check if the UPS is on battery
if [[ "$status" == "OL" ]]; then
    logger "NUT: UPS on line power detected. Waiting 60 seconds before powering up all devices."
    
    # Wait for 60 seconds
    sleep 60
    
    # Log the power up initiation
    logger "NUT: Initiating power up after 60-second delay."
    /usr/local/bin/wake_devices "UPS online"
else
    logger "NUT: UPS status is not ONLINE (status: $status). No power up triggered."
fi

```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

{% hint style="info" %}
This online.sh script makes use of the wake\_devices script that we created in the Wake-on-LAN page.
{% endhint %}

Make this shell script executable but set proper permissions for security.

```sh
sudo chmod +x /etc/nut/online.sh
sudo chown root:nut /etc/nut/online.sh
sudo chmod 750 /etc/nut/online.sh
```

Restart the NUT services.

```sh
sudo service nut-server restart
sudo service nut-client restart
sudo systemctl restart nut-monitor
sudo upsdrvctl stop
sudo upsdrvctl start
```

Inspect the `nut-server` and `nut-monitor` for errors.

```
sudo journalctl -fu nut-server  -o cat | ccze -A
sudo journalctl -fu nut-monitor -o cat | ccze -A
```

**Example output:**

```sh
#nut-server
Starting Network UPS Tools - power devices information server... 
fopen /run/nut/upsd.pid: No such file or directory 
listening on 0.0.0.0 port 3493 
listening on 0.0.0.0 port 3493 
Connected to UPS [prolink]: blazer_usb-prolink 
Connected to UPS [prolink]: blazer_usb-prolink 
Startup successful 
Started Network UPS Tools - power devices information server. 
User monuser@127.0.0.1 logged into UPS [prolink]

#nut-monitor
Starting Network UPS Tools - power device monitor and shutdown controller... 
fopen /run/nut/upsmon.pid: No such file or directory 
UPS: prolink@localhost (master) (power value 1) 
Using power down flag file /etc/killpower 
Startup successful 
nut-monitor.service: Can't open PID file /run/nut/upsmon.pid (yet?) after start: Operation not permitted 
nut-monitor.service: Supervising process 1206 which is not our child. We'll most likely not notice when it exits. 
Started Network UPS Tools - power device monitor and shutdown controller. 
nut-monitor.service: Supervising process 1206 which is not our child. We'll most likely not notice when it exits. 
nut-monitor.service: Supervising process 1206 which is not our child. We'll most likely not notice when it exits. 
```

`CTRL+C` to exit logging view.

## NUT Clients

{% hint style="info" %}
The following steps need to be configured on all your other devices (e.g., validator node) to power down gracefully when there is a power outage.
{% endhint %}

Install the Network UPS Tools client on your device.&#x20;

```
sudo apt update
sudo apt install nut-client
```

Inspect the NUT folder.&#x20;

```
sudo ls -l /etc/nut
```

You should see the following configuration files which we will be customising in this guide.

```
nut.conf  upsmon.conf  upssched.conf
```

**Back up the exiting `nut.conf` file as a copy and edit the main file.**

<pre><code><strong>sudo cp /etc/nut/nut.conf /etc/nut/nut.conf.example
</strong><strong>sudo nano /etc/nut/nut.conf
</strong></code></pre>

Replace the file contents with the following. Use `CTRL+T` and then `CTRL+V` to clear all file contents. **This sets your Validator Node to the NUT `server` mode.**

```
MODE=netclient
```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

**Back up the exiting `upsmon.conf` file as a copy and edit the main file.**

<pre><code><strong>sudo cp /etc/nut/upsmon.conf /etc/nut/upsmon.conf.example
</strong><strong>sudo nano /etc/nut/upsmon.conf
</strong></code></pre>

***Add the following as new lines** to the bottom of the existing file content. Replace `IP_ADDRESS_OF_NUT_SERVER` with the actual internal IP address of your Raspberry Pi. **This defines the actual power monitoring activities and consequent actions upon detecting a power restoration.***&#x20;

```sh
MONITOR nutdev1@IP_ADDRESS_OF_NUT_SERVER 1 monuser secret slave
#"upsmon" and "secret" need to match the contents of the upsd.users set in your NUT server
NOTIFYFLAG ONBATT SYSLOG+EXEC+WALL
NOTIFYCMD /etc/nut/onbatt.sh 
# we will create this shell script later
```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

**Create the `onbatt.sh` shell script** which tells your device to shut down gracefully when it detects that power supply to your UPS has been cut off (e.g., due to a power outage).

{% hint style="info" %}
***Note:** I am using a simple script to handle the automated shutdown sequence because I can't get my NUT to work as intended. Let me know if anyone managed to get yours working.*
{% endhint %}

```sh
sudo nano /etc/nut/onbatt.sh
```

Paste the following content.&#x20;

```sh
#!/bin/bash
# Log the start of the script
logger "NUT: Checking UPS status for ONBATT event"

# Fetch the UPS status; Set to the actual IP Address of your NUT server here
status=$(upsc nutdev1@IP_ADDRESS_OF_NUT_SERVER ups.status)

# Check if the UPS is on battery
if [[ "$status" == "OB" ]]; then
    logger "NUT: UPS on battery power detected. Waiting 120 seconds before shutting down."
    
    # Wait for 120 seconds
    sleep 120
    
    # Log the shutdown initiation
    logger "NUT: Initiating shutdown after 120-second delay."
    sudo /sbin/shutdown -h now "UPS on battery power"
else
    logger "NUT: UPS status is not ONBATT (status: $status). No shutdown triggered."
fi

```

`CTRL+O`, `ENTER`, `CTRL+X` to save and exit.

Make this shell script executable but set proper permissions for security.

```sh
sudo chmod +x /etc/nut/onbatt.sh
sudo chown root:nut /etc/nut/onbatt.sh
sudo chmod 750 /etc/nut/onbatt.sh
```

Allow the nut user to run ***only the*** `/sbin/shutdown` to power down your device without needing the `sudo` (superuser) password.

```sh
sudo visudo
```

Add the following as a new line in the file.

```
nut ALL=(ALL) NOPASSWD: /sbin/shutdown
```

Restart the NUT services.

```sh
sudo service nut-client restart
sudo systemctl restart nut-monitor
sudo systemctl status nut-client nut-monitor
```

### Enable auto-power-on in BIOS (Optional)

{% hint style="info" %}
This is optional as your Raspberry Pi will send a power-on signal to all your devices when power is restored but still good to have as a backup.
{% endhint %}

1. Restart your device and **press** ***F2*** repeatedly during boot to enter BIOS Setup.
2. **Select** `Advanced`, then **select** the `Power menu`.
3. Expand the *`Secondary Power Settings`* sub-menu and set  `After Power Failure` to `Power On`.
4. **Press** ***F10*** to save and exit the BIOS Setup.
