# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dvt-homestaker.stakesaurus.com/automation-tools/automated-power-on-off/network-ups-tools-nut.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
