This guide assumes that you have a functioning Oxidized installation. If you don’t you can head over to Part 1 and go back here when finished.

It’s time to connect Oxidized to LibreNMS so it can pull a device list instead of manually defining it in the router.db csv file. The guide below is just a summary of the things that was useful to me in my setup and written as I understood it.

For the latest, and most accurate guide, head over to the LibreNMS Documentation.

Getting an API token

Go to Settings -> API Settings

Then click on the Create API access token, assign it to the appropriate user and take a note of the token.

LibreNMS config

This section is technically optional, although you probably want to read it to know what’s available.

Groups

In some cases you need to authenticate to different types of devices with different set of credentials. For instance, if you are using TACACS for routers/switches, LDAP authentication for loadbalancers and local authentication to a Wifi controller you need groups.

To configure groups we have to this we have to add some lines to the LibreNMS config.php file. Below is a made-up example with a few groups.

# Enable Oxidized support in the LibreNMS GUI
$config['oxidized']['enabled']         = TRUE;

# Tell LibreNMS where to fetch the configuration from 
$config['oxidized']['url']             = 'http://127.0.0.1:8888';

# Enable groups

$config['oxidized']['group_support'] = true;

# Default group
$config['oxidized']['default_group'] = 'Other';

# Recommended if using Git for storing the configuration
$config['oxidized']['features']['versioning'] = true;

# Tell LibreNMS to tell Oxidized to update the device list when new devices has been added
$config['oxidized']['reload_nodes'] = true;

# Add WIFI-CONTROLLER-01 to the group Wifi controllers
$config['oxidized']['maps']['group']['hostname'][] = array('regex' => '/^WIFI-CONTROLLER-01$/i', 'group' => 'WIFI-controllers');

# Add ie. PROD-LB-01 to the group Production-LBs
$config['oxidized']['maps']['group']['hostname'][] = array('regex' => '/^PROD-LB-[0-9]+$/i', 'group' => 'Production-LBs');

# Add anything starting with PROD- to the group Production
$config['oxidized']['maps']['group']['hostname'][] = array('regex' => '/^PROD-/i', 'group' => 'Production');

Worth noting is that group are assigned using first match. So the default catch at the bottom will only assign Production in case the any of the patterns above does not match. If no pattern match the default group is assigned.

Ignore hosts

LibreNMS can omit certain types and OS:es by adding a few lines to the configuration. The example below ignores device of the types server and power and devices with an OS of aruba-instant, apc, hpe-rtups and linux.

$config['oxidized']['ignore_types'] = array('server','power');
$config['oxidized']['ignore_os'] = array('aruba-instant','apc','hpe-rtups','linux');

Verify the configuration

Before you start with the Oxidized configuration it might be a good idea to verify the LibreNMS configuration. You can do this with the help of curl:

curl -H 'X-Auth-Token: YOURAPITOKENHERE' http://localhost:8080/api/v0/oxidized

Note that you need to replace localhost and the port with whatever your LibreNMS instance is listening on. If running this on a vanilla LibreNMS server though the command above should work. Just remember to use your token.

[
    {
        "hostname": "PROD-LB-01",
        "os": "f5",
        "ip": "10.0.0.1",
        "group": "Production-LBs"
    },
    {
        "hostname": "PROD-ROUTER-01",
        "os": "eos",
        "ip": "10.1.1.1",
        "group": "Production"
    }
]

Look through the list and if you’re happy with the result, move on to the Oxidized configuration below.

Oxidized configuration

If you’ve followed Part 1 you should have an Oxidized installation with a functioning GitHub integration.

Groups

This is where we tie the group configuration we did above to a specific set of credentials:

groups:
  WIFI-controllers:
    username: localaccount
    password: supersecretpassword
  Production-LBs:
    username: ldap-user
    password: password
  Production:
    username: tacacs-user
    password: yetanotherpassword

LibreNMS info

First you want to remove the old source configuration. Delete the following lines or prefix each line with # to comment it out:

source:
  default: csv
  csv:
    file: "/root/.config/oxidized/router.db"
    delimiter: !ruby/regexp /:/
    map:
      name: 0
      model: 1
    gpg: false

In order for Oxidized to be able to pull the device list from LibreNMS we need to tell Oxidized where the LibreNMS API is listening and which API token to authenticate with. Below is an example when Oxidized is running on the same machine as LibreNMS. Insert the following lines where your old source used to be:

source:
  default: http
  debug: false
  http:
    url: http://127.0.0.1:8080/api/v0/oxidized
    map:
      name: hostname
      model: os
      group: group
    headers:
      X-Auth-Token: 'YOURTOKEN'

Final configuration

Below is a final configuration example that worked for me:

---
username: xx
password: xx
resolve_dns: true
interval: 7200
use_syslog: false
debug: true
threads: 30
timeout: 20
retries: 3
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
rest: 127.0.0.1:8888
next_adds_job: false
vars:
  auth_methods: ["none", "publickey", "password", "keyboard-interactive"]
  remove_secret: true
  ssh_keys: "/root/.config/oxidized/.ssh/id_rsa.pem"
groups:
  WIFI-controllers:
    username: localaccount
    password: supersecretpassword
  Production-LBs:
    username: ldap-user
    password: password
  Production:
    username: tacacs-user
    password: yetanotherpassword
models: {}
pid: "/root/.config/oxidized/pid"
crash:
  directory: "/root/.config/oxidized/crashes"
  hostnames: false
stats:
  history_size: 10
input:
  default: ssh, telnet
  debug: true
  ssh:
    secure: false
  utf8_encoded: true
output:
  default: git
  file:
    directory: "/root/.config/oxidized/gitrepo"
  git:
    single_repo: true
    user: Oxidized
    email: oxidized@domain.com
    repo: "/root/.config/oxidized/gitrepo/oxidized.git"
hooks:
  push_to_remote:
    type: githubrepo
    events: [post_store]
    remote_repo: "git@github.com:my-repo/oxidized.git"
    publickey: "/root/.config/oxidized/.ssh/id_rsa.pub"
    privatekey: "/root/.config/oxidized/.ssh/id_rsa.pem"
    publickey: "/root/.config/oxidized/.ssh/id_rsa.pub"
    privatekey: "/root/.config/oxidized/.ssh/id_rsa.pem"
source:
  default: http
  debug: false
  http:
    url: http://127.0.0.1:8080/api/v0/oxidized
    map:
      name: hostname
      model: os
      group: group
    headers:
      X-Auth-Token: 'YOURTOKEN'
model_map:
  juniper: junos
  cisco: ios
  f5: tmos
  arista: eos
  fortigate: fortios

Final thoughts

This has been super useful for us as a team. It’s possible to roll back the state of a classic network infrastructure by storing the configuration changes in Git. Of course, doing this with GitOps would be better as it comes with more granularity and audit logging but I reckon this is as close as it gets if not going down that road.

Did the guide help you? Did I miss anything important or make a mistake when writing it? Feel free to leave a comment below.

Related Posts

2 thoughts on “Oxidized – Part 2

  1. How did you protect your oxidized api/web port 8888?
    I am stuck mentally getting this protected with the docker mode and would love to know what you did.

    1. Sorry for the late reply. I guess I didn’t. Ran it with network=host. Suppose one could put them on the same docker network though.

Leave a Reply to darkfader Cancel reply

Your email address will not be published. Required fields are marked *