• Mac-like copy/paste on Fedora

    2018 is the year of Linux on the desktop—but only for me and only since I started working at a new company where I use Fedora for ~ eight hours daily. Coming from 10+ years of using Macs at work, the biggest change is using Ctrl + C/V for copy/paste and not Cmd + C/V. A couple of weeks in and my hand began to get a slight cramp from using my pinky and index fingers rather than my thumb and index fingers for the operation.

    After reading how to remap keys with xmodmap, the configuration below is what I came up with.

    Once parsed by Xorg, this lines in this file will remap right alt to right super, left alt to right control and left super to left alt.

    $ vi ~/.Xmodmap
    clear control
    clear mod1
    clear mod4
    keycode 133 = Alt_L Meta_L
    keycode 37 = Control_L
    keycode 64 = Control_R
    keycode 108 = Super_R
    add control = Control_L Control_R
    add mod1 = Alt_L Meta_L
    add mod4 = Super_R

    Confirm that this file is in your home directory, logout, log back in, and test. This may break existing shortcuts, so be sure to remap as neccessary under Settings > Keyboard > Application Shortcuts.

  • UPS Monitoring with NUT + Net-SNMP

    Early last year a friend and I started a local, wireless mesh network that eventually evolved into a community-run WISP. The full story of how it came to be is for another post…

    Fast forward many months and we secured some tower space for our radios and some limited rack space for our main networking equipment and servers. The location was just about perfect, but rather inconvenient to service.

    Secret internet lair
    Definition of not accessible

    Needing some reliable—but cheap—backup power for our main router, switch, and small 1U server we settled on the 10-outlet CyberPower 850VA/510W UPS (CP850PFCLCD). It provides reliable, stable output and will run our equipment (and radio) for about 45 minutes in the event the mountain site loses power.

    When I drove up to connect it to our equipment I plugged in the supplied USB Type-B to Type-A cable from the UPS to an empty port on our server—not yet knowing how to query the UPS, or if there was any linux tooling available for our particular device.

    Below are the steps I took to enable quantifiable monitoring of my consumer-grade UPS via open-source tooling on CentOS 7. And, in the footnotes I’ve linked the two pages that helped me succeed in this project.

    Install + configure NUT on CentOS 7

    Throughout this guide I’m using CentOS, but NUT should be available on most distros/package managers.

    Enable EPEL repository and install NUT

    $ sudo yum install epel-release
    $ sudo yum install nut

    Configure NUT driver

    If you’re not using the same UPS, check the NUT hardware compatibility list to see if your equipment is supported by the drivers included with NUT.

    First, run the command below to detect any supported UPS devices, and determine which driver is being used.

    $ sudo nut-scanner -U

    Output wil be similar to:

        driver = "usbhid-ups"
        port = "auto"
        vendorid = "0764"
        productid = "0501"
        product = "CP850PFCLCD"
        serial = "000000000000"
        vendor = "CPS"
        bus = "001"

    Next, let’s configure NUT:

    $ sudo vi /etc/ups/ups.conf

    Append these lines:

        driver = usbhid-ups
            port = auto
            desc = "CyberPower 850"

    Change [cyberpower] to any name you’d like. This value becomes the query name for polling the device. Additionally, driver should reference the output of nut-scanner and desc is entirely optional.

    Let’s start the UPS driver:

    $ sudo upsdrvctl start

    Successful output should resemble:

    Using subdriver: CyberPower HID 0.3

    If you receive any error ensure you have sudo privileges, and try restarting the machine if the problem persists.

    We should also set NUT’s mode to standalone.

    $ sudo vi /etc/ups/nut.conf

    From their documentation:

    standalone: This mode address a local only configuration, with 1 UPS protecting the local system. This implies to start the 3 NUT layer (driver, upsd and upsmon) and the matching configuration files. This mode can also address UPS redundancy.

    Configure NUT server and monitor

    Once the driver is up and running, we need to set up the user for accessing the NUT daemon.

    $ sudo vi /etc/ups/upsd.users


    password = <secretpass>
    upsmon master

    Change <secretpass> to a secure password of your choosing.

    Lastly, we’ll edit the NUT monitor configuration with the name of our device, and the access information for the newly created user.

    $ sudo vi /etc/ups/upsmon.conf

    And append:

    MONITOR cyberpower@localhost 1 local_mon <secretpass> master

    Of course, change cyberpower to the name you gave your device, and <secretpass> to the password you specified in /etc/ups/upsd.users

    Enable services

    To ensure monitoring ability after planned and unplanned reboots, we need to enable and start the NUT system services.

    $ sudo systemctl enable nut-monitor.service
    $ sudo systemctl enable nut-server.service
    $ sudo systemctl start nut-server.service
    $ sudo systemctl start nut-monitor.service

    If you encounter any errors starting the services, restarting may resolve these. Often, running upsdrvctl start as we did earlier hijacks USB communication with the UPS and causes an error when trying to start NUT services.

    Test UPS querying!

    Run (replacing cyberpower with your device name):

    $ upsc cyberpower

    And, if all configurations are happy you will see some data returned:

    battery.charge: 100
    battery.charge.low: 10
    battery.charge.warning: 20
    battery.mfr.date: CPS
    battery.runtime: 2790
    battery.runtime.low: 300
    battery.type: PbAcid
    battery.voltage: 16.0
    battery.voltage.nominal: 24
    device.mfr: CPS
    device.model: CP850PFCLCD
    device.serial: 000000000000
    device.type: ups
    driver.name: usbhid-ups
    driver.parameter.pollfreq: 30
    driver.parameter.pollinterval: 2
    driver.parameter.port: auto
    driver.version: 2.7.2
    driver.version.data: CyberPower HID 0.3
    driver.version.internal: 0.38
    input.transfer.high: 139
    input.transfer.low: 88

    Install Net-SNMP

    $ sudo yum install net-snmp

    Create the script for MIB formatting of the query data:
    Note: this script formats MIBs specifically for LibreNMS.

    $ sudo vi /etc/snmp/ups-nut.sh

    Past the following, making sure to change UPS_NAME to your device name:

    #!/usr/bin/env bash
    TMP=$(upsc $UPS_NAME 2>/dev/null)
    for value in "battery\.charge: [0-9.]+" "battery\.(runtime\.)?low: [0-9]+" "battery\.runtime: [0-9]+" "battery\.voltage: [0-9.]+" "battery\.voltage\.nominal: [0-9]+" "input\.voltage\.nominal: [0-9.]+" "input\.voltage: [0-9.]+" "ups\.load: [0-9.]+"
        OUT=$(echo $TMP | grep -Eo "$value" | awk '{print $2}' | LANG=C sort | head -n 1)
        if [ -n "$OUT" ]; then
            echo $OUT
            echo "Unknown"

    Make the script executable:

    $ sudo chmod +x /etc/snmp/ups-nut.sh

    Now let’s extend this script to the SNMP daemon:

    $ sudo vi /etc/snmp/snmpd.conf

    Append the following and change <community> to your community name:

    rocommunity <community>
    extend ups-nut /etc/snmp/ups-nut.sh

    Let’s enable and start the SNMP daemon:

    $ sudo systemctl enable snmpd
    $ sudo systemctl start snmpd

    And finally, make a test query from a another host that can reach the server:

    $ snmpwalk -v2c -c <community> <host> 'NET-SNMP-EXTEND-MIB::nsExtendOutLine'

    You should see results similar to this:

    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".1 = STRING: 100
    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".2 = STRING: 300
    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".3 = STRING: 2790
    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".4 = STRING: 16.0
    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".5 = STRING: 24
    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".6 = STRING: 120
    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".7 = STRING: 125.0
    NET-SNMP-EXTEND-MIB::nsExtendOutLine."ups-nut".8 = STRING: 14


    Your host can now receive an SNMP query, poll your device with NUT, and respond with MIBs formatted for display/graphing on LibreNMS, Observium, or other SNMP-based monitoring platforms.

    You could also skip SNMP entirely and use a bash or python script to automate the retrieval of the UPS values via the upsc command.

    I hope this helps anyone looking to quantify and monitor the health of their UPS from afar.

    How I display my data

    I use both LibreNMS and Grafana (via LibreNMS + InfluxDB) to display information about my UPS.