From 3a8baa186aa5cdd562854202c567d9f027fcbb93 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:25:04 +0000 Subject: [PATCH] Deploy to GitHub pages --- Developing/os/Health-Information/index.html | 2 +- search/search_index.json | 2 +- sitemap.xml | 260 ++++++++++---------- sitemap.xml.gz | Bin 1425 -> 1424 bytes 4 files changed, 132 insertions(+), 132 deletions(-) diff --git a/Developing/os/Health-Information/index.html b/Developing/os/Health-Information/index.html index e1c21483..e8b8ed22 100644 --- a/Developing/os/Health-Information/index.html +++ b/Developing/os/Health-Information/index.html @@ -12,7 +12,7 @@ num_oid: '.1.3.6.1.4.1.5528.100.4.1.5.1.2.{{ $index }}' descr: '{{ $airFlowSensorLabel }}' index: 'airFlowSensorValue.{{ $index }}' -
At the top you can define one or more mibs to be used in the lookup of data:
mib: NETBOTZV2-MIB
For use of multiple MIB files separate them with a colon: mib: NETBOTZV2-MIB:SECOND-MIB
For data:
you have the following options:
The only sensor we have defined here is airflow. The available options are as follows:
oid
(required): This is the name of the table you want to snmp walk for data.value
(optional): This is the key within the table that contains the value. If not provided will use oid
num_oid
(required for PullRequests): If not provided, this parameter should be computed automatically by discovery process. This parameter is still required to submit a pull request. This is the numerical OID that contains value
. This should usually include {{ $index }}
. In case the index is a string, {{ $index_string }}
can be used instead.divisor
(optional): This is the divisor to use against the returned value
.multiplier
(optional): This is the multiplier to use against the returned value
.low_limit
(optional): This is the critical low threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.low_warn_limit
(optional): This is the warning low threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.warn_limit
(optional): This is the warning high threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.high_limit
(optional): This is the critical high threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.descr
(required): The visible label for this sensor. It can be a key with in the table or a static string, optionally using {{ index }}
.group
(optional): Groups sensors together under in the webui, displaying this text. Not specifying this will put the sensors in the default group.index
(optional): This is the index value we use to uniquely identify this sensor. {{ $index }}
will be replaced by the index
from the snmp walk.skip_values
(optional): This is an array of values we should skip over (see note below).skip_value_lt
(optional): If sensor value is less than this, skip the discovery.skip_value_gt
(optional): If sensor value is greater than this, skip the discovery.entPhysicalIndex
(optional): If the sensor belongs to a physical entity then you can specify the index here.entPhysicalIndex_measured
(optional): If the sensor belongs to a physical entity then you can specify the entity type here.user_func
(optional): You can provide a function name for the sensors value to be processed through (i.e. Convert fahrenheit to celsius use fahrenheit_to_celsius
)snmp_flags
(optional): this sets the flags to be sent to snmpwalk, it overrides flags set on the sensor type and os. The default is '-OQUb'
. A common issue is dealing with string indexes, setting '-OQUsbe'
will change them to numeric oids. Setting ['-OQUsbe', '-Pu']
will also allow _ in oid names. You can find more in the Man Pagerrd_type
(optional): You can change the type of the RRD file that will be created to store the data. By default, type GAUGE is used. More details can be found here: https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.htmlFor options:
you have the following available:
divisor
: This is the divisor to use against the returned value
.multiplier
: This is the multiplier to use against the returned value
.skip_values
: This is an array of values we should skip over (see note below).skip_value_lt
: If sensor value is less than this, skip the discovery.skip_value_gt
: If sensor value is greater than this, skip the discovery.Multiple variables can be used in the sensor's definition. The syntax is {{ $variable }}
. Any oid in the current table can be used, as well as pre_cached data. The index ($index) and the sub_indexes (in case the oid is indexed multiple times) are also available: if $index="1.20", then $subindex0="1" and $subindex1="20".
When referencing an oid in another table the full index will be used to match the other table. If this is undesirable, you may use a single sub index by appending the sub index after a colon to the variable name. Example {{ $ifName:2 }}
skip_values
can also compare items within the OID table against values. The index of the sensor is used to retrieve the value from the OID, unless a target index is appended to the OID. Additionally, you may check fields from the device. Comparisons behave on a logical OR basis when chained, so only one of them needs to be matched for that particular sensor to be skipped during discovery. An example of this is below:
skip_values:
+
At the top you can define one or more mibs to be used in the lookup of data:
mib: NETBOTZV2-MIB
For use of multiple MIB files separate them with a colon: mib: NETBOTZV2-MIB:SECOND-MIB
For data:
you have the following options:
The only sensor we have defined here is airflow. The available options are as follows:
oid
(required): This is the name of the table you want to snmp walk for data.value
(optional): This is the key within the table that contains the value. If not provided will use oid
num_oid
(required for PullRequests): If not provided, this parameter should be computed automatically by discovery process. This parameter is still required to submit a pull request. This is the numerical OID that contains value
. This should usually include {{ $index }}
. In case the index is a string, {{ $index_string }}
can be used instead.divisor
(optional): This is the divisor to use against the returned value
.multiplier
(optional): This is the multiplier to use against the returned value
.low_limit
(optional): This is the critical low threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.low_warn_limit
(optional): This is the warning low threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.warn_limit
(optional): This is the warning high threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.high_limit
(optional): This is the critical high threshold that value
should be (used in alerting). If an OID is specified then divisor / multiplier are used.descr
(required): The visible label for this sensor. It can be a key with in the table or a static string, optionally using {{ index }}
.group
(optional): Groups sensors together under in the webui, displaying this text. Not specifying this will put the sensors in the default group.index
(optional): This is the index value we use to uniquely identify this sensor. {{ $index }}
will be replaced by the index
from the snmp walk.skip_values
(optional): This is an array of values we should skip over (see note below).skip_value_lt
(optional): If sensor value is less than this, skip the discovery.skip_value_gt
(optional): If sensor value is greater than this, skip the discovery.entPhysicalIndex
and entPhysicalIndex_measured
(optional) : If the sensor belongs to a physical entity then you can link them here. The currently supported variants are :entPhysicalIndex
contains the entPhysicalIndex from entPhysical table, and entPhysicalIndex_measured
is NULLentPhysicalIndex
contains "ifIndex" value of the linked port and entPhysicalIndex_measured
contains "ports"user_func
(optional): You can provide a function name for the sensors value to be processed through (i.e. Convert fahrenheit to celsius use fahrenheit_to_celsius
)snmp_flags
(optional): this sets the flags to be sent to snmpwalk, it overrides flags set on the sensor type and os. The default is '-OQUb'
. A common issue is dealing with string indexes, setting '-OQUsbe'
will change them to numeric oids. Setting ['-OQUsbe', '-Pu']
will also allow _ in oid names. You can find more in the Man Pagerrd_type
(optional): You can change the type of the RRD file that will be created to store the data. By default, type GAUGE is used. More details can be found here: https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.htmlFor options:
you have the following available:
divisor
: This is the divisor to use against the returned value
.multiplier
: This is the multiplier to use against the returned value
.skip_values
: This is an array of values we should skip over (see note below).skip_value_lt
: If sensor value is less than this, skip the discovery.skip_value_gt
: If sensor value is greater than this, skip the discovery.Multiple variables can be used in the sensor's definition. The syntax is {{ $variable }}
. Any oid in the current table can be used, as well as pre_cached data. The index ($index) and the sub_indexes (in case the oid is indexed multiple times) are also available: if $index="1.20", then $subindex0="1" and $subindex1="20".
When referencing an oid in another table the full index will be used to match the other table. If this is undesirable, you may use a single sub index by appending the sub index after a colon to the variable name. Example {{ $ifName:2 }}
skip_values
can also compare items within the OID table against values. The index of the sensor is used to retrieve the value from the OID, unless a target index is appended to the OID. Additionally, you may check fields from the device. Comparisons behave on a logical OR basis when chained, so only one of them needs to be matched for that particular sensor to be skipped during discovery. An example of this is below:
skip_values:
-
oid: sensUnit
op: '!='
diff --git a/search/search_index.json b/search/search_index.json
index 719d8e81..a2a0fb5e 100644
--- a/search/search_index.json
+++ b/search/search_index.json
@@ -1 +1 @@
-{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Installing Install LibreNMS Now Install Using Docker Setup Applications Auto Discovery Oxidized RRDCached Alerting Rules Templates Transports More... API Using the API API Endpoints Support FAQ Install validation Performance tweaks More... Developing Getting Started Support for a new OS","title":"Home"},{"location":"API/","text":"Versioning Versioning an API is a minefield which saw us looking at numerous options on how to do this. We have currently settled on using versioning within the API end point itself /api/v0 . As the API itself is new and still in active development we also decided that v0 would be the best starting point to indicate it's in development. Tokens To access any of the token end points you will be required to authenticate using a token. Tokens can be created directly from within the LibreNMS web interface by going to /api-access/ . Click on 'Create API access token'. Select the user you would like to generate the token for. Enter an optional description. Click Create API Token. Endpoints Whilst this documentation will describe and show examples of the end points, we've designed the API so you should be able to traverse through it without knowing any of the available API routes. You can do this by first calling /api/v0 : curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0 Output: { \"list_bgp\" : \"https://librenms.org/api/v0/bgp\" , ... \"edit_rule\" : \"https://librenms.org/api/v0/rules\" } Input Input to the API is done in three different ways, sometimes a combination of two or three of these. Passing parameters via the api route. For example when obtaining a devices details you will pass the hostname of the device in the route: /api/v0/devices/:hostname . Passing parameters via the query string. For example you can list all devices on your install but limit the output to devices that are currently down: /api/v0/devices?type=down Passing data in via JSON, this will mainly be used when adding or updating information via the API, for instance adding a new device: curl -X POST -d '{\"hostname\":\"localhost.localdomain\",\"version\":\"v1\",\"community\":\"public\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices Output Output from the API currently is via two output types: JSON: Most API responses will output json. As shown in the example for calling the API endpoint. PNG: This is for when the request is for an image such as a graph for a switch port. Endpoint Categories Devices DeviceGroups Ports Port_Groups PortGroups Alerts Routing Switching Inventory Bills ARP Services Logs System Locations","title":"Using the API"},{"location":"API/#versioning","text":"Versioning an API is a minefield which saw us looking at numerous options on how to do this. We have currently settled on using versioning within the API end point itself /api/v0 . As the API itself is new and still in active development we also decided that v0 would be the best starting point to indicate it's in development.","title":"Versioning"},{"location":"API/#tokens","text":"To access any of the token end points you will be required to authenticate using a token. Tokens can be created directly from within the LibreNMS web interface by going to /api-access/ . Click on 'Create API access token'. Select the user you would like to generate the token for. Enter an optional description. Click Create API Token.","title":"Tokens"},{"location":"API/#endpoints","text":"Whilst this documentation will describe and show examples of the end points, we've designed the API so you should be able to traverse through it without knowing any of the available API routes. You can do this by first calling /api/v0 : curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0 Output: { \"list_bgp\" : \"https://librenms.org/api/v0/bgp\" , ... \"edit_rule\" : \"https://librenms.org/api/v0/rules\" }","title":"Endpoints"},{"location":"API/#input","text":"Input to the API is done in three different ways, sometimes a combination of two or three of these. Passing parameters via the api route. For example when obtaining a devices details you will pass the hostname of the device in the route: /api/v0/devices/:hostname . Passing parameters via the query string. For example you can list all devices on your install but limit the output to devices that are currently down: /api/v0/devices?type=down Passing data in via JSON, this will mainly be used when adding or updating information via the API, for instance adding a new device: curl -X POST -d '{\"hostname\":\"localhost.localdomain\",\"version\":\"v1\",\"community\":\"public\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices","title":"Input"},{"location":"API/#output","text":"Output from the API currently is via two output types: JSON: Most API responses will output json. As shown in the example for calling the API endpoint. PNG: This is for when the request is for an image such as a graph for a switch port.","title":"Output"},{"location":"API/#endpoint-categories","text":"Devices DeviceGroups Ports Port_Groups PortGroups Alerts Routing Switching Inventory Bills ARP Services Logs System Locations","title":"Endpoint Categories"},{"location":"API/ARP/","text":"list_arp Retrieve a specific ARP entry or all ARP entries for a device Route: /api/v0/resources/ip/arp/:query Query can be: - An IP address - A MAC address - A CIDR network (192.168.1.0/24) - all and set ?device= hostname (or device id) Input: device if you specify all for the query then you need to populate this with the hostname or id of the device. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/arp/1.1.1.1 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/arp/192.168.1.0/24 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/arp/all?device=localhost Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"arp\" : [ { \"port_id\" : \"229\" , \"mac_address\" : \"da160e5c2002\" , \"ipv4_address\" : \"1.1.1.1\" , \"context_name\" : \"\" } ] }","title":"ARP"},{"location":"API/ARP/#list_arp","text":"Retrieve a specific ARP entry or all ARP entries for a device Route: /api/v0/resources/ip/arp/:query Query can be: - An IP address - A MAC address - A CIDR network (192.168.1.0/24) - all and set ?device= hostname (or device id) Input: device if you specify all for the query then you need to populate this with the hostname or id of the device. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/arp/1.1.1.1 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/arp/192.168.1.0/24 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/arp/all?device=localhost Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"arp\" : [ { \"port_id\" : \"229\" , \"mac_address\" : \"da160e5c2002\" , \"ipv4_address\" : \"1.1.1.1\" , \"context_name\" : \"\" } ] }","title":"list_arp"},{"location":"API/Alerts/","text":"get_alert Get details of an alert Route: /api/v0/alerts/:id id is the alert id, you can obtain a list of alert ids from list_alerts . Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 7 , \"alerts\" : [ { \"hostname\" : \"localhost\" , \"id\" : \"1\" , \"device_id\" : \"1\" , \"rule_id\" : \"1\" , \"state\" : \"1\" , \"alerted\" : \"1\" , \"open\" : \"1\" , \"timestamp\" : \"2014-12-11 14:40:02\" }] } ack_alert Acknowledge an alert Route: /api/v0/alerts/:id id is the alert id, you can obtain a list of alert ids from list_alerts . note is the note to add to the alert until_clear is a boolean and if set to false, the alert will re-alert if it worsens/betters. Input: - Example: curl -X PUT -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"message\" : \"Alert has been acknowledged\" } unmute_alert Unmute an alert Route: /api/v0/alerts/unmute/:id id is the alert id, you can obtain a list of alert ids from list_alerts . Input: - Example: curl -X PUT -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts/unmute/1 Output: { \"status\" : \"ok\" , \"message\" : \"Alert has been unmuted\" } list_alerts List all alerts Route: /api/v0/alerts Input: state: Filter the alerts by state, 0 = ok, 1 = alert, 2 = ack severity: Filter the alerts by severity. Valid values are ok , warning , critical . alert_rule: Filter alerts by alert rule ID. order: How to order the output, default is by timestamp (descending). Can be appended by DESC or ASC to change the order. Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?state=1 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?severity=critical curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?order=timestamp%20ASC curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?alert_rule=49 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"alerts\" : [ { \"id\" : \"1\" , \"device_id\" : \"1\" , \"rule_id\" : \"1\" , \"state\" : \"1\" , \"alerted\" : \"1\" , \"open\" : \"1\" , \"timestamp\" : \"2014-12-11 14:40:02\" }] } Rules get_alert_rule Get the alert rule details. Route: /api/v0/rules/:id id is the rule id. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"rules\" : [ { \"id\" : \"1\" , \"device_id\" : \"1\" , \"rule\" : \"%devices.os != \\\"Juniper\\\"\" , \"severity\" : \"warning\" , \"extra\" : \"{\\\"mute\\\":true,\\\"count\\\":\\\"15\\\",\\\"delay\\\":null,\\\"invert\\\":false}\" , \"disabled\" : \"0\" , \"name\" : \"A test rule\" } ] } delete_rule Delete an alert rule by id Route: /api/v0/rules/:id id is the rule id. Input: - Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"message\" : \"Alert rule has been removed\" } list_alert_rules List the alert rules. Route: /api/v0/rules - Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"rules\" : [ { \"id\" : \"1\" , \"device_id\" : \"-1\" , \"rule\" : \"%devices.os != \\\"Juniper\\\"\" , \"severity\" : \"critical\" , \"extra\" : \"{\\\"mute\\\":false,\\\"count\\\":\\\"15\\\",\\\"delay\\\":\\\"300\\\",\\\"invert\\\":false}\" , \"disabled\" : \"0\" , \"name\" : \"A test rule\" }] } add_rule Add a new alert rule. Route: /api/v0/rules - Input (JSON): devices: This is either an array of device ids or -1 for a global rule builder: The rule which should be in the format entity.condition value (i.e devices.status != 0 for devices marked as down). It must be json encoded in the format rules are currently stored. severity: The severity level the alert will be raised against, Ok, Warning, Critical. disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled count: This is how many polling runs before an alert will trigger and the frequency. delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. interval: How often to re-issue notifications while this alert is active,0 means notify once.The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). invert: This would invert the rules check. name: This is the name of the rule and is mandatory. notes: Some informal notes for this rule Example: curl -X POST -d '{\"devices\":[1,2,3], \"name\": \"testrule\", \"builder\":{\"condition\":\"AND\",\"rules\":[{\"id\":\"devices.hostname\",\"field\":\"devices.hostname\",\"type\":\"string\",\"input\":\"text\",\"operator\":\"equal\",\"value\":\"localhost\"}],\"valid\":true},\"severity\": \"critical\",\"count\":15,\"delay\":\"5 m\",\"interval\":\"5 m\",\"mute\":false,\"notes\":\"This a note from the API\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules Output: { \"status\" : \"ok\" } edit_rule Edit an existing alert rule Route: /api/v0/rules - Input (JSON): rule_id: You must specify the rule_id to edit an existing rule, if this is absent then a new rule will be created. devices: This is either an array of device ids or -1 for a global rule builder: The rule which should be in the format entity.condition value (i.e devices.status != 0 for devices marked as down). It must be json encoded in the format rules are currently stored. severity: The severity level the alert will be raised against, Ok, Warning, Critical. disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled count: This is how many polling runs before an alert will trigger and the frequency. delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. interval: How often to re-issue notifications while this alert is active,0 means notify once.The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). invert: This would invert the rules check. name: This is the name of the rule and is mandatory. notes: Some informal notes for this rule Example: curl -X PUT -d '{\"rule_id\":1,\"device_id\":\"-1\", \"name\": \"testrule\", \"builder\":{\"condition\":\"AND\",\"rules\":[{\"id\":\"devices.hostname\",\"field\":\"devices.hostname\",\"type\":\"string\",\"input\":\"text\",\"operator\":\"equal\",\"value\":\"localhost\"}],\"valid\":true},\"severity\": \"critical\",\"count\":15,\"delay\":\"5 m\",\"interval\":\"5 m\",\"mute\":false,\"notes\":\"This a note from the API\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules Output: { \"status\" : \"ok\" }","title":"Alerts"},{"location":"API/Alerts/#get_alert","text":"Get details of an alert Route: /api/v0/alerts/:id id is the alert id, you can obtain a list of alert ids from list_alerts . Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 7 , \"alerts\" : [ { \"hostname\" : \"localhost\" , \"id\" : \"1\" , \"device_id\" : \"1\" , \"rule_id\" : \"1\" , \"state\" : \"1\" , \"alerted\" : \"1\" , \"open\" : \"1\" , \"timestamp\" : \"2014-12-11 14:40:02\" }] }","title":"get_alert"},{"location":"API/Alerts/#ack_alert","text":"Acknowledge an alert Route: /api/v0/alerts/:id id is the alert id, you can obtain a list of alert ids from list_alerts . note is the note to add to the alert until_clear is a boolean and if set to false, the alert will re-alert if it worsens/betters. Input: - Example: curl -X PUT -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"message\" : \"Alert has been acknowledged\" }","title":"ack_alert"},{"location":"API/Alerts/#unmute_alert","text":"Unmute an alert Route: /api/v0/alerts/unmute/:id id is the alert id, you can obtain a list of alert ids from list_alerts . Input: - Example: curl -X PUT -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts/unmute/1 Output: { \"status\" : \"ok\" , \"message\" : \"Alert has been unmuted\" }","title":"unmute_alert"},{"location":"API/Alerts/#list_alerts","text":"List all alerts Route: /api/v0/alerts Input: state: Filter the alerts by state, 0 = ok, 1 = alert, 2 = ack severity: Filter the alerts by severity. Valid values are ok , warning , critical . alert_rule: Filter alerts by alert rule ID. order: How to order the output, default is by timestamp (descending). Can be appended by DESC or ASC to change the order. Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?state=1 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?severity=critical curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?order=timestamp%20ASC curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/alerts?alert_rule=49 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"alerts\" : [ { \"id\" : \"1\" , \"device_id\" : \"1\" , \"rule_id\" : \"1\" , \"state\" : \"1\" , \"alerted\" : \"1\" , \"open\" : \"1\" , \"timestamp\" : \"2014-12-11 14:40:02\" }] }","title":"list_alerts"},{"location":"API/Alerts/#rules","text":"","title":"Rules"},{"location":"API/Alerts/#get_alert_rule","text":"Get the alert rule details. Route: /api/v0/rules/:id id is the rule id. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"rules\" : [ { \"id\" : \"1\" , \"device_id\" : \"1\" , \"rule\" : \"%devices.os != \\\"Juniper\\\"\" , \"severity\" : \"warning\" , \"extra\" : \"{\\\"mute\\\":true,\\\"count\\\":\\\"15\\\",\\\"delay\\\":null,\\\"invert\\\":false}\" , \"disabled\" : \"0\" , \"name\" : \"A test rule\" } ] }","title":"get_alert_rule"},{"location":"API/Alerts/#delete_rule","text":"Delete an alert rule by id Route: /api/v0/rules/:id id is the rule id. Input: - Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules/1 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"message\" : \"Alert rule has been removed\" }","title":"delete_rule"},{"location":"API/Alerts/#list_alert_rules","text":"List the alert rules. Route: /api/v0/rules - Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"rules\" : [ { \"id\" : \"1\" , \"device_id\" : \"-1\" , \"rule\" : \"%devices.os != \\\"Juniper\\\"\" , \"severity\" : \"critical\" , \"extra\" : \"{\\\"mute\\\":false,\\\"count\\\":\\\"15\\\",\\\"delay\\\":\\\"300\\\",\\\"invert\\\":false}\" , \"disabled\" : \"0\" , \"name\" : \"A test rule\" }] }","title":"list_alert_rules"},{"location":"API/Alerts/#add_rule","text":"Add a new alert rule. Route: /api/v0/rules - Input (JSON): devices: This is either an array of device ids or -1 for a global rule builder: The rule which should be in the format entity.condition value (i.e devices.status != 0 for devices marked as down). It must be json encoded in the format rules are currently stored. severity: The severity level the alert will be raised against, Ok, Warning, Critical. disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled count: This is how many polling runs before an alert will trigger and the frequency. delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. interval: How often to re-issue notifications while this alert is active,0 means notify once.The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). invert: This would invert the rules check. name: This is the name of the rule and is mandatory. notes: Some informal notes for this rule Example: curl -X POST -d '{\"devices\":[1,2,3], \"name\": \"testrule\", \"builder\":{\"condition\":\"AND\",\"rules\":[{\"id\":\"devices.hostname\",\"field\":\"devices.hostname\",\"type\":\"string\",\"input\":\"text\",\"operator\":\"equal\",\"value\":\"localhost\"}],\"valid\":true},\"severity\": \"critical\",\"count\":15,\"delay\":\"5 m\",\"interval\":\"5 m\",\"mute\":false,\"notes\":\"This a note from the API\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules Output: { \"status\" : \"ok\" }","title":"add_rule"},{"location":"API/Alerts/#edit_rule","text":"Edit an existing alert rule Route: /api/v0/rules - Input (JSON): rule_id: You must specify the rule_id to edit an existing rule, if this is absent then a new rule will be created. devices: This is either an array of device ids or -1 for a global rule builder: The rule which should be in the format entity.condition value (i.e devices.status != 0 for devices marked as down). It must be json encoded in the format rules are currently stored. severity: The severity level the alert will be raised against, Ok, Warning, Critical. disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled count: This is how many polling runs before an alert will trigger and the frequency. delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. interval: How often to re-issue notifications while this alert is active,0 means notify once.The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). invert: This would invert the rules check. name: This is the name of the rule and is mandatory. notes: Some informal notes for this rule Example: curl -X PUT -d '{\"rule_id\":1,\"device_id\":\"-1\", \"name\": \"testrule\", \"builder\":{\"condition\":\"AND\",\"rules\":[{\"id\":\"devices.hostname\",\"field\":\"devices.hostname\",\"type\":\"string\",\"input\":\"text\",\"operator\":\"equal\",\"value\":\"localhost\"}],\"valid\":true},\"severity\": \"critical\",\"count\":15,\"delay\":\"5 m\",\"interval\":\"5 m\",\"mute\":false,\"notes\":\"This a note from the API\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/rules Output: { \"status\" : \"ok\" }","title":"edit_rule"},{"location":"API/Bills/","text":"list_bills Retrieve the list of bills currently in the system. Route: /api/v0/bills /api/v0/bills?period=previous Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills?period=previous Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"bills\" : [ { \"bill_id\" : \"1\" , \"bill_name\" : \"Router bills\" , \"bill_type\" : \"cdr\" , \"bill_cdr\" : \"10000000\" , \"bill_day\" : \"1\" , \"bill_quota\" : \"0\" , \"rate_95th_in\" : \"0\" , \"rate_95th_out\" : \"0\" , \"rate_95th\" : \"0\" , \"dir_95th\" : \"in\" , \"total_data\" : \"0\" , \"total_data_in\" : \"0\" , \"total_data_out\" : \"0\" , \"rate_average_in\" : \"0\" , \"rate_average_out\" : \"0\" , \"rate_average\" : \"0\" , \"bill_last_calc\" : \"2015-07-02 17:01:26\" , \"bill_custid\" : \"Router\" , \"bill_ref\" : \"Router\" , \"bill_notes\" : \"Bill me\" , \"bill_autoadded\" : \"0\" , \"ports_total\" : \"0\" , \"allowed\" : \"10Mbps\" , \"used\" : \"0bps\" , \"percent\" : 0 , \"overuse\" : \"-\" , \"ports\" : [ { \"device_id\" : \"168\" , \"port_id\" : \"35146\" , \"ifName\" : \"eth0\" } ] } ] } get_bill Retrieve a specific bill Route: /api/v0/bills/:id /api/v0/bills/:id?period=previous /api/v0/bills?ref=:ref /api/v0/bills?ref=:ref&period=previous /api/v0/bills?custid=:custid /api/v0/bills?custid=:custid&period=previous id is the specific bill id ref is the billing reference custid is the customer reference period=previous indicates you would like the data for the last complete period rather than the current period Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills?ref=:customerref curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills?custid=:custid Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"bills\" : [ { \"bill_id\" : \"1\" , \"bill_name\" : \"Router bills\" , \"bill_type\" : \"cdr\" , \"bill_cdr\" : \"10000000\" , \"bill_day\" : \"1\" , \"bill_quota\" : \"0\" , \"rate_95th_in\" : \"0\" , \"rate_95th_out\" : \"0\" , \"rate_95th\" : \"0\" , \"dir_95th\" : \"in\" , \"total_data\" : \"0\" , \"total_data_in\" : \"0\" , \"total_data_out\" : \"0\" , \"rate_average_in\" : \"0\" , \"rate_average_out\" : \"0\" , \"rate_average\" : \"0\" , \"bill_last_calc\" : \"2015-07-02 17:01:26\" , \"bill_custid\" : \"Router\" , \"bill_ref\" : \"Router\" , \"bill_notes\" : \"Bill me\" , \"bill_autoadded\" : \"0\" , \"ports_total\" : \"0\" , \"allowed\" : \"10Mbps\" , \"used\" : \"0bps\" , \"percent\" : 0 , \"overuse\" : \"-\" , \"ports\" : [ { \"device_id\" : \"168\" , \"port_id\" : \"35146\" , \"ifName\" : \"eth0\" } ] } ] } get_bill_graph Retrieve a graph image associated with a bill. NB: The graphs returned from this will always be png as they do not come from rrdtool, even if you have SVG set. Route: `/api/v0/bills/:id/graphs/:graph_type Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/bits?from=1517443200 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/bits?from=1517443200&to=1517788800 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/monthly Output: Graph Image get_bill_graphdata Retrieve the data used to draw a graph so it can be rendered in an external system Route: /api/v0/bills/:id/graphdata/:graph_type Input: The reducefactor parameter is used to reduce the number of data points. Billing data has 5 minute granularity, so requesting a graph for a long time period will result in many data points. If not supplied, it will be automatically calculated. A reducefactor of 1 means return all items, 2 means half of the items etc. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits?from=1517443200 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits?from=1517443200&to=1517788800 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits?from=1517443200&to=1517788800&reducefactor=5 Output: { \"status\": \"ok\", \"graph_data\": { \"from\": \"1517443200\", \"to\": 1518196161, \"last\": \"1518195901\", \"in_data\": [ 103190525.20999999, 104949255.81 ], \"out_data\": [ 1102059.1299999999, 1079216.46 ], \"tot_data\": [ 104292584.33999999, 106028472.27 ], \"ticks\": [ \"1517750401\", \"1517756101\" ], \"rate_95th\": \"251880417\", \"rate_average\": \"146575554\", \"bill_type\": \"cdr\", \"max_in\": 9888289942, \"max_out\": 75848756, \"ave_in\": 18029660.242105871, \"ave_out\": 196447.38060137472, \"last_in\": 3790227.9500000002, \"last_out\": 122731.63333333333 } } get_bill_history Retrieve the history of specific bill Route: /api/v0/bills/:id/history Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history Output: { \"status\" : \"ok\" , \"bill_history\" : [ { \"bill_hist_id\" : \"1\" , \"bill_id\" : \"1\" , \"updated\" : \"2018-02-06 17:01:01\" , \"bill_datefrom\" : \"2018-02-01 00:00:00\" , \"bill_dateto\" : \"2018-02-28 23:59:59\" , \"bill_type\" : \"CDR\" , \"bill_allowed\" : \"100000000\" , \"bill_used\" : \"229963765\" , \"bill_overuse\" : \"129963765\" , \"bill_percent\" : \"229.96\" , \"rate_95th_in\" : \"229963765\" , \"rate_95th_out\" : \"1891344\" , \"rate_95th\" : \"229963765\" , \"dir_95th\" : \"in\" , \"rate_average\" : \"136527101\" , \"rate_average_in\" : \"135123359\" , \"rate_average_out\" : \"1403743\" , \"traf_in\" : \"3235123452544\" , \"traf_out\" : \"33608406566\" , \"traf_total\" : \"3268731859110\" , \"bill_peak_out\" : \"2782349290\" , \"bill_peak_in\" : \"10161119\" , \"pdf\" : null } ], \"count\" : 1 , } get_bill_history_graph Retrieve a graph of a previous period of a bill NB: The graphs returned from this will always be png as they do not come from rrdtool, even if you have SVG set. Route: /api/v0/bills/:id/history/:bill_hist_id/graphs/:graph_type Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphs/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphs/hour curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphs/day Output: (image) get_bill_history_graphdata Retrieve the data for a graph of a previous period of a bill, to be rendered in an external system Route: /api/v0/bills/:id/history/:bill_hist_id/graphdata/:graph_type Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphdata/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphdata/hour curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphdata/day Output: delete_bill Delete a specific bill and all dependent data Route: /api/v0/bills/:id id is the specific bill id Input: Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1 Output: { \"status\" : \"ok\" , \"message\" : \"Bill has been removed\" } create_edit_bill Creates a new bill or updates an existing one Route: /api/v0/bills Method: POST If you send an existing bill_id the call replaces all values it receives. For example if you send 2 ports it will delete the existing ports and add the the 2 new ports. So to add ports you have to get the current ports first and add them to your update call. Input: Example (create): curl -X POST -d '{\"ports\":[ 1021 ],\"bill_name\":\"NEWBILL\",\"bill_day\":\"1\",\"bill_type\":\"quota\",\"bill_quota\":\"2000000000000\",\"bill_custid\":\"1337\",\"bill_ref\":\"reference1\",\"bill_notes\":\"mynote\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills Example (set): curl -X POST -d '{\"bill_id\":\"32\",\"ports\":[ 1021 ],\"bill_name\":\"NEWNAME\",\"bill_quota\":\"1000000000000\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills Output: { \"status\" : \"ok\" , \"bill_id\" : 32 }","title":"Bills"},{"location":"API/Bills/#list_bills","text":"Retrieve the list of bills currently in the system. Route: /api/v0/bills /api/v0/bills?period=previous Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills?period=previous Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"bills\" : [ { \"bill_id\" : \"1\" , \"bill_name\" : \"Router bills\" , \"bill_type\" : \"cdr\" , \"bill_cdr\" : \"10000000\" , \"bill_day\" : \"1\" , \"bill_quota\" : \"0\" , \"rate_95th_in\" : \"0\" , \"rate_95th_out\" : \"0\" , \"rate_95th\" : \"0\" , \"dir_95th\" : \"in\" , \"total_data\" : \"0\" , \"total_data_in\" : \"0\" , \"total_data_out\" : \"0\" , \"rate_average_in\" : \"0\" , \"rate_average_out\" : \"0\" , \"rate_average\" : \"0\" , \"bill_last_calc\" : \"2015-07-02 17:01:26\" , \"bill_custid\" : \"Router\" , \"bill_ref\" : \"Router\" , \"bill_notes\" : \"Bill me\" , \"bill_autoadded\" : \"0\" , \"ports_total\" : \"0\" , \"allowed\" : \"10Mbps\" , \"used\" : \"0bps\" , \"percent\" : 0 , \"overuse\" : \"-\" , \"ports\" : [ { \"device_id\" : \"168\" , \"port_id\" : \"35146\" , \"ifName\" : \"eth0\" } ] } ] }","title":"list_bills"},{"location":"API/Bills/#get_bill","text":"Retrieve a specific bill Route: /api/v0/bills/:id /api/v0/bills/:id?period=previous /api/v0/bills?ref=:ref /api/v0/bills?ref=:ref&period=previous /api/v0/bills?custid=:custid /api/v0/bills?custid=:custid&period=previous id is the specific bill id ref is the billing reference custid is the customer reference period=previous indicates you would like the data for the last complete period rather than the current period Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills?ref=:customerref curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills?custid=:custid Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"bills\" : [ { \"bill_id\" : \"1\" , \"bill_name\" : \"Router bills\" , \"bill_type\" : \"cdr\" , \"bill_cdr\" : \"10000000\" , \"bill_day\" : \"1\" , \"bill_quota\" : \"0\" , \"rate_95th_in\" : \"0\" , \"rate_95th_out\" : \"0\" , \"rate_95th\" : \"0\" , \"dir_95th\" : \"in\" , \"total_data\" : \"0\" , \"total_data_in\" : \"0\" , \"total_data_out\" : \"0\" , \"rate_average_in\" : \"0\" , \"rate_average_out\" : \"0\" , \"rate_average\" : \"0\" , \"bill_last_calc\" : \"2015-07-02 17:01:26\" , \"bill_custid\" : \"Router\" , \"bill_ref\" : \"Router\" , \"bill_notes\" : \"Bill me\" , \"bill_autoadded\" : \"0\" , \"ports_total\" : \"0\" , \"allowed\" : \"10Mbps\" , \"used\" : \"0bps\" , \"percent\" : 0 , \"overuse\" : \"-\" , \"ports\" : [ { \"device_id\" : \"168\" , \"port_id\" : \"35146\" , \"ifName\" : \"eth0\" } ] } ] }","title":"get_bill"},{"location":"API/Bills/#get_bill_graph","text":"Retrieve a graph image associated with a bill. NB: The graphs returned from this will always be png as they do not come from rrdtool, even if you have SVG set. Route: `/api/v0/bills/:id/graphs/:graph_type Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/bits?from=1517443200 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/bits?from=1517443200&to=1517788800 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphs/monthly Output: Graph Image","title":"get_bill_graph"},{"location":"API/Bills/#get_bill_graphdata","text":"Retrieve the data used to draw a graph so it can be rendered in an external system Route: /api/v0/bills/:id/graphdata/:graph_type Input: The reducefactor parameter is used to reduce the number of data points. Billing data has 5 minute granularity, so requesting a graph for a long time period will result in many data points. If not supplied, it will be automatically calculated. A reducefactor of 1 means return all items, 2 means half of the items etc. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits?from=1517443200 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits?from=1517443200&to=1517788800 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/graphdata/bits?from=1517443200&to=1517788800&reducefactor=5 Output: { \"status\": \"ok\", \"graph_data\": { \"from\": \"1517443200\", \"to\": 1518196161, \"last\": \"1518195901\", \"in_data\": [ 103190525.20999999, 104949255.81 ], \"out_data\": [ 1102059.1299999999, 1079216.46 ], \"tot_data\": [ 104292584.33999999, 106028472.27 ], \"ticks\": [ \"1517750401\", \"1517756101\" ], \"rate_95th\": \"251880417\", \"rate_average\": \"146575554\", \"bill_type\": \"cdr\", \"max_in\": 9888289942, \"max_out\": 75848756, \"ave_in\": 18029660.242105871, \"ave_out\": 196447.38060137472, \"last_in\": 3790227.9500000002, \"last_out\": 122731.63333333333 } }","title":"get_bill_graphdata"},{"location":"API/Bills/#get_bill_history","text":"Retrieve the history of specific bill Route: /api/v0/bills/:id/history Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history Output: { \"status\" : \"ok\" , \"bill_history\" : [ { \"bill_hist_id\" : \"1\" , \"bill_id\" : \"1\" , \"updated\" : \"2018-02-06 17:01:01\" , \"bill_datefrom\" : \"2018-02-01 00:00:00\" , \"bill_dateto\" : \"2018-02-28 23:59:59\" , \"bill_type\" : \"CDR\" , \"bill_allowed\" : \"100000000\" , \"bill_used\" : \"229963765\" , \"bill_overuse\" : \"129963765\" , \"bill_percent\" : \"229.96\" , \"rate_95th_in\" : \"229963765\" , \"rate_95th_out\" : \"1891344\" , \"rate_95th\" : \"229963765\" , \"dir_95th\" : \"in\" , \"rate_average\" : \"136527101\" , \"rate_average_in\" : \"135123359\" , \"rate_average_out\" : \"1403743\" , \"traf_in\" : \"3235123452544\" , \"traf_out\" : \"33608406566\" , \"traf_total\" : \"3268731859110\" , \"bill_peak_out\" : \"2782349290\" , \"bill_peak_in\" : \"10161119\" , \"pdf\" : null } ], \"count\" : 1 , }","title":"get_bill_history"},{"location":"API/Bills/#get_bill_history_graph","text":"Retrieve a graph of a previous period of a bill NB: The graphs returned from this will always be png as they do not come from rrdtool, even if you have SVG set. Route: /api/v0/bills/:id/history/:bill_hist_id/graphs/:graph_type Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphs/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphs/hour curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphs/day Output: (image)","title":"get_bill_history_graph"},{"location":"API/Bills/#get_bill_history_graphdata","text":"Retrieve the data for a graph of a previous period of a bill, to be rendered in an external system Route: /api/v0/bills/:id/history/:bill_hist_id/graphdata/:graph_type Input: Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphdata/bits curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphdata/hour curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1/history/1/graphdata/day Output:","title":"get_bill_history_graphdata"},{"location":"API/Bills/#delete_bill","text":"Delete a specific bill and all dependent data Route: /api/v0/bills/:id id is the specific bill id Input: Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills/1 Output: { \"status\" : \"ok\" , \"message\" : \"Bill has been removed\" }","title":"delete_bill"},{"location":"API/Bills/#create_edit_bill","text":"Creates a new bill or updates an existing one Route: /api/v0/bills Method: POST If you send an existing bill_id the call replaces all values it receives. For example if you send 2 ports it will delete the existing ports and add the the 2 new ports. So to add ports you have to get the current ports first and add them to your update call. Input: Example (create): curl -X POST -d '{\"ports\":[ 1021 ],\"bill_name\":\"NEWBILL\",\"bill_day\":\"1\",\"bill_type\":\"quota\",\"bill_quota\":\"2000000000000\",\"bill_custid\":\"1337\",\"bill_ref\":\"reference1\",\"bill_notes\":\"mynote\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills Example (set): curl -X POST -d '{\"bill_id\":\"32\",\"ports\":[ 1021 ],\"bill_name\":\"NEWNAME\",\"bill_quota\":\"1000000000000\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bills Output: { \"status\" : \"ok\" , \"bill_id\" : 32 }","title":"create_edit_bill"},{"location":"API/DeviceGroups/","text":"get_devicegroups List all device groups. Route: /api/v0/devicegroups Input (JSON): - Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devicegroups Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 1 device groups\" , \"count\" : 1 , \"groups\" : [ { \"id\" : \"1\" , \"name\" : \"Testing\" , \"desc\" : \"Testing\" , \"pattern\" : \"%devices.status = \\\"1\\\" &&\" } ] } ] add_devicegroup Add a new device group. Upon success, the ID of the new device group is returned and the HTTP response code is 201 . Route: /api/v0/devicegroups Input (JSON): name : required - The name of the device group type : required - should be static or dynamic . Setting this to static requires that the devices input be provided desc : optional - Description of the device group rules : required if type == dynamic - A set of rules to determine which devices should be included in this device group devices : required if type == static - A list of devices that should be included in this group. This is a static list of devices Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups \\ --data-raw ' { \"name\": \"New Device Group\", \"desc\": \"A very fancy dynamic group\", \"type\": \"dynamic\", \"rules\": \"{\\\"condition\\\":\\\"AND\\\",\\\"rules\\\":[{\\\"id\\\":\\\"access_points.name\\\",\\\"field\\\":\\\"access_points.name\\\",\\\"type\\\":\\\"string\\\",\\\"input\\\":\\\"text\\\",\\\"operator\\\":\\\"equal\\\",\\\"value\\\":\\\"accesspoint1\\\"}],\\\"valid\\\":true}\" } ' Output: { \"status\" : \"ok\" , \"id\" : 86 , \"message\" : \"Device group New Device Group created\" } Static Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups \\ -d '{\"name\":\"New Device Group\",\"type\":\"static\",\"devices\":[261,271]}' Output: { \"status\" : \"ok\" , \"id\" : 86 , \"message\" : \"Device group New Device Group created\" } update_devicegroup Updates a device group. Route: /api/v0/devicegroups/:name name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): name : optional - The name of the device group type : optional - should be static or dynamic . Setting this to static requires that the devices input be provided desc : optional - Description of the device group rules : required if type == dynamic - A set of rules to determine which devices should be included in this device group devices : required if type == static - A list of devices that should be included in this group. This is a static list of devices Examples: curl -X PATCH -d '{\"name\": \"NewLinuxServers\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/LinuxServers Output: { \"status\" : \"ok\" , \"message\" : \"Device group LinuxServers updated\" } delete_devicegroup Deletes a device group. Route: /api/v0/devicegroups/:name name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input: - Examples: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/LinuxServers Output: { \"status\" : \"ok\" , \"message\" : \"Device group LinuxServers deleted\" } get_devices_by_group List all devices matching the group provided. Route: /api/v0/devicegroups/:name name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): full: set to any value to return all data for the devices in a given group Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devicegroups/LinuxServers Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 3 in group LinuxServers\" , \"count\" : 3 , \"devices\" : [ { \"device_id\" : \"15\" }, { \"device_id\" : \"18\" }, { \"device_id\" : \"20\" } ] } ] maintenance_devicegroup Set a device group into maintenance mode. Route: /api/v0/devicesgroups/:name/maintenance Input (JSON): title : optional - Some title for the Maintenance Will be replaced with device group name if omitted notes : optional - Some description for the Maintenance start : optional - start time of Maintenance in full format Y-m-d H:i:00 eg: 2022-08-01 22:45:00 Current system time now() will be used if omitted duration : required - Duration of Maintenance in format H:i / Hrs:Mins eg: 02:00 Example with start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups/Cisco%20switches/maintenance/ \\ --data-raw ' { \"title\":\"Device group Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with start time\", \"start\":\"2022-08-01 08:00:00\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device group Cisco switches (2) will begin maintenance mode at 2022-08-01 22:45:00 for 2:00h\" } Example with no start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups/Cisco%20switches/maintenance/ \\ --data-raw ' { \"title\":\"Device group Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with no start time\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device group Cisco switches (2) moved into maintenance mode for 2:00h\" } Add devices to group Add devices to a device group. Route: /api/v0/devicesgroups/:name/devices name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): devices : required - A list of devices to be added to the group. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups/devices \\ --data-raw '{\"devices\":[261,271]}' Output: { \"status\" : \"ok\" , \"message\" : \"Devices added\" } Remove devices from group Removes devices from a device group. Route: /api/v0/devicesgroups/:name/devices name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): devices : required - A list of devices to be removed from the group. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X DELETE https://librenms.org/api/v0/devicegroups/devices \\ --data-raw '{\"devices\":[261,271]}' Output: { \"status\" : \"ok\" , \"message\" : \"Devices removed\" }","title":"DeviceGroups"},{"location":"API/DeviceGroups/#get_devicegroups","text":"List all device groups. Route: /api/v0/devicegroups Input (JSON): - Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devicegroups Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 1 device groups\" , \"count\" : 1 , \"groups\" : [ { \"id\" : \"1\" , \"name\" : \"Testing\" , \"desc\" : \"Testing\" , \"pattern\" : \"%devices.status = \\\"1\\\" &&\" } ] } ]","title":"get_devicegroups"},{"location":"API/DeviceGroups/#add_devicegroup","text":"Add a new device group. Upon success, the ID of the new device group is returned and the HTTP response code is 201 . Route: /api/v0/devicegroups Input (JSON): name : required - The name of the device group type : required - should be static or dynamic . Setting this to static requires that the devices input be provided desc : optional - Description of the device group rules : required if type == dynamic - A set of rules to determine which devices should be included in this device group devices : required if type == static - A list of devices that should be included in this group. This is a static list of devices Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups \\ --data-raw ' { \"name\": \"New Device Group\", \"desc\": \"A very fancy dynamic group\", \"type\": \"dynamic\", \"rules\": \"{\\\"condition\\\":\\\"AND\\\",\\\"rules\\\":[{\\\"id\\\":\\\"access_points.name\\\",\\\"field\\\":\\\"access_points.name\\\",\\\"type\\\":\\\"string\\\",\\\"input\\\":\\\"text\\\",\\\"operator\\\":\\\"equal\\\",\\\"value\\\":\\\"accesspoint1\\\"}],\\\"valid\\\":true}\" } ' Output: { \"status\" : \"ok\" , \"id\" : 86 , \"message\" : \"Device group New Device Group created\" } Static Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups \\ -d '{\"name\":\"New Device Group\",\"type\":\"static\",\"devices\":[261,271]}' Output: { \"status\" : \"ok\" , \"id\" : 86 , \"message\" : \"Device group New Device Group created\" }","title":"add_devicegroup"},{"location":"API/DeviceGroups/#update_devicegroup","text":"Updates a device group. Route: /api/v0/devicegroups/:name name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): name : optional - The name of the device group type : optional - should be static or dynamic . Setting this to static requires that the devices input be provided desc : optional - Description of the device group rules : required if type == dynamic - A set of rules to determine which devices should be included in this device group devices : required if type == static - A list of devices that should be included in this group. This is a static list of devices Examples: curl -X PATCH -d '{\"name\": \"NewLinuxServers\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/LinuxServers Output: { \"status\" : \"ok\" , \"message\" : \"Device group LinuxServers updated\" }","title":"update_devicegroup"},{"location":"API/DeviceGroups/#delete_devicegroup","text":"Deletes a device group. Route: /api/v0/devicegroups/:name name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input: - Examples: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/LinuxServers Output: { \"status\" : \"ok\" , \"message\" : \"Device group LinuxServers deleted\" }","title":"delete_devicegroup"},{"location":"API/DeviceGroups/#get_devices_by_group","text":"List all devices matching the group provided. Route: /api/v0/devicegroups/:name name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): full: set to any value to return all data for the devices in a given group Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devicegroups/LinuxServers Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 3 in group LinuxServers\" , \"count\" : 3 , \"devices\" : [ { \"device_id\" : \"15\" }, { \"device_id\" : \"18\" }, { \"device_id\" : \"20\" } ] } ]","title":"get_devices_by_group"},{"location":"API/DeviceGroups/#maintenance_devicegroup","text":"Set a device group into maintenance mode. Route: /api/v0/devicesgroups/:name/maintenance Input (JSON): title : optional - Some title for the Maintenance Will be replaced with device group name if omitted notes : optional - Some description for the Maintenance start : optional - start time of Maintenance in full format Y-m-d H:i:00 eg: 2022-08-01 22:45:00 Current system time now() will be used if omitted duration : required - Duration of Maintenance in format H:i / Hrs:Mins eg: 02:00 Example with start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups/Cisco%20switches/maintenance/ \\ --data-raw ' { \"title\":\"Device group Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with start time\", \"start\":\"2022-08-01 08:00:00\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device group Cisco switches (2) will begin maintenance mode at 2022-08-01 22:45:00 for 2:00h\" } Example with no start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups/Cisco%20switches/maintenance/ \\ --data-raw ' { \"title\":\"Device group Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with no start time\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device group Cisco switches (2) moved into maintenance mode for 2:00h\" }","title":"maintenance_devicegroup"},{"location":"API/DeviceGroups/#add-devices-to-group","text":"Add devices to a device group. Route: /api/v0/devicesgroups/:name/devices name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): devices : required - A list of devices to be added to the group. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devicegroups/devices \\ --data-raw '{\"devices\":[261,271]}' Output: { \"status\" : \"ok\" , \"message\" : \"Devices added\" }","title":"Add devices to group"},{"location":"API/DeviceGroups/#remove-devices-from-group","text":"Removes devices from a device group. Route: /api/v0/devicesgroups/:name/devices name Is the name of the device group which can be obtained using get_devicegroups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): devices : required - A list of devices to be removed from the group. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X DELETE https://librenms.org/api/v0/devicegroups/devices \\ --data-raw '{\"devices\":[261,271]}' Output: { \"status\" : \"ok\" , \"message\" : \"Devices removed\" }","title":"Remove devices from group"},{"location":"API/Devices/","text":"del_device Delete a given device. Route: /api/v0/devices/:hostname hostname can be either the device hostname or id Input: - Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: { \"status\" : \"ok\" , \"message\" : \"Removed device localhost\" , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] } get_device Get details of a given device. Route: /api/v0/devices/:hostname hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: { \"status\" : \"ok\" , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] } discover_device Trigger a discovery of given device. Route: /api/v0/devices/:hostname/discover hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/discover Output: { \"status\" : \"ok\" , \"result\" : { \"status\" : 0 , \"message\" : \"Device will be rediscovered\" }, \"count\" : 2 } availability Get calculated availabilities of given device. Route: /api/v0/devices/:hostname/availability hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/availability Output: { \"status\" : \"ok\" , \"availability\" : [ { \"duration\" : 86400 , \"availability_perc\" : \"100.000000\" }, { \"duration\" : 604800 , \"availability_perc\" : \"100.000000\" }, { \"duration\" : 2592000 , \"availability_perc\" : \"99.946000\" }, { \"duration\" : 31536000 , \"availability_perc\" : \"99.994000\" } ], \"count\" : 4 } outages Get detected outages of given device. Route: /api/v0/devices/:hostname/outages hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/outages Output: { \"status\" : \"ok\" , \"outages\" : [ { \"going_down\" : 1593194031 , \"up_again\" : 1593194388 }, { \"going_down\" : 1593946507 , \"up_again\" : 1593946863 }, { \"going_down\" : 1594628616 , \"up_again\" : 1594628968 }, { \"going_down\" : 1594628974 , \"up_again\" : 1594629339 }, { \"going_down\" : 1594638668 , \"up_again\" : 1594638992 } ], \"count\" : 5 } get_graphs Get a list of available graphs for a device, this does not include ports. Route: /api/v0/devices/:hostname/graphs hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 3 , \"graphs\" : [ { \"desc\" : \"Poller Time\" , \"name\" : \"device_poller_perf\" }, { \"desc\" : \"Ping Response\" , \"name\" : \"device_ping_perf\" }, { \"desc\" : \"System Uptime\" , \"name\" : \"uptime\" } ] } list_available_health_graphs This function allows to do three things: Get a list of overall health graphs available. Get a list of health graphs based on provided class. Get the health sensors information based on ID. Route: /api/v0/devices/:hostname/health(/:type)(/:sensor_id) hostname can be either the device hostname or id type (optional) is health type / sensor class sensor_id (optional) is the sensor id to retrieve specific information. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health Output: { \"status\": \"ok\", \"message\": \"\", \"count\": 2, \"graphs\": [ { \"desc\": \"Airflow\", \"name\": \"device_airflow\" }, { \"desc\": \"Voltage\", \"name\": \"device_voltage\" } ] } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health/device_voltage Output: { \"status\": \"ok\", \"message\": \"\", \"count\": 2, \"graphs\": [ { \"sensor_id\": \"1\", \"desc\": \"Input Feed A\" }, { \"sensor_id\": \"2\", \"desc\": \"Output Feed\" } ] } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health/device_voltage/1 Output: { \"status\": \"ok\", \"message\": \"\", \"count\": 1, \"graphs\": [ { \"sensor_id\": \"1\", \"sensor_deleted\": \"0\", \"sensor_class\": \"voltage\", \"device_id\": \"1\", \"poller_type\": \"snmp\", \"sensor_oid\": \".1.3.6.1.4.1.318.1.1.27.1.1.0\", \"sensor_index\": \"1\", \"sensor_type\": \"apc\", \"sensor_descr\": \"Input\", \"sensor_divisor\": \"1\", \"sensor_multiplier\": \"1\", \"sensor_current\": \"1\", \"sensor_limit\": \"1.15\", \"sensor_limit_warn\": null, \"sensor_limit_low\": \"0.85\", \"sensor_limit_low_warn\": null, \"sensor_alert\": \"1\", \"sensor_custom\": \"No\", \"entPhysicalIndex\": null, \"entPhysicalIndex_measured\": null, \"lastupdate\": \"2017-01-13 13:50:26\", \"sensor_prev\": \"1\" } ] } list_available_wireless_graphs This function allows to do three things: Get a list of overall wireless graphs available. Get a list of wireless graphs based on provided class. Get the wireless sensors information based on ID. Route: /api/v0/devices/:hostname/wireless(/:type)(/:sensor_id) hostname can be either the device hostname or id type (optional) is wireless type / wireless class sensor_id (optional) is the sensor id to retrieve specific information. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/wireless Output: { \"status\": \"ok\", \"graphs\": [ { \"desc\": \"Ccq\", \"name\": \"device_wireless_ccq\" }, { \"desc\": \"Clients\", \"name\": \"device_wireless_clients\" } ], \"count\": 2 } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/wireless/device_wireless_ccq Output: { \"status\": \"ok\", \"graphs\": [ { \"sensor_id\": \"791\", \"desc\": \"SSID: bast (ng)\" }, { \"sensor_id\": \"792\", \"desc\": \"SSID: bast (na)\" } ], \"count\": 2 } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health/device_wireless_ccq/1 Output: { \"status\": \"ok\", \"graphs\": [ { \"sensor_id\": \"791\", \"sensor_deleted\": \"0\", \"sensor_class\": \"ccq\", \"device_id\": \"381\", \"sensor_index\": \"0\", \"sensor_type\": \"unifi\", \"sensor_descr\": \"SSID: bast (ng)\", \"sensor_divisor\": \"10\", \"sensor_multiplier\": \"1\", \"sensor_aggregator\": \"sum\", \"sensor_current\": \"100\", \"sensor_prev\": \"100\", \"sensor_limit\": null, \"sensor_limit_warn\": null, \"sensor_limit_low\": null, \"sensor_limit_low_warn\": null, \"sensor_alert\": \"1\", \"sensor_custom\": \"No\", \"entPhysicalIndex\": null, \"entPhysicalIndex_measured\": null, \"lastupdate\": \"2017-12-06 21:26:29\", \"sensor_oids\": \"[\\\".1.3.6.1.4.1.41112.1.6.1.2.1.3.0\\\"]\", \"access_point_id\": null } ], \"count\": 1 } get_health_graph Get a particular health class graph for a device, if you provide a sensor_id as well then a single sensor graph will be provided. If no sensor_id value is provided then you will be sent a stacked sensor graph. Route: /api/v0/devices/:hostname/graphs/health/:type(/:sensor_id) hostname can be either the device hostname or id type is the name of the health graph as returned by list_available_health_graphs sensor_id (optional) restricts the graph to return a particular health sensor graph. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/health/device_voltage Output: Output is a stacked graph for the health type provided. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/health/device_voltage/1 Output: Output is the graph of the particular health type sensor provided. get_wireless_graph Get a particular wireless class graph for a device, if you provide a sensor_id as well then a single sensor graph will be provided. If no sensor_id value is provided then you will be sent a stacked wireless graph. Route: /api/v0/devices/:hostname/graphs/wireless/:type(/:sensor_id) hostname can be either the device hostname or id type is the name of the wireless graph as returned by list_available_wireless_graphs sensor_id (optional) restricts the graph to return a particular wireless sensor graph. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/wireless/device_wireless_ccq Output: Output is a stacked graph for the wireless type provided. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/wireless/device_wireless_ccq/1 Output: Output is the graph of the particular wireless type sensor provided. get_graph_generic_by_hostname Get a specific graph for a device, this does not include ports. Route: /api/v0/devices/:hostname/:type hostname can be either the device hostname or id type is the type of graph you want, use [ get_graphs ](#function-get_graphs to see the graphs available. Defaults to device uptime. Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. output: Set how the graph should be outputted (base64, display), defaults to display. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/device_poller_perf Output: Output is an image. get_graph_by_service Get the graph for a service Route: /api/v0/devices/:hostname/services/:service_id/graphs/:datasource hostname can be either the device hostname or id service id datasource is the name of the service datasource Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/localhost/35/graphs/loss Output: Output is an image. get_port_graphs Get a list of ports for a particular device. Route: /api/v0/devices/:hostname/ports hostname can be either the device hostname or id Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ports Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 3 , \"ports\" : [ { \"ifName\" : \"lo\" }, { \"ifName\" : \"eth0\" }, { \"ifName\" : \"eth1\" } ] } get_device_fdb Get a list of FDB entries associated with a device. Route: /api/v0/devices/:hostname/fdb hostname can be either the device hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/fdb Output: { \"status\" : \"ok\" , \"ports_fdb\" : { \"ports_fdb_id\" : 10 , \"port_id\" : 10000 , \"mac_address\" : \"1aaa2bbb3ccc\" , \"vlan_id\" : 20000 , \"device_id\" : 1 , \"created_at\" : \"2019-01-1 01:01:01\" , \"updated_at\" : \"2019-01-1 01:01:01\" } } get_device_ip_addresses Get a list of IP addresses (v4 and v6) associated with a device. Route: /api/v0/devices/:hostname/ip hostname can be either the device hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ip Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"addresses\" : [ { \"ipv4_address_id\" : \"290\" , \"ipv4_address\" : \"192.168.99.292\" , \"ipv4_prefixlen\" : \"30\" , \"ipv4_network_id\" : \"247\" , \"port_id\" : \"323\" , \"context_name\" : \"\" } ] } get_port_stack Get a list of port mappings for a device. This is useful for showing physical ports that are in a virtual port-channel. Route: /api/v0/devices/:hostname/port_stack hostname can be either the device hostname or id Input: valid_mappings: Filter the result by only showing valid mappings (\"0\" values not shown). Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/port_stack?valid_mappings Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 2 , \"mappings\" : [ { \"device_id\" : \"3742\" , \"port_id_high\" : \"1001000\" , \"port_id_low\" : \"51001\" , \"ifStackStatus\" : \"active\" }, { \"device_id\" : \"3742\" , \"port_id_high\" : \"1001000\" , \"port_id_low\" : \"52001\" , \"ifStackStatus\" : \"active\" } ] } get_components Get a list of components for a particular device. Route: /api/v0/devices/:hostname/components hostname can be either the device hostname or id Input: type: Filter the result by type (Equals). id: Filter the result by id (Equals). label: Filter the result by label (Contains). status: Filter the result by status (Equals). disabled: Filter the result by disabled (Equals). ignore: Filter the result by ignore (Equals). Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 3 , \"components\" : { \"2\" : { \"TestAttribute-1\" : \"Value1\" , \"TestAttribute-2\" : \"Value2\" , \"TestAttribute-3\" : \"Value3\" , \"type\" : \"TestComponent-1\" , \"label\" : \"This is a really cool blue component\" , \"status\" : \"1\" , \"ignore\" : \"0\" , \"disabled\" : \"0\" }, \"20\" : { \"TestAttribute-1\" : \"Value4\" , \"TestAttribute-2\" : \"Value5\" , \"TestAttribute-3\" : \"Value6\" , \"type\" : \"TestComponent-1\" , \"label\" : \"This is a really cool red component\" , \"status\" : \"1\" , \"ignore\" : \"0\" , \"disabled\" : \"0\" }, \"27\" : { \"TestAttribute-1\" : \"Value7\" , \"TestAttribute-2\" : \"Value8\" , \"TestAttribute-3\" : \"Value9\" , \"type\" : \"TestComponent-2\" , \"label\" : \"This is a really cool yellow widget\" , \"status\" : \"1\" , \"ignore\" : \"0\" , \"disabled\" : \"0\" } } } add_components Create a new component of a type on a particular device. Route: /api/v0/devices/:hostname/components/:type hostname can be either the device hostname or id type is the type of component to add Example: curl -X POST -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components/APITEST Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"components\" : { \"4459\" : { \"type\" : \"APITEST\" , \"label\" : \"\" , \"status\" : 1 , \"ignore\" : 0 , \"disabled\" : 0 , \"error\" : \"\" } } } edit_components Edit an existing component on a particular device. Route: /api/v0/devices/:hostname/components hostname can be either the device hostname or id In this example we set the label and add a new field: TestField: curl -X PUT -d '{\"4459\": {\"type\": \"APITEST\",\"label\": \"This is a test label\",\"status\": 1,\"ignore\": 0,\"disabled\": 0,\"error\": \"\",\"TestField\": \"TestData\"}}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 } Just take the JSON array from add_components or edit_components, edit as you wish and submit it back to edit components. delete_components Delete an existing component on a particular device. Route: /api/v0/devices/:hostname/components/:component hostname can be either the device hostname or id component is the component ID to be deleted. Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components/4459 Output: { \"status\" : \"ok\" , \"message\" : \"\" } get_port_stats_by_port_hostname Get information about a particular port for a device. Route: /api/v0/devices/:hostname/ports/:ifname hostname can be either the device hostname or id ifname can be any of the interface names for the device which can be obtained using get_port_graphs . Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ports/eth0 Output: { \"status\" : \"ok\" , \"port\" : { \"port_id\" : \"2\" , \"device_id\" : \"1\" , ... \"poll_prev\" : \"1418412902\" , \"poll_period\" : \"300\" } } get_graph_by_port_hostname Get a graph of a port for a particular device. Route: /api/v0/devices/:hostname/ports/:ifname/:type hostname can be either the device hostname or id ifname can be any of the interface names for the device which can be obtained using get_port_graphs . Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. type is the port type you want the graph for, you can request a list of ports for a device with get_port_graphs . Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. ifDescr: If this is set to true then we will use ifDescr to lookup the port instead of ifName. Pass the ifDescr value you want to search as you would ifName. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ports/eth0/port_bits Output: Output is an image. list_sensors Get a list of all Sensors. Route: /api/v0/resources/sensors Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/sensors Output: { \"status\" : \"ok\" , \"sensors\" : [ { \"sensor_id\" : 218810 , \"sensor_deleted\" : 0 , \"sensor_class\" : \"dbm\" , \"device_id\" : 136 , \"poller_type\" : \"snmp\" , \"sensor_oid\" : \".1.3.6.1.4.1.2636.3.60.1.1.1.1.7.919\" , \"sensor_index\" : \"tx-919\" , \"sensor_type\" : \"junos\" , \"sensor_descr\" : \"xe-2/1/4 Tx Power\" , \"group\" : null , \"sensor_divisor\" : 100 , \"sensor_multiplier\" : 1 , \"sensor_current\" : -1.81 , \"sensor_limit\" : 2 , \"sensor_limit_warn\" : 0.5 , \"sensor_limit_low\" : -9.7 , \"sensor_limit_low_warn\" : -8.21 , \"sensor_alert\" : 1 , \"sensor_custom\" : \"No\" , \"entPhysicalIndex\" : \"919\" , \"entPhysicalIndex_measured\" : \"ports\" , \"lastupdate\" : \"2019-02-18 02:47:09\" , \"sensor_prev\" : -1.77 , \"user_func\" : null }, ... ], \"count\" : 100 } list_devices Return a list of devices. Route: /api/v0/devices Input: order: How to order the output, default is by hostname. Can be prepended by DESC or ASC to change the order. type: can be one of the following to filter or search by: all: All devices active: Only not ignored and not disabled devices ignored: Only ignored devices up: Only devices that are up down: Only devices that are down disabled: Disabled devices os: search by os type mac: search by mac address ipv4: search by IPv4 address ipv6: search by IPv6 address (compressed or uncompressed) location: search by location location_id: serach by locaiton_id hostname: search by hostname sysName: search by sysName display: search by display name device_id: exact match by device-id type: search by device type query: If searching by, then this will be used as the input. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices?order=hostname%20DESC&type=down Output: { \"status\" : \"ok\" , \"count\" : 1 , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices?type=mac&query=00000c9ff013 Output: { \"status\" : \"ok\" , \"count\" : 1 , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] } maintenance_device Set a device into maintenance mode. Route: /api/v0/devices/:hostname/maintenance Input (JSON): title : optional - Some title for the Maintenance Will be replaced with hostname if omitted notes : optional - Some description for the Maintenance Will also be added to device notes if user prefs \"Add schedule notes to devices notes\" is set start : optional - start time of Maintenance in full format Y-m-d H:i:00 eg: 2022-08-01 22:45:00 Current system time now() will be used if omitted duration : required - Duration of Maintenance in format H:i / Hrs:Mins eg: 02:00 Example with start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devices/localhost/maintenance/ \\ --data-raw ' \"title\":\"Device Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with start time\", \"start\":\"2022-08-01 08:00:00\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device localhost (1) will begin maintenance mode at 2022-08-01 22:45:00 for 2:00h\" } Example with no start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devices/localhost/maintenance/ \\ --data-raw ' \"title\":\"Device Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with no start time\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device localhost (1) moved into maintenance mode for 2:00h\" } add_device Add a new device. Most fields are optional. You may omit snmp credentials to attempt each system credential in order. See snmp.version, snmp.community, and snmp.v3 To guarantee device is added, use force_add. This will skip checks for duplicate device and snmp reachability, but not duplicate hostname. Route: /api/v0/devices Input (JSON): Fields: hostname (required): device hostname or IP display: A string to display as the name of this device, defaults to hostname (or device_display_default setting). May be a simple template using replacements: {{ $hostname }}, {{ $sysName }}, {{ $sysName_fallback }}, {{ $ip }} snmpver: SNMP version to use, v1, v2c or v3. During checks detection order is v2c,v3,v1 port: SNMP port (defaults to port defined in config). transport: SNMP protocol (udp,tcp,udp6,tcp6) Defaults to transport defined in config. port_association_mode: method to identify ports: ifIndex (default), ifName, ifDescr, ifAlias poller_group: This is the poller_group id used for distributed poller setup. Defaults to 0. location or location_id: set the location by text or location id Options: force_add: Skip all checks and attempts to detect credentials. Add the device as given directly to the database. ping_fallback: if snmp checks fail, add the device as ping only instead of failing SNMP v1 or v2c credentials: community: Required for SNMP v1 or v2c. SNMP v3 credentials: authlevel: SNMP authlevel (noAuthNoPriv, authNoPriv, authPriv). authname: SNMP Auth username authpass: SNMP Auth password authalgo: SNMP Auth algorithm (MD5, SHA) (SHA-224, SHA-256, SHA-384, SHA-512 if supported by your server) cryptopass: SNMP Crypto Password cryptoalgo: SNMP Crypto algorithm (AES, DES) For ICMP only: snmp_disable: set to true for ICMP only. Disables SNMP checks and polling. os: OS short name for the device (defaults to ping). sysName: sysName for the device. hardware: Device hardware. Example: curl -X POST -d '{\"hostname\":\"localhost.localdomain\",\"version\":\"v1\",\"community\":\"public\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices Output: { \"status\" : \"ok\" , \"message\" : \"Device localhost.localdomain (57) has been added successfully\" , \"devices\" : [ { \"device_id\" : \"57\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } } list_oxidized List devices for use with Oxidized. If you have group support enabled then a group will also be returned based on your config. LibreNMS will automatically map the OS to the Oxidized model name if they don't match. Route: /api/v0/oxidized(/:hostname) Input (JSON): - Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/oxidized Output: [ { \"hostname\" : \"localhost\" , \"os\" : \"linux\" }, { \"hostname\" : \"otherserver\" , \"os\" : \"linux\" } ] update_device_field Update devices field in the database. Route: /api/v0/devices/:hostname hostname can be either the device hostname or id Input (JSON): field: The column name within the database (can be an array of fields) data: The data to update the column with (can be an array of data)) Examples: curl -X PATCH -d '{\"field\": \"notes\", \"data\": \"This server should be kept online\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: [ { \"status\" : \"ok\" , \"message\" : \"Device notes has been updated\" } ] update_device_port_notes Update a device port notes field in the devices_attrs database. Route: /api/v0/devices/:hostname/port/:portid hostname can be either the device hostname or id portid needs to be the port unique id (int). Input (JSON): - notes: The string data to populate on the port notes field. Examples: curl -X PATCH -d '{\"notes\": \"This port is in a scheduled maintenance with the provider.\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/port/5 Output: [ { \"status\" : \"ok\" , \"message\" : \"Port notes field has been updated\" } ] curl -X PATCH -d '{\"field\": [\"notes\",\"purpose\"], \"data\": [\"This server should be kept online\", \"For serving web traffic\"]}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: [ { \"status\" : \"ok\" , \"message\" : \"Device fields have been updated\" } ] rename_device Rename device. Route: /api/v0/devices/:hostname/rename/:new_hostname hostname can be either the device hostname or id Input: - Examples: curl -X PATCH -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/rename/localhost2 Output: [ { \"status\" : \"ok\" , \"message\" : \"Device has been renamed\" } ] get_device_groups List the device groups that a device is matched on. Route: /api/v0/devices/:hostname/groups hostname can be either the device hostname or id Input (JSON): - Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/groups Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 1 device groups\" , \"count\" : 1 , \"groups\" : [ { \"id\" : \"1\" , \"name\" : \"Testing\" , \"desc\" : \"Testing\" , \"pattern\" : \"%devices.status = \\\"1\\\" &&\" } ] } ] search_oxidized search all oxidized device configs for a string. Route: api/v0/oxidized/config/search/:searchstring searchstring is the specific string you would like to search for. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/oxidized/config/search/vlan10 Output: { \"status\" : \"ok\" , \"nodes\" : [ { \"node\" : \"asr9k.librenms.org\" , \"full_name\" : \"cisco\\/ASR9K.Librenms.org\" }, { \"node\" : \"ios.Librenms.org\" , \"full_name\" : \"cisco\\/ios.Librenms.org\" } ], \"count\" : 2 } get_oxidized_config Returns a specific device's config from oxidized. Route: api/v0/oxidized/config/:hostname hostname is the Hostname or IP of the device used when adding the device to librenms. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/oxidized/config/router.corp.com Output: { \"status\" : \"ok\" , \"config\" : \"DEVICE CONFIG HERE\" } add_parents_to_host Add one or more parents to a host. Route: /api/v0/devices/:device/parents Input (JSON): parent_ids: one or more parent ids or hostnames Example: curl -X POST -d '{\"parent_ids\":\"15,16,17\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/1/parents Output: { \"status\" : \"ok\" , \"message\" : \"Device dependencies have been saved\" } delete_parents_from_host Deletes some or all the parents from a host. Route: /api/v0/devices/:device/parents Input (JSON): parent_ids: One or more parent ids or hostnames, if not specified deletes all parents from host. Example: curl -X DELETE -d '{\"parent_ids\":\"15,16,17\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/1/parents Output: { \"status\" : \"ok\" , \"message\" : \"All device dependencies have been removed\" } list_parents_of_host This is not a seperate API call. Instead, you obtain the list of parents from list_devices . See that entry point for more detailed information. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' 'http://librenms.org/api/v0/devices?type=device_id&query=34' Output: { \"status\" : \"ok\" , \"devices\" : [ { ... \"dependency_parent_id\" : \"98,99\" , \"dependency_parent_hostname\" : \"HOSTNAME1,HOSTNAME2\" , ... } ], \"count\" : 1 }","title":"Devices"},{"location":"API/Devices/#del_device","text":"Delete a given device. Route: /api/v0/devices/:hostname hostname can be either the device hostname or id Input: - Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: { \"status\" : \"ok\" , \"message\" : \"Removed device localhost\" , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] }","title":"del_device"},{"location":"API/Devices/#get_device","text":"Get details of a given device. Route: /api/v0/devices/:hostname hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: { \"status\" : \"ok\" , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] }","title":"get_device"},{"location":"API/Devices/#discover_device","text":"Trigger a discovery of given device. Route: /api/v0/devices/:hostname/discover hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/discover Output: { \"status\" : \"ok\" , \"result\" : { \"status\" : 0 , \"message\" : \"Device will be rediscovered\" }, \"count\" : 2 }","title":"discover_device"},{"location":"API/Devices/#availability","text":"Get calculated availabilities of given device. Route: /api/v0/devices/:hostname/availability hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/availability Output: { \"status\" : \"ok\" , \"availability\" : [ { \"duration\" : 86400 , \"availability_perc\" : \"100.000000\" }, { \"duration\" : 604800 , \"availability_perc\" : \"100.000000\" }, { \"duration\" : 2592000 , \"availability_perc\" : \"99.946000\" }, { \"duration\" : 31536000 , \"availability_perc\" : \"99.994000\" } ], \"count\" : 4 }","title":"availability"},{"location":"API/Devices/#outages","text":"Get detected outages of given device. Route: /api/v0/devices/:hostname/outages hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/outages Output: { \"status\" : \"ok\" , \"outages\" : [ { \"going_down\" : 1593194031 , \"up_again\" : 1593194388 }, { \"going_down\" : 1593946507 , \"up_again\" : 1593946863 }, { \"going_down\" : 1594628616 , \"up_again\" : 1594628968 }, { \"going_down\" : 1594628974 , \"up_again\" : 1594629339 }, { \"going_down\" : 1594638668 , \"up_again\" : 1594638992 } ], \"count\" : 5 }","title":"outages"},{"location":"API/Devices/#get_graphs","text":"Get a list of available graphs for a device, this does not include ports. Route: /api/v0/devices/:hostname/graphs hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 3 , \"graphs\" : [ { \"desc\" : \"Poller Time\" , \"name\" : \"device_poller_perf\" }, { \"desc\" : \"Ping Response\" , \"name\" : \"device_ping_perf\" }, { \"desc\" : \"System Uptime\" , \"name\" : \"uptime\" } ] }","title":"get_graphs"},{"location":"API/Devices/#list_available_health_graphs","text":"This function allows to do three things: Get a list of overall health graphs available. Get a list of health graphs based on provided class. Get the health sensors information based on ID. Route: /api/v0/devices/:hostname/health(/:type)(/:sensor_id) hostname can be either the device hostname or id type (optional) is health type / sensor class sensor_id (optional) is the sensor id to retrieve specific information. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health Output: { \"status\": \"ok\", \"message\": \"\", \"count\": 2, \"graphs\": [ { \"desc\": \"Airflow\", \"name\": \"device_airflow\" }, { \"desc\": \"Voltage\", \"name\": \"device_voltage\" } ] } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health/device_voltage Output: { \"status\": \"ok\", \"message\": \"\", \"count\": 2, \"graphs\": [ { \"sensor_id\": \"1\", \"desc\": \"Input Feed A\" }, { \"sensor_id\": \"2\", \"desc\": \"Output Feed\" } ] } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health/device_voltage/1 Output: { \"status\": \"ok\", \"message\": \"\", \"count\": 1, \"graphs\": [ { \"sensor_id\": \"1\", \"sensor_deleted\": \"0\", \"sensor_class\": \"voltage\", \"device_id\": \"1\", \"poller_type\": \"snmp\", \"sensor_oid\": \".1.3.6.1.4.1.318.1.1.27.1.1.0\", \"sensor_index\": \"1\", \"sensor_type\": \"apc\", \"sensor_descr\": \"Input\", \"sensor_divisor\": \"1\", \"sensor_multiplier\": \"1\", \"sensor_current\": \"1\", \"sensor_limit\": \"1.15\", \"sensor_limit_warn\": null, \"sensor_limit_low\": \"0.85\", \"sensor_limit_low_warn\": null, \"sensor_alert\": \"1\", \"sensor_custom\": \"No\", \"entPhysicalIndex\": null, \"entPhysicalIndex_measured\": null, \"lastupdate\": \"2017-01-13 13:50:26\", \"sensor_prev\": \"1\" } ] }","title":"list_available_health_graphs"},{"location":"API/Devices/#list_available_wireless_graphs","text":"This function allows to do three things: Get a list of overall wireless graphs available. Get a list of wireless graphs based on provided class. Get the wireless sensors information based on ID. Route: /api/v0/devices/:hostname/wireless(/:type)(/:sensor_id) hostname can be either the device hostname or id type (optional) is wireless type / wireless class sensor_id (optional) is the sensor id to retrieve specific information. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/wireless Output: { \"status\": \"ok\", \"graphs\": [ { \"desc\": \"Ccq\", \"name\": \"device_wireless_ccq\" }, { \"desc\": \"Clients\", \"name\": \"device_wireless_clients\" } ], \"count\": 2 } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/wireless/device_wireless_ccq Output: { \"status\": \"ok\", \"graphs\": [ { \"sensor_id\": \"791\", \"desc\": \"SSID: bast (ng)\" }, { \"sensor_id\": \"792\", \"desc\": \"SSID: bast (na)\" } ], \"count\": 2 } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/health/device_wireless_ccq/1 Output: { \"status\": \"ok\", \"graphs\": [ { \"sensor_id\": \"791\", \"sensor_deleted\": \"0\", \"sensor_class\": \"ccq\", \"device_id\": \"381\", \"sensor_index\": \"0\", \"sensor_type\": \"unifi\", \"sensor_descr\": \"SSID: bast (ng)\", \"sensor_divisor\": \"10\", \"sensor_multiplier\": \"1\", \"sensor_aggregator\": \"sum\", \"sensor_current\": \"100\", \"sensor_prev\": \"100\", \"sensor_limit\": null, \"sensor_limit_warn\": null, \"sensor_limit_low\": null, \"sensor_limit_low_warn\": null, \"sensor_alert\": \"1\", \"sensor_custom\": \"No\", \"entPhysicalIndex\": null, \"entPhysicalIndex_measured\": null, \"lastupdate\": \"2017-12-06 21:26:29\", \"sensor_oids\": \"[\\\".1.3.6.1.4.1.41112.1.6.1.2.1.3.0\\\"]\", \"access_point_id\": null } ], \"count\": 1 }","title":"list_available_wireless_graphs"},{"location":"API/Devices/#get_health_graph","text":"Get a particular health class graph for a device, if you provide a sensor_id as well then a single sensor graph will be provided. If no sensor_id value is provided then you will be sent a stacked sensor graph. Route: /api/v0/devices/:hostname/graphs/health/:type(/:sensor_id) hostname can be either the device hostname or id type is the name of the health graph as returned by list_available_health_graphs sensor_id (optional) restricts the graph to return a particular health sensor graph. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/health/device_voltage Output: Output is a stacked graph for the health type provided. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/health/device_voltage/1 Output: Output is the graph of the particular health type sensor provided.","title":"get_health_graph"},{"location":"API/Devices/#get_wireless_graph","text":"Get a particular wireless class graph for a device, if you provide a sensor_id as well then a single sensor graph will be provided. If no sensor_id value is provided then you will be sent a stacked wireless graph. Route: /api/v0/devices/:hostname/graphs/wireless/:type(/:sensor_id) hostname can be either the device hostname or id type is the name of the wireless graph as returned by list_available_wireless_graphs sensor_id (optional) restricts the graph to return a particular wireless sensor graph. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/wireless/device_wireless_ccq Output: Output is a stacked graph for the wireless type provided. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/graphs/wireless/device_wireless_ccq/1 Output: Output is the graph of the particular wireless type sensor provided.","title":"get_wireless_graph"},{"location":"API/Devices/#get_graph_generic_by_hostname","text":"Get a specific graph for a device, this does not include ports. Route: /api/v0/devices/:hostname/:type hostname can be either the device hostname or id type is the type of graph you want, use [ get_graphs ](#function-get_graphs to see the graphs available. Defaults to device uptime. Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. output: Set how the graph should be outputted (base64, display), defaults to display. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/device_poller_perf Output: Output is an image.","title":"get_graph_generic_by_hostname"},{"location":"API/Devices/#get_graph_by_service","text":"Get the graph for a service Route: /api/v0/devices/:hostname/services/:service_id/graphs/:datasource hostname can be either the device hostname or id service id datasource is the name of the service datasource Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/localhost/35/graphs/loss Output: Output is an image.","title":"get_graph_by_service"},{"location":"API/Devices/#get_port_graphs","text":"Get a list of ports for a particular device. Route: /api/v0/devices/:hostname/ports hostname can be either the device hostname or id Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ports Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 3 , \"ports\" : [ { \"ifName\" : \"lo\" }, { \"ifName\" : \"eth0\" }, { \"ifName\" : \"eth1\" } ] }","title":"get_port_graphs"},{"location":"API/Devices/#get_device_fdb","text":"Get a list of FDB entries associated with a device. Route: /api/v0/devices/:hostname/fdb hostname can be either the device hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/fdb Output: { \"status\" : \"ok\" , \"ports_fdb\" : { \"ports_fdb_id\" : 10 , \"port_id\" : 10000 , \"mac_address\" : \"1aaa2bbb3ccc\" , \"vlan_id\" : 20000 , \"device_id\" : 1 , \"created_at\" : \"2019-01-1 01:01:01\" , \"updated_at\" : \"2019-01-1 01:01:01\" } }","title":"get_device_fdb"},{"location":"API/Devices/#get_device_ip_addresses","text":"Get a list of IP addresses (v4 and v6) associated with a device. Route: /api/v0/devices/:hostname/ip hostname can be either the device hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ip Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"addresses\" : [ { \"ipv4_address_id\" : \"290\" , \"ipv4_address\" : \"192.168.99.292\" , \"ipv4_prefixlen\" : \"30\" , \"ipv4_network_id\" : \"247\" , \"port_id\" : \"323\" , \"context_name\" : \"\" } ] }","title":"get_device_ip_addresses"},{"location":"API/Devices/#get_port_stack","text":"Get a list of port mappings for a device. This is useful for showing physical ports that are in a virtual port-channel. Route: /api/v0/devices/:hostname/port_stack hostname can be either the device hostname or id Input: valid_mappings: Filter the result by only showing valid mappings (\"0\" values not shown). Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/port_stack?valid_mappings Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 2 , \"mappings\" : [ { \"device_id\" : \"3742\" , \"port_id_high\" : \"1001000\" , \"port_id_low\" : \"51001\" , \"ifStackStatus\" : \"active\" }, { \"device_id\" : \"3742\" , \"port_id_high\" : \"1001000\" , \"port_id_low\" : \"52001\" , \"ifStackStatus\" : \"active\" } ] }","title":"get_port_stack"},{"location":"API/Devices/#get_components","text":"Get a list of components for a particular device. Route: /api/v0/devices/:hostname/components hostname can be either the device hostname or id Input: type: Filter the result by type (Equals). id: Filter the result by id (Equals). label: Filter the result by label (Contains). status: Filter the result by status (Equals). disabled: Filter the result by disabled (Equals). ignore: Filter the result by ignore (Equals). Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 3 , \"components\" : { \"2\" : { \"TestAttribute-1\" : \"Value1\" , \"TestAttribute-2\" : \"Value2\" , \"TestAttribute-3\" : \"Value3\" , \"type\" : \"TestComponent-1\" , \"label\" : \"This is a really cool blue component\" , \"status\" : \"1\" , \"ignore\" : \"0\" , \"disabled\" : \"0\" }, \"20\" : { \"TestAttribute-1\" : \"Value4\" , \"TestAttribute-2\" : \"Value5\" , \"TestAttribute-3\" : \"Value6\" , \"type\" : \"TestComponent-1\" , \"label\" : \"This is a really cool red component\" , \"status\" : \"1\" , \"ignore\" : \"0\" , \"disabled\" : \"0\" }, \"27\" : { \"TestAttribute-1\" : \"Value7\" , \"TestAttribute-2\" : \"Value8\" , \"TestAttribute-3\" : \"Value9\" , \"type\" : \"TestComponent-2\" , \"label\" : \"This is a really cool yellow widget\" , \"status\" : \"1\" , \"ignore\" : \"0\" , \"disabled\" : \"0\" } } }","title":"get_components"},{"location":"API/Devices/#add_components","text":"Create a new component of a type on a particular device. Route: /api/v0/devices/:hostname/components/:type hostname can be either the device hostname or id type is the type of component to add Example: curl -X POST -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components/APITEST Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"components\" : { \"4459\" : { \"type\" : \"APITEST\" , \"label\" : \"\" , \"status\" : 1 , \"ignore\" : 0 , \"disabled\" : 0 , \"error\" : \"\" } } }","title":"add_components"},{"location":"API/Devices/#edit_components","text":"Edit an existing component on a particular device. Route: /api/v0/devices/:hostname/components hostname can be either the device hostname or id In this example we set the label and add a new field: TestField: curl -X PUT -d '{\"4459\": {\"type\": \"APITEST\",\"label\": \"This is a test label\",\"status\": 1,\"ignore\": 0,\"disabled\": 0,\"error\": \"\",\"TestField\": \"TestData\"}}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 } Just take the JSON array from add_components or edit_components, edit as you wish and submit it back to edit components.","title":"edit_components"},{"location":"API/Devices/#delete_components","text":"Delete an existing component on a particular device. Route: /api/v0/devices/:hostname/components/:component hostname can be either the device hostname or id component is the component ID to be deleted. Example: curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/components/4459 Output: { \"status\" : \"ok\" , \"message\" : \"\" }","title":"delete_components"},{"location":"API/Devices/#get_port_stats_by_port_hostname","text":"Get information about a particular port for a device. Route: /api/v0/devices/:hostname/ports/:ifname hostname can be either the device hostname or id ifname can be any of the interface names for the device which can be obtained using get_port_graphs . Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ports/eth0 Output: { \"status\" : \"ok\" , \"port\" : { \"port_id\" : \"2\" , \"device_id\" : \"1\" , ... \"poll_prev\" : \"1418412902\" , \"poll_period\" : \"300\" } }","title":"get_port_stats_by_port_hostname"},{"location":"API/Devices/#get_graph_by_port_hostname","text":"Get a graph of a port for a particular device. Route: /api/v0/devices/:hostname/ports/:ifname/:type hostname can be either the device hostname or id ifname can be any of the interface names for the device which can be obtained using get_port_graphs . Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. type is the port type you want the graph for, you can request a list of ports for a device with get_port_graphs . Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. ifDescr: If this is set to true then we will use ifDescr to lookup the port instead of ifName. Pass the ifDescr value you want to search as you would ifName. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/ports/eth0/port_bits Output: Output is an image.","title":"get_graph_by_port_hostname"},{"location":"API/Devices/#list_sensors","text":"Get a list of all Sensors. Route: /api/v0/resources/sensors Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/sensors Output: { \"status\" : \"ok\" , \"sensors\" : [ { \"sensor_id\" : 218810 , \"sensor_deleted\" : 0 , \"sensor_class\" : \"dbm\" , \"device_id\" : 136 , \"poller_type\" : \"snmp\" , \"sensor_oid\" : \".1.3.6.1.4.1.2636.3.60.1.1.1.1.7.919\" , \"sensor_index\" : \"tx-919\" , \"sensor_type\" : \"junos\" , \"sensor_descr\" : \"xe-2/1/4 Tx Power\" , \"group\" : null , \"sensor_divisor\" : 100 , \"sensor_multiplier\" : 1 , \"sensor_current\" : -1.81 , \"sensor_limit\" : 2 , \"sensor_limit_warn\" : 0.5 , \"sensor_limit_low\" : -9.7 , \"sensor_limit_low_warn\" : -8.21 , \"sensor_alert\" : 1 , \"sensor_custom\" : \"No\" , \"entPhysicalIndex\" : \"919\" , \"entPhysicalIndex_measured\" : \"ports\" , \"lastupdate\" : \"2019-02-18 02:47:09\" , \"sensor_prev\" : -1.77 , \"user_func\" : null }, ... ], \"count\" : 100 }","title":"list_sensors"},{"location":"API/Devices/#list_devices","text":"Return a list of devices. Route: /api/v0/devices Input: order: How to order the output, default is by hostname. Can be prepended by DESC or ASC to change the order. type: can be one of the following to filter or search by: all: All devices active: Only not ignored and not disabled devices ignored: Only ignored devices up: Only devices that are up down: Only devices that are down disabled: Disabled devices os: search by os type mac: search by mac address ipv4: search by IPv4 address ipv6: search by IPv6 address (compressed or uncompressed) location: search by location location_id: serach by locaiton_id hostname: search by hostname sysName: search by sysName display: search by display name device_id: exact match by device-id type: search by device type query: If searching by, then this will be used as the input. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices?order=hostname%20DESC&type=down Output: { \"status\" : \"ok\" , \"count\" : 1 , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] } Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices?type=mac&query=00000c9ff013 Output: { \"status\" : \"ok\" , \"count\" : 1 , \"devices\" : [ { \"device_id\" : \"1\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } ] }","title":"list_devices"},{"location":"API/Devices/#maintenance_device","text":"Set a device into maintenance mode. Route: /api/v0/devices/:hostname/maintenance Input (JSON): title : optional - Some title for the Maintenance Will be replaced with hostname if omitted notes : optional - Some description for the Maintenance Will also be added to device notes if user prefs \"Add schedule notes to devices notes\" is set start : optional - start time of Maintenance in full format Y-m-d H:i:00 eg: 2022-08-01 22:45:00 Current system time now() will be used if omitted duration : required - Duration of Maintenance in format H:i / Hrs:Mins eg: 02:00 Example with start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devices/localhost/maintenance/ \\ --data-raw ' \"title\":\"Device Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with start time\", \"start\":\"2022-08-01 08:00:00\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device localhost (1) will begin maintenance mode at 2022-08-01 22:45:00 for 2:00h\" } Example with no start time: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST https://librenms.org/api/v0/devices/localhost/maintenance/ \\ --data-raw ' \"title\":\"Device Maintenance\", \"notes\":\"A 2 hour Maintenance triggered via API with no start time\", \"duration\":\"2:00\" } ' Output: { \"status\" : \"ok\" , \"message\" : \"Device localhost (1) moved into maintenance mode for 2:00h\" }","title":"maintenance_device"},{"location":"API/Devices/#add_device","text":"Add a new device. Most fields are optional. You may omit snmp credentials to attempt each system credential in order. See snmp.version, snmp.community, and snmp.v3 To guarantee device is added, use force_add. This will skip checks for duplicate device and snmp reachability, but not duplicate hostname. Route: /api/v0/devices Input (JSON): Fields: hostname (required): device hostname or IP display: A string to display as the name of this device, defaults to hostname (or device_display_default setting). May be a simple template using replacements: {{ $hostname }}, {{ $sysName }}, {{ $sysName_fallback }}, {{ $ip }} snmpver: SNMP version to use, v1, v2c or v3. During checks detection order is v2c,v3,v1 port: SNMP port (defaults to port defined in config). transport: SNMP protocol (udp,tcp,udp6,tcp6) Defaults to transport defined in config. port_association_mode: method to identify ports: ifIndex (default), ifName, ifDescr, ifAlias poller_group: This is the poller_group id used for distributed poller setup. Defaults to 0. location or location_id: set the location by text or location id Options: force_add: Skip all checks and attempts to detect credentials. Add the device as given directly to the database. ping_fallback: if snmp checks fail, add the device as ping only instead of failing SNMP v1 or v2c credentials: community: Required for SNMP v1 or v2c. SNMP v3 credentials: authlevel: SNMP authlevel (noAuthNoPriv, authNoPriv, authPriv). authname: SNMP Auth username authpass: SNMP Auth password authalgo: SNMP Auth algorithm (MD5, SHA) (SHA-224, SHA-256, SHA-384, SHA-512 if supported by your server) cryptopass: SNMP Crypto Password cryptoalgo: SNMP Crypto algorithm (AES, DES) For ICMP only: snmp_disable: set to true for ICMP only. Disables SNMP checks and polling. os: OS short name for the device (defaults to ping). sysName: sysName for the device. hardware: Device hardware. Example: curl -X POST -d '{\"hostname\":\"localhost.localdomain\",\"version\":\"v1\",\"community\":\"public\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices Output: { \"status\" : \"ok\" , \"message\" : \"Device localhost.localdomain (57) has been added successfully\" , \"devices\" : [ { \"device_id\" : \"57\" , \"hostname\" : \"localhost\" , ... \"serial\" : null , \"icon\" : null } }","title":"add_device"},{"location":"API/Devices/#list_oxidized","text":"List devices for use with Oxidized. If you have group support enabled then a group will also be returned based on your config. LibreNMS will automatically map the OS to the Oxidized model name if they don't match. Route: /api/v0/oxidized(/:hostname) Input (JSON): - Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/oxidized Output: [ { \"hostname\" : \"localhost\" , \"os\" : \"linux\" }, { \"hostname\" : \"otherserver\" , \"os\" : \"linux\" } ]","title":"list_oxidized"},{"location":"API/Devices/#update_device_field","text":"Update devices field in the database. Route: /api/v0/devices/:hostname hostname can be either the device hostname or id Input (JSON): field: The column name within the database (can be an array of fields) data: The data to update the column with (can be an array of data)) Examples: curl -X PATCH -d '{\"field\": \"notes\", \"data\": \"This server should be kept online\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: [ { \"status\" : \"ok\" , \"message\" : \"Device notes has been updated\" } ]","title":"update_device_field"},{"location":"API/Devices/#update_device_port_notes","text":"Update a device port notes field in the devices_attrs database. Route: /api/v0/devices/:hostname/port/:portid hostname can be either the device hostname or id portid needs to be the port unique id (int). Input (JSON): - notes: The string data to populate on the port notes field. Examples: curl -X PATCH -d '{\"notes\": \"This port is in a scheduled maintenance with the provider.\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/port/5 Output: [ { \"status\" : \"ok\" , \"message\" : \"Port notes field has been updated\" } ] curl -X PATCH -d '{\"field\": [\"notes\",\"purpose\"], \"data\": [\"This server should be kept online\", \"For serving web traffic\"]}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost Output: [ { \"status\" : \"ok\" , \"message\" : \"Device fields have been updated\" } ]","title":"update_device_port_notes"},{"location":"API/Devices/#rename_device","text":"Rename device. Route: /api/v0/devices/:hostname/rename/:new_hostname hostname can be either the device hostname or id Input: - Examples: curl -X PATCH -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/rename/localhost2 Output: [ { \"status\" : \"ok\" , \"message\" : \"Device has been renamed\" } ]","title":"rename_device"},{"location":"API/Devices/#get_device_groups","text":"List the device groups that a device is matched on. Route: /api/v0/devices/:hostname/groups hostname can be either the device hostname or id Input (JSON): - Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/groups Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 1 device groups\" , \"count\" : 1 , \"groups\" : [ { \"id\" : \"1\" , \"name\" : \"Testing\" , \"desc\" : \"Testing\" , \"pattern\" : \"%devices.status = \\\"1\\\" &&\" } ] } ]","title":"get_device_groups"},{"location":"API/Devices/#search_oxidized","text":"search all oxidized device configs for a string. Route: api/v0/oxidized/config/search/:searchstring searchstring is the specific string you would like to search for. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/oxidized/config/search/vlan10 Output: { \"status\" : \"ok\" , \"nodes\" : [ { \"node\" : \"asr9k.librenms.org\" , \"full_name\" : \"cisco\\/ASR9K.Librenms.org\" }, { \"node\" : \"ios.Librenms.org\" , \"full_name\" : \"cisco\\/ios.Librenms.org\" } ], \"count\" : 2 }","title":"search_oxidized"},{"location":"API/Devices/#get_oxidized_config","text":"Returns a specific device's config from oxidized. Route: api/v0/oxidized/config/:hostname hostname is the Hostname or IP of the device used when adding the device to librenms. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/oxidized/config/router.corp.com Output: { \"status\" : \"ok\" , \"config\" : \"DEVICE CONFIG HERE\" }","title":"get_oxidized_config"},{"location":"API/Devices/#add_parents_to_host","text":"Add one or more parents to a host. Route: /api/v0/devices/:device/parents Input (JSON): parent_ids: one or more parent ids or hostnames Example: curl -X POST -d '{\"parent_ids\":\"15,16,17\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/1/parents Output: { \"status\" : \"ok\" , \"message\" : \"Device dependencies have been saved\" }","title":"add_parents_to_host"},{"location":"API/Devices/#delete_parents_from_host","text":"Deletes some or all the parents from a host. Route: /api/v0/devices/:device/parents Input (JSON): parent_ids: One or more parent ids or hostnames, if not specified deletes all parents from host. Example: curl -X DELETE -d '{\"parent_ids\":\"15,16,17\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/1/parents Output: { \"status\" : \"ok\" , \"message\" : \"All device dependencies have been removed\" }","title":"delete_parents_from_host"},{"location":"API/Devices/#list_parents_of_host","text":"This is not a seperate API call. Instead, you obtain the list of parents from list_devices . See that entry point for more detailed information. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' 'http://librenms.org/api/v0/devices?type=device_id&query=34' Output: { \"status\" : \"ok\" , \"devices\" : [ { ... \"dependency_parent_id\" : \"98,99\" , \"dependency_parent_hostname\" : \"HOSTNAME1,HOSTNAME2\" , ... } ], \"count\" : 1 }","title":"list_parents_of_host"},{"location":"API/Inventory/","text":"get_inventory Retrieve the inventory for a device. If you call this without any parameters then you will only get part of the inventory. This is because a lot of devices nest each component, for instance you may initially have the chassis, within this the ports - 1 being an sfp cage, then the sfp itself. The way this API call is designed is to enable a recursive lookup. The first call will retrieve the root entry, included within this response will be entPhysicalIndex, you can then call for entPhysicalContainedIn which will then return the next layer of results. To retrieve all items together, see get_inventory_for_device . Route: /api/v0/inventory/:hostname hostname can be either the device hostname or the device id Input: entPhysicalClass: This is used to restrict the class of the inventory, for example you can specify chassis to only return items in the inventory that are labelled as chassis. entPhysicalContainedIn: This is used to retrieve items within the inventory assigned to a previous component, for example specifying the chassis (entPhysicalIndex) will retrieve all items where the chassis is the parent. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/inventory/localhost?entPhysicalContainedIn=65536 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"inventory\" : [ { \"entPhysical_id\" : \"2\" , \"device_id\" : \"32\" , \"entPhysicalIndex\" : \"262145\" , \"entPhysicalDescr\" : \"Linux 3.3.5 ehci_hcd RB400 EHCI\" , \"entPhysicalClass\" : \"unknown\" , \"entPhysicalName\" : \"1:1\" , \"entPhysicalHardwareRev\" : \"\" , \"entPhysicalFirmwareRev\" : \"\" , \"entPhysicalSoftwareRev\" : \"\" , \"entPhysicalAlias\" : \"\" , \"entPhysicalAssetID\" : \"\" , \"entPhysicalIsFRU\" : \"false\" , \"entPhysicalModelName\" : \"0x0002\" , \"entPhysicalVendorType\" : \"zeroDotZero\" , \"entPhysicalSerialNum\" : \"rb400_usb\" , \"entPhysicalContainedIn\" : \"65536\" , \"entPhysicalParentRelPos\" : \"-1\" , \"entPhysicalMfgName\" : \"0x1d6b\" , \"ifIndex\" : \"0\" } ] } get_inventory_for_device Retrieve the flattened inventory for a device. This retrieves all inventory items for a device regardless of their structure, and may be more useful for devices with with nested components. Route: /api/v0/inventory/:hostname/all hostname can be either the device hostname or the device id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/inventory/localhost?entPhysicalContainedIn=65536 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"inventory\" : [ { \"entPhysical_id\" : \"2\" , \"device_id\" : \"32\" , \"entPhysicalIndex\" : \"262145\" , \"entPhysicalDescr\" : \"Linux 3.3.5 ehci_hcd RB400 EHCI\" , \"entPhysicalClass\" : \"unknown\" , \"entPhysicalName\" : \"1:1\" , \"entPhysicalHardwareRev\" : \"\" , \"entPhysicalFirmwareRev\" : \"\" , \"entPhysicalSoftwareRev\" : \"\" , \"entPhysicalAlias\" : \"\" , \"entPhysicalAssetID\" : \"\" , \"entPhysicalIsFRU\" : \"false\" , \"entPhysicalModelName\" : \"0x0002\" , \"entPhysicalVendorType\" : \"zeroDotZero\" , \"entPhysicalSerialNum\" : \"rb400_usb\" , \"entPhysicalContainedIn\" : \"65536\" , \"entPhysicalParentRelPos\" : \"-1\" , \"entPhysicalMfgName\" : \"0x1d6b\" , \"ifIndex\" : \"0\" } ] }","title":"Inventory"},{"location":"API/Inventory/#get_inventory","text":"Retrieve the inventory for a device. If you call this without any parameters then you will only get part of the inventory. This is because a lot of devices nest each component, for instance you may initially have the chassis, within this the ports - 1 being an sfp cage, then the sfp itself. The way this API call is designed is to enable a recursive lookup. The first call will retrieve the root entry, included within this response will be entPhysicalIndex, you can then call for entPhysicalContainedIn which will then return the next layer of results. To retrieve all items together, see get_inventory_for_device . Route: /api/v0/inventory/:hostname hostname can be either the device hostname or the device id Input: entPhysicalClass: This is used to restrict the class of the inventory, for example you can specify chassis to only return items in the inventory that are labelled as chassis. entPhysicalContainedIn: This is used to retrieve items within the inventory assigned to a previous component, for example specifying the chassis (entPhysicalIndex) will retrieve all items where the chassis is the parent. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/inventory/localhost?entPhysicalContainedIn=65536 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"inventory\" : [ { \"entPhysical_id\" : \"2\" , \"device_id\" : \"32\" , \"entPhysicalIndex\" : \"262145\" , \"entPhysicalDescr\" : \"Linux 3.3.5 ehci_hcd RB400 EHCI\" , \"entPhysicalClass\" : \"unknown\" , \"entPhysicalName\" : \"1:1\" , \"entPhysicalHardwareRev\" : \"\" , \"entPhysicalFirmwareRev\" : \"\" , \"entPhysicalSoftwareRev\" : \"\" , \"entPhysicalAlias\" : \"\" , \"entPhysicalAssetID\" : \"\" , \"entPhysicalIsFRU\" : \"false\" , \"entPhysicalModelName\" : \"0x0002\" , \"entPhysicalVendorType\" : \"zeroDotZero\" , \"entPhysicalSerialNum\" : \"rb400_usb\" , \"entPhysicalContainedIn\" : \"65536\" , \"entPhysicalParentRelPos\" : \"-1\" , \"entPhysicalMfgName\" : \"0x1d6b\" , \"ifIndex\" : \"0\" } ] }","title":"get_inventory"},{"location":"API/Inventory/#get_inventory_for_device","text":"Retrieve the flattened inventory for a device. This retrieves all inventory items for a device regardless of their structure, and may be more useful for devices with with nested components. Route: /api/v0/inventory/:hostname/all hostname can be either the device hostname or the device id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/inventory/localhost?entPhysicalContainedIn=65536 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"inventory\" : [ { \"entPhysical_id\" : \"2\" , \"device_id\" : \"32\" , \"entPhysicalIndex\" : \"262145\" , \"entPhysicalDescr\" : \"Linux 3.3.5 ehci_hcd RB400 EHCI\" , \"entPhysicalClass\" : \"unknown\" , \"entPhysicalName\" : \"1:1\" , \"entPhysicalHardwareRev\" : \"\" , \"entPhysicalFirmwareRev\" : \"\" , \"entPhysicalSoftwareRev\" : \"\" , \"entPhysicalAlias\" : \"\" , \"entPhysicalAssetID\" : \"\" , \"entPhysicalIsFRU\" : \"false\" , \"entPhysicalModelName\" : \"0x0002\" , \"entPhysicalVendorType\" : \"zeroDotZero\" , \"entPhysicalSerialNum\" : \"rb400_usb\" , \"entPhysicalContainedIn\" : \"65536\" , \"entPhysicalParentRelPos\" : \"-1\" , \"entPhysicalMfgName\" : \"0x1d6b\" , \"ifIndex\" : \"0\" } ] }","title":"get_inventory_for_device"},{"location":"API/Locations/","text":"list_locations Return a list of locations. Route: /api/v0/resources/locations Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/locations Output: { \"status\" : \"ok\" , \"locations\" : [ { \"id\" : \"1\" , \"location\" : \"Example location, Example city, Example Country\" , \"lat\" : \"-18.911436\" , \"lng\" : \"47.517446\" , \"timestamp\" : \"2017-04-01 02:40:05\" }, ... ], \"count\" : 100 } add_location Add a new location Route: /api/v0/locations/ Input: location: name of the new location lat: latitude lng: longitude fixed_coordinates: 0 if updated from the device or 1 if the coordinate is fixed (default is fixed if lat and lng are valid) Example: curl -X POST -d '{\"location\":\"Google\", \"lat\":\"37.4220041\",\"lng\":\"-122.0862462\"}' -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/locations Output: { \"status\" : \"ok\" , \"message\" : \"Location added with id #45\" } delete_location Deletes an existing location Route: /api/v0/locations/:location location: name or id of the location to delete Example: curl -X DELETE -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/locations/Google Output: { \"status\" : \"ok\" , \"message\" : \"Location Google has been deleted successfully\" } edit_location Edits a location Route: /api/v0/locations/:location location: name or id of the location to edit Input: lat: latitude lng: longitude Example: curl -X PATCH -d '{\"lng\":\"100.0862462\"}' -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/locations/Google Output: { \"status\" : \"ok\" , \"message\" : \"Location updated successfully\" } get_location Gets a specific location Route: /api/v0/location/:location location: name or id of the location to get Output: { \"status\" : \"ok\" , \"get_location\" : [ { \"id\" : 1 , \"location\" : \"TEST\" , \"lat\" : 00.000000 , \"lng\" : 00.000000 , \"timestamp\" : \"2023-01-01 00:00:00\" , \"fixed_coordinates\" : 1 } ], \"count\" : 1 }","title":"Locations"},{"location":"API/Locations/#list_locations","text":"Return a list of locations. Route: /api/v0/resources/locations Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/locations Output: { \"status\" : \"ok\" , \"locations\" : [ { \"id\" : \"1\" , \"location\" : \"Example location, Example city, Example Country\" , \"lat\" : \"-18.911436\" , \"lng\" : \"47.517446\" , \"timestamp\" : \"2017-04-01 02:40:05\" }, ... ], \"count\" : 100 }","title":"list_locations"},{"location":"API/Locations/#add_location","text":"Add a new location Route: /api/v0/locations/ Input: location: name of the new location lat: latitude lng: longitude fixed_coordinates: 0 if updated from the device or 1 if the coordinate is fixed (default is fixed if lat and lng are valid) Example: curl -X POST -d '{\"location\":\"Google\", \"lat\":\"37.4220041\",\"lng\":\"-122.0862462\"}' -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/locations Output: { \"status\" : \"ok\" , \"message\" : \"Location added with id #45\" }","title":"add_location"},{"location":"API/Locations/#delete_location","text":"Deletes an existing location Route: /api/v0/locations/:location location: name or id of the location to delete Example: curl -X DELETE -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/locations/Google Output: { \"status\" : \"ok\" , \"message\" : \"Location Google has been deleted successfully\" }","title":"delete_location"},{"location":"API/Locations/#edit_location","text":"Edits a location Route: /api/v0/locations/:location location: name or id of the location to edit Input: lat: latitude lng: longitude Example: curl -X PATCH -d '{\"lng\":\"100.0862462\"}' -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/locations/Google Output: { \"status\" : \"ok\" , \"message\" : \"Location updated successfully\" }","title":"edit_location"},{"location":"API/Locations/#get_location","text":"Gets a specific location Route: /api/v0/location/:location location: name or id of the location to get Output: { \"status\" : \"ok\" , \"get_location\" : [ { \"id\" : 1 , \"location\" : \"TEST\" , \"lat\" : 00.000000 , \"lng\" : 00.000000 , \"timestamp\" : \"2023-01-01 00:00:00\" , \"fixed_coordinates\" : 1 } ], \"count\" : 1 }","title":"get_location"},{"location":"API/Logs/","text":"All the list_*logs calls are aliased to list_logs . Retrieve all logs or logs for a specific device. id or hostname is the specific device Input: start: The page number to request. limit: The limit of results to be returned. from: The date and time or the event id to search from. to: The data and time or the event id to search to. list_eventlog Route: /api/v0/logs/eventlog/:hostname list_syslog Route: /api/v0/logs/syslog/:hostname list_alertlog Route: /api/v0/logs/alertlog/:hostname list_authlog Route: /api/v0/logs/authlog/:hostname Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/eventlog/:hostname curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/syslog/:hostname?limit=20 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/eventlog/:hostname?limit=20&start=5&from=2017-07-22%2023:00:00 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/eventlog/:hostname?sortorder=DESC Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 5 , \"total\" : \"15\" , \"logs\" : [ { \"hostname\" : \"localhost\" , \"sysName\" : \"web01.1.novalocal\" , \"event_id\" : \"10050349\" , \"host\" : \"279\" , \"device_id\" : \"279\" , \"datetime\" : \"2017-07-22 19:57:47\" , \"message\" : \"ifAlias: -> \" , \"type\" : \"interface\" , \"reference\" : \"NULL\" , \"username\" : \"\" , \"severity\" : \"3\" }, .... { \"hostname\" : \"localhost\" , \"sysName\" : \"web01.1.novalocal\" , \"event_id\" : \"10050353\" , \"host\" : \"279\" , \"device_id\" : \"279\" , \"datetime\" : \"2017-07-22 19:57:47\" , \"message\" : \"ifHighSpeed: -> 0\" , \"type\" : \"interface\" , \"reference\" : \"NULL\" , \"username\" : \"\" , \"severity\" : \"3\" } ] } syslogsink Route: /api/v0/logs/syslogsink Accept any json messages and passes to further syslog processing. single messages or an array of multiple messages is accepted. see Syslog for more details and logstash integration Example curl -L -X POST 'https://sink.librenms.org/api/v0/syslogsink/' -H 'X-Auth-Token: xxxxxxxLibreNMSApiToken' --data-raw '[ { \"msg\": \"kernel: minimum Message\", \"host\": \"mydevice.fqdn.com\" }, { \"msg\": \"Line protocol on Interface GigabitEthernet1/0/41, changed state to up\", \"facility\": 23, \"priority\": \"189\", \"program\": \"LINEPROTO-5-UPDOWN\", \"host\": \"172.29.10.24\", \"@timestamp\": \"2022-12-01T20:14:28.257Z\", \"severity\": 5, \"level\": \"ERROR\" }, { \"msg\": \"kernel: a unknown host\", \"host\": \"unknown.fqdn.com\" } ]'","title":"Logs"},{"location":"API/Logs/#list_eventlog","text":"Route: /api/v0/logs/eventlog/:hostname","title":"list_eventlog"},{"location":"API/Logs/#list_syslog","text":"Route: /api/v0/logs/syslog/:hostname","title":"list_syslog"},{"location":"API/Logs/#list_alertlog","text":"Route: /api/v0/logs/alertlog/:hostname","title":"list_alertlog"},{"location":"API/Logs/#list_authlog","text":"Route: /api/v0/logs/authlog/:hostname Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/eventlog/:hostname curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/syslog/:hostname?limit=20 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/eventlog/:hostname?limit=20&start=5&from=2017-07-22%2023:00:00 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/logs/eventlog/:hostname?sortorder=DESC Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 5 , \"total\" : \"15\" , \"logs\" : [ { \"hostname\" : \"localhost\" , \"sysName\" : \"web01.1.novalocal\" , \"event_id\" : \"10050349\" , \"host\" : \"279\" , \"device_id\" : \"279\" , \"datetime\" : \"2017-07-22 19:57:47\" , \"message\" : \"ifAlias: -> \" , \"type\" : \"interface\" , \"reference\" : \"NULL\" , \"username\" : \"\" , \"severity\" : \"3\" }, .... { \"hostname\" : \"localhost\" , \"sysName\" : \"web01.1.novalocal\" , \"event_id\" : \"10050353\" , \"host\" : \"279\" , \"device_id\" : \"279\" , \"datetime\" : \"2017-07-22 19:57:47\" , \"message\" : \"ifHighSpeed: -> 0\" , \"type\" : \"interface\" , \"reference\" : \"NULL\" , \"username\" : \"\" , \"severity\" : \"3\" } ] }","title":"list_authlog"},{"location":"API/Logs/#syslogsink","text":"Route: /api/v0/logs/syslogsink Accept any json messages and passes to further syslog processing. single messages or an array of multiple messages is accepted. see Syslog for more details and logstash integration Example curl -L -X POST 'https://sink.librenms.org/api/v0/syslogsink/' -H 'X-Auth-Token: xxxxxxxLibreNMSApiToken' --data-raw '[ { \"msg\": \"kernel: minimum Message\", \"host\": \"mydevice.fqdn.com\" }, { \"msg\": \"Line protocol on Interface GigabitEthernet1/0/41, changed state to up\", \"facility\": 23, \"priority\": \"189\", \"program\": \"LINEPROTO-5-UPDOWN\", \"host\": \"172.29.10.24\", \"@timestamp\": \"2022-12-01T20:14:28.257Z\", \"severity\": 5, \"level\": \"ERROR\" }, { \"msg\": \"kernel: a unknown host\", \"host\": \"unknown.fqdn.com\" } ]'","title":"syslogsink"},{"location":"API/PollerGroups/","text":"get_poller_group Gets a specific poller group or all if none is specified Route: /api/v0/poller_group/:poller_group poller_group: optional name or id of the poller group to get Output: { \"status\" : \"ok\" , \"get_poller_group\" : [ { \"id\" : 1 , \"group_name\" : \"test\" , \"descr\" : \"test group\" } ], \"count\" : 1 }","title":"PollerGroups"},{"location":"API/PollerGroups/#get_poller_group","text":"Gets a specific poller group or all if none is specified Route: /api/v0/poller_group/:poller_group poller_group: optional name or id of the poller group to get Output: { \"status\" : \"ok\" , \"get_poller_group\" : [ { \"id\" : 1 , \"group_name\" : \"test\" , \"descr\" : \"test group\" } ], \"count\" : 1 }","title":"get_poller_group"},{"location":"API/PortGroups/","text":"get_graph_by_portgroup Get the graph based on the group type. Route: /api/v0/portgroups/:group group is the type of port group graph you want, I.e Transit, Peering, etc. You can specify multiple types comma separated. Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/portgroups/transit,peering Output: Output is an image. get_graph_by_portgroup_multiport_bits Get the graph based on the multiple port id separated by commas , . Route: /api/v0/portgroups/multiport/bits/:id id is a comma separated list of port ids you want, I.e 1,2,3,4, etc. You can specify multiple IDs comma separated. Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/portgroups/multiport/bits/1,2,3 Output: Output is an image.","title":"PortGroups"},{"location":"API/PortGroups/#get_graph_by_portgroup","text":"Get the graph based on the group type. Route: /api/v0/portgroups/:group group is the type of port group graph you want, I.e Transit, Peering, etc. You can specify multiple types comma separated. Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/portgroups/transit,peering Output: Output is an image.","title":"get_graph_by_portgroup"},{"location":"API/PortGroups/#get_graph_by_portgroup_multiport_bits","text":"Get the graph based on the multiple port id separated by commas , . Route: /api/v0/portgroups/multiport/bits/:id id is a comma separated list of port ids you want, I.e 1,2,3,4, etc. You can specify multiple IDs comma separated. Input: from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. width: The graph width, defaults to 1075. height: The graph height, defaults to 300. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/portgroups/multiport/bits/1,2,3 Output: Output is an image.","title":"get_graph_by_portgroup_multiport_bits"},{"location":"API/Port_Groups/","text":"get_port_groups List all port groups. Route: /api/v0/port_groups Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/port_groups Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 1 port groups\" , \"count\" : 1 , \"groups\" : [ { \"id\" : \"1\" , \"name\" : \"Testing\" , \"desc\" : \"Testing\" } ] } ] get_ports_by_group List all ports matching the group provided. Route: /api/v0/port_groups/:name name Is the name of the port group which can be obtained using get_port_groups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Params: full: set to any value to return all data for the devices in a given group Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/port_groups/Billable Output: { \"status\" : \"ok\" , \"ports\" : [ { \"port_id\" : 1376 }, { \"port_id\" : 2376 } ], \"count\" : 2 } add_port_group Add a new port group. Upon success, the ID of the new port group is returned and the HTTP response code is 201 . Route: /api/v0/port_groups Input (JSON): name : required - The name of the port group desc : optional - Description of the port group Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST \\ -d '{\"name\": \"New Port Group\", \\ \"desc\": \"A very fancy port group\"}' \\ https://librenms.org/api/v0/port_groups Output: { \"status\" : \"ok\" , \"id\" : 86 , \"message\" : \"Port group New Port Group created\" } assign_port_group Assign a Port Group to a list of Ports Route: /api/v0/port_groups/:port_group_id/assign Input (JSON): port_ids : required - List of Port Ids Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' -X POST -d '{\"port_ids\": [\"4\",\"34\",\"25,\"983\"]}' https://librenms.org/api/v0/port_groups/3/assign Output: { \"status\" : \"ok\" , \"Port Ids 4, 34, 25, 983 have been added to Port Group Id 3\" : 200 } remove_port_group Remove a Port Group from a list of Ports Route: /api/v0/port_groups/:port_group_id/remove Input (JSON): port_ids : required - List of Port Ids Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' -X POST -d '{\"port_ids\": [\"4\",\"34\",\"25,\"983\"]}' https://librenms.org/api/v0/port_groups/3/remove Output: { \"status\" : \"ok\" , \"Port Ids 4, 34, 25, 983 have been removed from Port Group Id 3\" : 200 }","title":"Port_Groups"},{"location":"API/Port_Groups/#get_port_groups","text":"List all port groups. Route: /api/v0/port_groups Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/port_groups Output: [ { \"status\" : \"ok\" , \"message\" : \"Found 1 port groups\" , \"count\" : 1 , \"groups\" : [ { \"id\" : \"1\" , \"name\" : \"Testing\" , \"desc\" : \"Testing\" } ] } ]","title":"get_port_groups"},{"location":"API/Port_Groups/#get_ports_by_group","text":"List all ports matching the group provided. Route: /api/v0/port_groups/:name name Is the name of the port group which can be obtained using get_port_groups . Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Params: full: set to any value to return all data for the devices in a given group Examples: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/port_groups/Billable Output: { \"status\" : \"ok\" , \"ports\" : [ { \"port_id\" : 1376 }, { \"port_id\" : 2376 } ], \"count\" : 2 }","title":"get_ports_by_group"},{"location":"API/Port_Groups/#add_port_group","text":"Add a new port group. Upon success, the ID of the new port group is returned and the HTTP response code is 201 . Route: /api/v0/port_groups Input (JSON): name : required - The name of the port group desc : optional - Description of the port group Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' \\ -X POST \\ -d '{\"name\": \"New Port Group\", \\ \"desc\": \"A very fancy port group\"}' \\ https://librenms.org/api/v0/port_groups Output: { \"status\" : \"ok\" , \"id\" : 86 , \"message\" : \"Port group New Port Group created\" }","title":"add_port_group"},{"location":"API/Port_Groups/#assign_port_group","text":"Assign a Port Group to a list of Ports Route: /api/v0/port_groups/:port_group_id/assign Input (JSON): port_ids : required - List of Port Ids Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' -X POST -d '{\"port_ids\": [\"4\",\"34\",\"25,\"983\"]}' https://librenms.org/api/v0/port_groups/3/assign Output: { \"status\" : \"ok\" , \"Port Ids 4, 34, 25, 983 have been added to Port Group Id 3\" : 200 }","title":"assign_port_group"},{"location":"API/Port_Groups/#remove_port_group","text":"Remove a Port Group from a list of Ports Route: /api/v0/port_groups/:port_group_id/remove Input (JSON): port_ids : required - List of Port Ids Examples: Dynamic Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' -X POST -d '{\"port_ids\": [\"4\",\"34\",\"25,\"983\"]}' https://librenms.org/api/v0/port_groups/3/remove Output: { \"status\" : \"ok\" , \"Port Ids 4, 34, 25, 983 have been removed from Port Group Id 3\" : 200 }","title":"remove_port_group"},{"location":"API/Ports/","text":"get_all_ports Get info for all ports on all devices. Strongly recommend that you use the columns parameter to avoid pulling too much data. Route: /api/v0/ports - Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports?columns=ifName%2Cport_id Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"ports\" : [ { \"ifName\" : \"Gi0/0/0\" , \"port_id\" : \"1\" }, { \"ifName\" : \"Gi0/0/1\" , \"port_id\" : \"2\" }, ... { \"ifName\" : \"Vlan 3615\" , \"port_id\" : \"5488\" } ] } search_ports Search for ports matching the query. Route: /api/v0/ports/search/:search search string to search in fields: ifAlias, ifDescr, and ifName Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/search/lo Output: { \"status\" : \"ok\" , \"ports\" : [ { \"device_id\" : 1 , \"port_id\" : 1 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 2 , \"port_id\" : 3 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 3 , \"port_id\" : 5 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" } ] } search_ports in specific field(s) Specific search for ports matching the query. Route: /api/v0/ports/search/:field/:search field: comma separated list of field(s) to search search: string to search in fields Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/search/ifName/lo Output: { \"status\" : \"ok\" , \"ports\" : [ { \"device_id\" : 1 , \"port_id\" : 1 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 2 , \"port_id\" : 3 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 3 , \"port_id\" : 5 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" } ] } ports_with_associated_mac Search for ports matching the search mac. Route: /api/v0/ports/mac/:search?filter=first search a mac address in fdb and print the ports ordered by the mac count of the associated port. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/mac/00:11:22:33:44:55 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/mac/001122.334455?filter=first curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/mac/001122334455?filter=first Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"port\" : [ { \"port_id\" : \"323\" , \"device_id\" : \"55\" , \"port_descr_type\" : null , \"port_descr_descr\" : null , \"port_descr_circuit\" : null , \"port_descr_speed\" : null , \"port_descr_notes\" : null , \"ifDescr\" : \"GigabitEthernet0/0/0\" , \"ifName\" : \"Gi0/0/0\" , \"portName\" : null , \"ifIndex\" : \"1\" , \"ifSpeed\" : \"1000000000\" , \"ifConnectorPresent\" : \"true\" , \"ifPromiscuousMode\" : \"false\" , \"ifHighSpeed\" : \"1000\" , \"ifOperStatus\" : \"up\" , \"ifOperStatus_prev\" : null , \"ifAdminStatus\" : \"up\" , \"ifAdminStatus_prev\" : null , \"ifDuplex\" : \"fullDuplex\" , \"ifMtu\" : \"1560\" , \"ifType\" : \"ethernetCsmacd\" , \"ifAlias\" : \"ASR Interconnect Trunk\" , \"ifPhysAddress\" : \"84bf20853e00\" , \"ifHardType\" : null , \"ifLastChange\" : \"42407358\" , \"ifVlan\" : \"\" , \"ifTrunk\" : \"\" , \"ifVrf\" : \"0\" , \"counter_in\" : null , \"counter_out\" : null , \"ignore\" : \"0\" , \"disabled\" : \"0\" , \"detailed\" : \"0\" , \"deleted\" : \"0\" , \"pagpOperationMode\" : null , \"pagpPortState\" : null , \"pagpPartnerDeviceId\" : null , \"pagpPartnerLearnMethod\" : null , \"pagpPartnerIfIndex\" : null , \"pagpPartnerGroupIfIndex\" : null , \"pagpPartnerDeviceName\" : null , \"pagpEthcOperationMode\" : null , \"pagpDeviceId\" : null , \"pagpGroupIfIndex\" : null , \"ifInUcastPkts\" : \"128518576\" , \"ifInUcastPkts_prev\" : \"128517284\" , \"ifInUcastPkts_delta\" : \"1292\" , \"ifInUcastPkts_rate\" : \"4\" , \"ifOutUcastPkts\" : \"128510560\" , \"ifOutUcastPkts_prev\" : \"128509268\" , \"ifOutUcastPkts_delta\" : \"1292\" , \"ifOutUcastPkts_rate\" : \"4\" , \"ifInErrors\" : \"0\" , \"ifInErrors_prev\" : \"0\" , \"ifInErrors_delta\" : \"0\" , \"ifInErrors_rate\" : \"0\" , \"ifOutErrors\" : \"0\" , \"ifOutErrors_prev\" : \"0\" , \"ifOutErrors_delta\" : \"0\" , \"ifOutErrors_rate\" : \"0\" , \"ifInOctets\" : \"12827393730\" , \"ifInOctets_prev\" : \"12827276736\" , \"ifInOctets_delta\" : \"116994\" , \"ifInOctets_rate\" : \"387\" , \"ifOutOctets\" : \"14957481766\" , \"ifOutOctets_prev\" : \"14957301765\" , \"ifOutOctets_delta\" : \"180001\" , \"ifOutOctets_rate\" : \"596\" , \"poll_time\" : \"1483779150\" , \"poll_prev\" : \"1483778848\" , \"poll_period\" : \"302\" } ] } get_port_info Get all info for a particular port. Route: /api/v0/ports/:portid portid must be an integer Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"port\" : [ { \"port_id\" : \"323\" , \"device_id\" : \"55\" , \"port_descr_type\" : null , \"port_descr_descr\" : null , \"port_descr_circuit\" : null , \"port_descr_speed\" : null , \"port_descr_notes\" : null , \"ifDescr\" : \"GigabitEthernet0/0/0\" , \"ifName\" : \"Gi0/0/0\" , \"portName\" : null , \"ifIndex\" : \"1\" , \"ifSpeed\" : \"1000000000\" , \"ifConnectorPresent\" : \"true\" , \"ifPromiscuousMode\" : \"false\" , \"ifHighSpeed\" : \"1000\" , \"ifOperStatus\" : \"up\" , \"ifOperStatus_prev\" : null , \"ifAdminStatus\" : \"up\" , \"ifAdminStatus_prev\" : null , \"ifDuplex\" : \"fullDuplex\" , \"ifMtu\" : \"1560\" , \"ifType\" : \"ethernetCsmacd\" , \"ifAlias\" : \"ASR Interconnect Trunk\" , \"ifPhysAddress\" : \"84bf20853e00\" , \"ifHardType\" : null , \"ifLastChange\" : \"42407358\" , \"ifVlan\" : \"\" , \"ifTrunk\" : \"\" , \"ifVrf\" : \"0\" , \"counter_in\" : null , \"counter_out\" : null , \"ignore\" : \"0\" , \"disabled\" : \"0\" , \"detailed\" : \"0\" , \"deleted\" : \"0\" , \"pagpOperationMode\" : null , \"pagpPortState\" : null , \"pagpPartnerDeviceId\" : null , \"pagpPartnerLearnMethod\" : null , \"pagpPartnerIfIndex\" : null , \"pagpPartnerGroupIfIndex\" : null , \"pagpPartnerDeviceName\" : null , \"pagpEthcOperationMode\" : null , \"pagpDeviceId\" : null , \"pagpGroupIfIndex\" : null , \"ifInUcastPkts\" : \"128518576\" , \"ifInUcastPkts_prev\" : \"128517284\" , \"ifInUcastPkts_delta\" : \"1292\" , \"ifInUcastPkts_rate\" : \"4\" , \"ifOutUcastPkts\" : \"128510560\" , \"ifOutUcastPkts_prev\" : \"128509268\" , \"ifOutUcastPkts_delta\" : \"1292\" , \"ifOutUcastPkts_rate\" : \"4\" , \"ifInErrors\" : \"0\" , \"ifInErrors_prev\" : \"0\" , \"ifInErrors_delta\" : \"0\" , \"ifInErrors_rate\" : \"0\" , \"ifOutErrors\" : \"0\" , \"ifOutErrors_prev\" : \"0\" , \"ifOutErrors_delta\" : \"0\" , \"ifOutErrors_rate\" : \"0\" , \"ifInOctets\" : \"12827393730\" , \"ifInOctets_prev\" : \"12827276736\" , \"ifInOctets_delta\" : \"116994\" , \"ifInOctets_rate\" : \"387\" , \"ifOutOctets\" : \"14957481766\" , \"ifOutOctets_prev\" : \"14957301765\" , \"ifOutOctets_delta\" : \"180001\" , \"ifOutOctets_rate\" : \"596\" , \"poll_time\" : \"1483779150\" , \"poll_prev\" : \"1483778848\" , \"poll_period\" : \"302\" } ] } get_port_ip_info Get all IP info (v4 and v6) for a given port id. Route: /api/v0/ports/:portid/ip portid must be an integer Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323/ip Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"addresses\" : [ { \"ipv4_address_id\" : \"290\" , \"ipv4_address\" : \"192.168.99.292\" , \"ipv4_prefixlen\" : \"30\" , \"ipv4_network_id\" : \"247\" , \"port_id\" : \"323\" , \"context_name\" : \"\" } ] } get_port_description Get the description ( ifAlias ) for a given port id. Route: /api/v0/ports/:portid/description Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323/description Output: { \"status\" : \"ok\" , \"port_description\" : \"GigabitEthernet14\" } update_port_description Change the description ( ifAlias ) for a given port id. Route: /api/v0/ports/:portid/description Input (JSON): description: The string data to use as the new port description. Sending an empty string will reset the description to default. Example: curl -X PATCH -d '{\"description\": \"Out-of-Band Management Link\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323/description Output: { \"status\" : \"ok\" , \"message\" : \"Port description updated.\" }","title":"Ports"},{"location":"API/Ports/#get_all_ports","text":"Get info for all ports on all devices. Strongly recommend that you use the columns parameter to avoid pulling too much data. Route: /api/v0/ports - Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports?columns=ifName%2Cport_id Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"ports\" : [ { \"ifName\" : \"Gi0/0/0\" , \"port_id\" : \"1\" }, { \"ifName\" : \"Gi0/0/1\" , \"port_id\" : \"2\" }, ... { \"ifName\" : \"Vlan 3615\" , \"port_id\" : \"5488\" } ] }","title":"get_all_ports"},{"location":"API/Ports/#search_ports","text":"Search for ports matching the query. Route: /api/v0/ports/search/:search search string to search in fields: ifAlias, ifDescr, and ifName Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/search/lo Output: { \"status\" : \"ok\" , \"ports\" : [ { \"device_id\" : 1 , \"port_id\" : 1 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 2 , \"port_id\" : 3 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 3 , \"port_id\" : 5 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" } ] }","title":"search_ports"},{"location":"API/Ports/#search_ports-in-specific-fields","text":"Specific search for ports matching the query. Route: /api/v0/ports/search/:field/:search field: comma separated list of field(s) to search search: string to search in fields Input: columns: Comma separated list of columns you want returned. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/search/ifName/lo Output: { \"status\" : \"ok\" , \"ports\" : [ { \"device_id\" : 1 , \"port_id\" : 1 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 2 , \"port_id\" : 3 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" }, { \"device_id\" : 3 , \"port_id\" : 5 , \"ifIndex\" : 1 , \"ifName\" : \"lo\" } ] }","title":"search_ports in specific field(s)"},{"location":"API/Ports/#ports_with_associated_mac","text":"Search for ports matching the search mac. Route: /api/v0/ports/mac/:search?filter=first search a mac address in fdb and print the ports ordered by the mac count of the associated port. Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/mac/00:11:22:33:44:55 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/mac/001122.334455?filter=first curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/mac/001122334455?filter=first Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"port\" : [ { \"port_id\" : \"323\" , \"device_id\" : \"55\" , \"port_descr_type\" : null , \"port_descr_descr\" : null , \"port_descr_circuit\" : null , \"port_descr_speed\" : null , \"port_descr_notes\" : null , \"ifDescr\" : \"GigabitEthernet0/0/0\" , \"ifName\" : \"Gi0/0/0\" , \"portName\" : null , \"ifIndex\" : \"1\" , \"ifSpeed\" : \"1000000000\" , \"ifConnectorPresent\" : \"true\" , \"ifPromiscuousMode\" : \"false\" , \"ifHighSpeed\" : \"1000\" , \"ifOperStatus\" : \"up\" , \"ifOperStatus_prev\" : null , \"ifAdminStatus\" : \"up\" , \"ifAdminStatus_prev\" : null , \"ifDuplex\" : \"fullDuplex\" , \"ifMtu\" : \"1560\" , \"ifType\" : \"ethernetCsmacd\" , \"ifAlias\" : \"ASR Interconnect Trunk\" , \"ifPhysAddress\" : \"84bf20853e00\" , \"ifHardType\" : null , \"ifLastChange\" : \"42407358\" , \"ifVlan\" : \"\" , \"ifTrunk\" : \"\" , \"ifVrf\" : \"0\" , \"counter_in\" : null , \"counter_out\" : null , \"ignore\" : \"0\" , \"disabled\" : \"0\" , \"detailed\" : \"0\" , \"deleted\" : \"0\" , \"pagpOperationMode\" : null , \"pagpPortState\" : null , \"pagpPartnerDeviceId\" : null , \"pagpPartnerLearnMethod\" : null , \"pagpPartnerIfIndex\" : null , \"pagpPartnerGroupIfIndex\" : null , \"pagpPartnerDeviceName\" : null , \"pagpEthcOperationMode\" : null , \"pagpDeviceId\" : null , \"pagpGroupIfIndex\" : null , \"ifInUcastPkts\" : \"128518576\" , \"ifInUcastPkts_prev\" : \"128517284\" , \"ifInUcastPkts_delta\" : \"1292\" , \"ifInUcastPkts_rate\" : \"4\" , \"ifOutUcastPkts\" : \"128510560\" , \"ifOutUcastPkts_prev\" : \"128509268\" , \"ifOutUcastPkts_delta\" : \"1292\" , \"ifOutUcastPkts_rate\" : \"4\" , \"ifInErrors\" : \"0\" , \"ifInErrors_prev\" : \"0\" , \"ifInErrors_delta\" : \"0\" , \"ifInErrors_rate\" : \"0\" , \"ifOutErrors\" : \"0\" , \"ifOutErrors_prev\" : \"0\" , \"ifOutErrors_delta\" : \"0\" , \"ifOutErrors_rate\" : \"0\" , \"ifInOctets\" : \"12827393730\" , \"ifInOctets_prev\" : \"12827276736\" , \"ifInOctets_delta\" : \"116994\" , \"ifInOctets_rate\" : \"387\" , \"ifOutOctets\" : \"14957481766\" , \"ifOutOctets_prev\" : \"14957301765\" , \"ifOutOctets_delta\" : \"180001\" , \"ifOutOctets_rate\" : \"596\" , \"poll_time\" : \"1483779150\" , \"poll_prev\" : \"1483778848\" , \"poll_period\" : \"302\" } ] }","title":"ports_with_associated_mac"},{"location":"API/Ports/#get_port_info","text":"Get all info for a particular port. Route: /api/v0/ports/:portid portid must be an integer Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"port\" : [ { \"port_id\" : \"323\" , \"device_id\" : \"55\" , \"port_descr_type\" : null , \"port_descr_descr\" : null , \"port_descr_circuit\" : null , \"port_descr_speed\" : null , \"port_descr_notes\" : null , \"ifDescr\" : \"GigabitEthernet0/0/0\" , \"ifName\" : \"Gi0/0/0\" , \"portName\" : null , \"ifIndex\" : \"1\" , \"ifSpeed\" : \"1000000000\" , \"ifConnectorPresent\" : \"true\" , \"ifPromiscuousMode\" : \"false\" , \"ifHighSpeed\" : \"1000\" , \"ifOperStatus\" : \"up\" , \"ifOperStatus_prev\" : null , \"ifAdminStatus\" : \"up\" , \"ifAdminStatus_prev\" : null , \"ifDuplex\" : \"fullDuplex\" , \"ifMtu\" : \"1560\" , \"ifType\" : \"ethernetCsmacd\" , \"ifAlias\" : \"ASR Interconnect Trunk\" , \"ifPhysAddress\" : \"84bf20853e00\" , \"ifHardType\" : null , \"ifLastChange\" : \"42407358\" , \"ifVlan\" : \"\" , \"ifTrunk\" : \"\" , \"ifVrf\" : \"0\" , \"counter_in\" : null , \"counter_out\" : null , \"ignore\" : \"0\" , \"disabled\" : \"0\" , \"detailed\" : \"0\" , \"deleted\" : \"0\" , \"pagpOperationMode\" : null , \"pagpPortState\" : null , \"pagpPartnerDeviceId\" : null , \"pagpPartnerLearnMethod\" : null , \"pagpPartnerIfIndex\" : null , \"pagpPartnerGroupIfIndex\" : null , \"pagpPartnerDeviceName\" : null , \"pagpEthcOperationMode\" : null , \"pagpDeviceId\" : null , \"pagpGroupIfIndex\" : null , \"ifInUcastPkts\" : \"128518576\" , \"ifInUcastPkts_prev\" : \"128517284\" , \"ifInUcastPkts_delta\" : \"1292\" , \"ifInUcastPkts_rate\" : \"4\" , \"ifOutUcastPkts\" : \"128510560\" , \"ifOutUcastPkts_prev\" : \"128509268\" , \"ifOutUcastPkts_delta\" : \"1292\" , \"ifOutUcastPkts_rate\" : \"4\" , \"ifInErrors\" : \"0\" , \"ifInErrors_prev\" : \"0\" , \"ifInErrors_delta\" : \"0\" , \"ifInErrors_rate\" : \"0\" , \"ifOutErrors\" : \"0\" , \"ifOutErrors_prev\" : \"0\" , \"ifOutErrors_delta\" : \"0\" , \"ifOutErrors_rate\" : \"0\" , \"ifInOctets\" : \"12827393730\" , \"ifInOctets_prev\" : \"12827276736\" , \"ifInOctets_delta\" : \"116994\" , \"ifInOctets_rate\" : \"387\" , \"ifOutOctets\" : \"14957481766\" , \"ifOutOctets_prev\" : \"14957301765\" , \"ifOutOctets_delta\" : \"180001\" , \"ifOutOctets_rate\" : \"596\" , \"poll_time\" : \"1483779150\" , \"poll_prev\" : \"1483778848\" , \"poll_period\" : \"302\" } ] }","title":"get_port_info"},{"location":"API/Ports/#get_port_ip_info","text":"Get all IP info (v4 and v6) for a given port id. Route: /api/v0/ports/:portid/ip portid must be an integer Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323/ip Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"addresses\" : [ { \"ipv4_address_id\" : \"290\" , \"ipv4_address\" : \"192.168.99.292\" , \"ipv4_prefixlen\" : \"30\" , \"ipv4_network_id\" : \"247\" , \"port_id\" : \"323\" , \"context_name\" : \"\" } ] }","title":"get_port_ip_info"},{"location":"API/Ports/#get_port_description","text":"Get the description ( ifAlias ) for a given port id. Route: /api/v0/ports/:portid/description Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323/description Output: { \"status\" : \"ok\" , \"port_description\" : \"GigabitEthernet14\" }","title":"get_port_description"},{"location":"API/Ports/#update_port_description","text":"Change the description ( ifAlias ) for a given port id. Route: /api/v0/ports/:portid/description Input (JSON): description: The string data to use as the new port description. Sending an empty string will reset the description to default. Example: curl -X PATCH -d '{\"description\": \"Out-of-Band Management Link\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ports/323/description Output: { \"status\" : \"ok\" , \"message\" : \"Port description updated.\" }","title":"update_port_description"},{"location":"API/Routing/","text":"list_bgp List the current BGP sessions. Route: /api/v0/bgp Input: hostname = Either the devices hostname or id. asn = The local ASN you would like to filter by remote_asn = Filter by remote peer ASN remote_address = Filter by remote peer address local_address = Filter by local address bgp_descr = Filter by BGP neighbor description bgp_state = Filter by BGP session state (like established,idle...) bgp_state = Filter by BGP admin state (start,stop,running...) bgp_family = Filter by BGP address Family (4,6) Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?hostname=host.example.com curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?asn=1234 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?remote_asn=1234 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?local_address=1.1.1.1&remote_address=2.2.2.2 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_descr=UPSTREAM curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_state=established curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_adminstate=start curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_family=6 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_state=idle&bgp_descr=CORE&bgp_family=4 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"bgp_sessions\" : [ { \"bgpPeer_id\" : 1260 , \"device_id\" : 7 , \"vrf_id\" : null , \"astext\" : \"Acme Ltd\" , \"bgpPeerIdentifier\" : \"2001:0DB8:0000:24cb:0000:0000:0000:0001\" , \"bgpPeerRemoteAs\" : 65432 , \"bgpPeerState\" : \"established\" , \"bgpPeerAdminStatus\" : \"start\" , \"bgpPeerLastErrorCode\" : 6 , \"bgpPeerLastErrorSubCode\" : 2 , \"bgpPeerLastErrorText\" : \"administrative shutdown\" , \"bgpPeerIface\" : 268 , \"bgpLocalAddr\" : \"2001:0DB8:0000:24cb:0000:0000:0000:0002\" , \"bgpPeerRemoteAddr\" : \"0.0.0.0\" , \"bgpPeerDescr\" : \"Another one #CORE\" , \"bgpPeerInUpdates\" : 283882969 , \"bgpPeerOutUpdates\" : 7008 , \"bgpPeerInTotalMessages\" : 283883031 , \"bgpPeerOutTotalMessages\" : 1386692 , \"bgpPeerFsmEstablishedTime\" : 1628487 , \"bgpPeerInUpdateElapsedTime\" : 0 , \"context_name\" : \"\" }, ... ], \"count\" : 100 } get_bgp Retrieves a BGP session by ID Route: /api/v0/bgp/:id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp/4 Output: { \"status\" : \"ok\" , \"bgp_session\" : [ { \"bgpPeer_id\" : \"4\" , \"device_id\" : \"2\" , \"astext\" : \"\" , \"bgpPeerIdentifier\" : \"1234:1b80:1:12::2\" , \"bgpPeerRemoteAs\" : \"54321\" , \"bgpPeerState\" : \"established\" , \"bgpPeerAdminStatus\" : \"running\" , \"bgpLocalAddr\" : \"1234:1b80:1:12::1\" , \"bgpPeerRemoteAddr\" : \"0.0.0.0\" , \"bgpPeerInUpdates\" : \"3\" , \"bgpPeerOutUpdates\" : \"1\" , \"bgpPeerInTotalMessages\" : \"0\" , \"bgpPeerOutTotalMessages\" : \"0\" , \"bgpPeerFsmEstablishedTime\" : \"0\" , \"bgpPeerInUpdateElapsedTime\" : \"0\" , \"context_name\" : \"\" } ], \"count\" : 1 } edit_bgp_descr This is a POST type request Set the BGP session description by ID Route: /api/v0/bgp/:id Input: id = The id of the BGP Peer Session. bgp_descr = The description for the bgpPeerDescr field on the BGP Session. Example: curl -v -H 'X-Auth-Token: YOURAPITOKENHERE' --data '{\"bgp_descr\": \"Your description here\"}' https://librenms.org/api/v0/bgp/4 Output: { \"status\" : \"ok\" , \"message\" : \"BGP description for peer X.X.X.X on device 1 updated to Your description here\" } list_cbgp List the current BGP sessions counters. Route: /api/v0/routing/bgp/cbgp Input: hostname = Either the devices hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/bgp/cbgp curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/bgp/cbgp?hostname=host.example.com Output: { \"status\" : \"ok\" , \"bgp_counters\" : [ { \"device_id\" : \"9\" , \"bgpPeerIdentifier\" : \"192.168.99.31\" , \"afi\" : \"ipv4\" , \"safi\" : \"multicast\" , \"AcceptedPrefixes\" : \"2\" , \"DeniedPrefixes\" : \"0\" , \"PrefixAdminLimit\" : \"0\" , \"PrefixThreshold\" : \"0\" , \"PrefixClearThreshold\" : \"0\" , \"AdvertisedPrefixes\" : \"11487\" , \"SuppressedPrefixes\" : \"0\" , \"WithdrawnPrefixes\" : \"10918\" , \"AcceptedPrefixes_delta\" : \"-2\" , \"AcceptedPrefixes_prev\" : \"2\" , \"DeniedPrefixes_delta\" : \"0\" , \"DeniedPrefixes_prev\" : \"0\" , \"AdvertisedPrefixes_delta\" : \"-11487\" , \"AdvertisedPrefixes_prev\" : \"11487\" , \"SuppressedPrefixes_delta\" : \"0\" , \"SuppressedPrefixes_prev\" : \"0\" , \"WithdrawnPrefixes_delta\" : \"-10918\" , \"WithdrawnPrefixes_prev\" : \"10918\" , \"context_name\" : \"\" }, ... ], \"count\" : 100 } list_ip_addresses List all IPv4 and IPv6 addresses. Route: /api/v0/resources/ip/addresses Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/addresses Output: { \"status\" : \"ok\" , \"ip_addresses\" : [ { \"ipv4_address_id\" : \"69\" , \"ipv4_address\" : \"127.0.0.1\" , \"ipv4_prefixlen\" : \"8\" , \"ipv4_network_id\" : \"55\" , \"port_id\" : \"135\" , \"context_name\" : \"\" }, ... ], \"count\" : 55 } get_network_ip_addresses Get all IPv4 and IPv6 addresses for particular network. Route: /api/v0/resources/ip/networks/:id/ip id must be integer Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/networks/55/ip Output: { \"status\" : \"ok\" , \"addresses\" : [ { \"ipv4_address_id\" : \"69\" , \"ipv4_address\" : \"127.0.0.1\" , \"ipv4_prefixlen\" : \"8\" , \"ipv4_network_id\" : \"55\" , \"port_id\" : \"135\" , \"context_name\" : \"\" } ], \"count\" : 1 } list_ip_networks List all IPv4 and IPv6 networks. Route: /api/v0/resources/ip/networks Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/networks Output: { \"status\" : \"ok\" , \"ip_networks\" : [ { \"ipv4_network_id\" : \"1\" , \"ipv4_network\" : \"127.0.0.0/8\" , \"context_name\" : \"\" }, ... ], \"count\" : 100 } list_ipsec List the current IPSec tunnels which are active. Route: /api/v0/routing/ipsec/data/:hostname hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/ipsec/data/localhost Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 0 , \"ipsec\" : [ \"tunnel_id\" : \"1\" , \"device_id\" : \"1\" , \"peer_port\" : \"0\" , \"peer_addr\" : \"127.0.0.1\" , \"local_addr\" : \"127.0.0.2\" , \"local_port\" : \"0\" , \"tunnel_name\" : \"\" , \"tunnel_status\" : \"active\" ] } Please note, this will only show active VPN sessions not all configured. list_ospf List the current OSPF neighbours. Route: /api/v0/ospf Input: hostname = Either the devices hostname or id. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ospf curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ospf?hostname=host.example.com Output: { \"status\" : \"ok\" , \"ospf_neighbours\" : [ { \"device_id\" : \"1\" , \"port_id\" : \"0\" , \"ospf_nbr_id\" : \"172.16.1.145.0\" , \"ospfNbrIpAddr\" : \"172.16.1.145\" , \"ospfNbrAddressLessIndex\" : \"0\" , \"ospfNbrRtrId\" : \"172.16.0.140\" , \"ospfNbrOptions\" : \"82\" , \"ospfNbrPriority\" : \"1\" , \"ospfNbrState\" : \"full\" , \"ospfNbrEvents\" : \"5\" , \"ospfNbrLsRetransQLen\" : \"0\" , \"ospfNbmaNbrStatus\" : \"active\" , \"ospfNbmaNbrPermanence\" : \"dynamic\" , \"ospfNbrHelloSuppressed\" : \"false\" , \"context_name\" : \"\" } ], \"count\" : 1 } list_ospf_ports List the current OSPF ports. Route: /api/v0/ospf_ports Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ospf_ports Output: { \"status\" : \"ok\" , \"ospf_ports\" : [ { \"id\" : 189086 , \"device_id\" : 43 , \"port_id\" : 2838 , \"ospf_port_id\" : \"10.10.2.86.0\" , \"ospfIfIpAddress\" : \"10.10.2.86\" , \"ospfAddressLessIf\" : 0 , \"ospfIfAreaId\" : \"0.0.0.0\" , \"ospfIfType\" : \"pointToPoint\" , \"ospfIfAdminStat\" : \"enabled\" , \"ospfIfRtrPriority\" : 128 , \"ospfIfTransitDelay\" : 1 , \"ospfIfRetransInterval\" : 5 , \"ospfIfHelloInterval\" : 10 , \"ospfIfRtrDeadInterval\" : 40 , \"ospfIfPollInterval\" : 90 , \"ospfIfState\" : \"pointToPoint\" , \"ospfIfDesignatedRouter\" : \"0.0.0.0\" , \"ospfIfBackupDesignatedRouter\" : \"0.0.0.0\" , \"ospfIfEvents\" : 33 , \"ospfIfAuthKey\" : \"\" , \"ospfIfStatus\" : \"active\" , \"ospfIfMulticastForwarding\" : \"unicast\" , \"ospfIfDemand\" : \"false\" , \"ospfIfAuthType\" : \"0\" , \"ospfIfMetricIpAddress\" : \"10.10.2.86\" , \"ospfIfMetricAddressLessIf\" : 0 , \"ospfIfMetricTOS\" : 0 , \"ospfIfMetricValue\" : 10 , \"ospfIfMetricStatus\" : \"active\" , \"context_name\" : null } ], \"count\" : 1 } list_vrf List the current VRFs. Route: /api/v0/routing/vrf Input: hostname = Either the devices hostname or id OR vrfname = The VRF name you would like to filter by Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf?hostname=host.example.com curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf?vrfname=Mgmt-vrf Output: { \"status\" : \"ok\" , \"vrfs\" : [ { \"vrf_id\" : \"2\" , \"vrf_oid\" : \"8.77.103.109.116.45.118.114.102\" , \"vrf_name\" : \"Mgmt-vrf\" , \"mplsVpnVrfRouteDistinguisher\" : \"\" , \"mplsVpnVrfDescription\" : \"\" , \"device_id\" : \"8\" }, ... ], \"count\" : 100 } get_vrf Retrieves VRF by ID Route: /api/v0/routing/vrf/:id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf/2 Output: { \"status\" : \"ok\" , \"vrf\" : [ { \"vrf_id\" : \"2\" , \"vrf_oid\" : \"8.77.103.109.116.45.118.114.102\" , \"vrf_name\" : \"Mgmt-vrf\" , \"mplsVpnVrfRouteDistinguisher\" : \"\" , \"mplsVpnVrfDescription\" : \"\" , \"device_id\" : \"8\" } ], \"count\" : 1 } list_mpls_services List MPLS services Route: /api/v0/routing/mpls/services Input: hostname = Either the devices hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/services curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/services?hostname=host.example.com Output: { \"status\" : \"ok\" , \"mpls_services\" : [ { \"svc_id\" : 1671 , \"svc_oid\" : 27 , \"device_id\" : 4 , \"svcRowStatus\" : \"active\" , \"svcType\" : \"tls\" , \"svcCustId\" : 1 , \"svcAdminStatus\" : \"up\" , \"svcOperStatus\" : \"up\" , \"svcDescription\" : \"\" , \"svcMtu\" : 9008 , \"svcNumSaps\" : 1 , \"svcNumSdps\" : 0 , \"svcLastMgmtChange\" : 2 , \"svcLastStatusChange\" : 168 , \"svcVRouterId\" : 0 , \"svcTlsMacLearning\" : \"enabled\" , \"svcTlsStpAdminStatus\" : \"disabled\" , \"svcTlsStpOperStatus\" : \"down\" , \"svcTlsFdbTableSize\" : 250 , \"svcTlsFdbNumEntries\" : 0 , \"hostname\" : \"host.example.com\" } ], \"count\" : 1 } list_mpls_saps List MPLS SAPs Route: /api/v0/routing/mpls/saps Input: hostname = Either the devices hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/saps curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/saps?hostname=host.example.com Output: { \"status\" : \"ok\" , \"saps\" : [ { \"sap_id\" : 1935 , \"svc_id\" : 1660 , \"svc_oid\" : 7 , \"sapPortId\" : 16108921125 , \"ifName\" : \"1/1/c2/1\" , \"device_id\" : 3 , \"sapEncapValue\" : \"0\" , \"sapRowStatus\" : \"active\" , \"sapType\" : \"epipe\" , \"sapDescription\" : \"\" , \"sapAdminStatus\" : \"up\" , \"sapOperStatus\" : \"down\" , \"sapLastMgmtChange\" : 2 , \"sapLastStatusChange\" : 0 , \"hostname\" : \"hostname=host.example.com\" } ], \"count\" : 1 }","title":"Routing"},{"location":"API/Routing/#list_bgp","text":"List the current BGP sessions. Route: /api/v0/bgp Input: hostname = Either the devices hostname or id. asn = The local ASN you would like to filter by remote_asn = Filter by remote peer ASN remote_address = Filter by remote peer address local_address = Filter by local address bgp_descr = Filter by BGP neighbor description bgp_state = Filter by BGP session state (like established,idle...) bgp_state = Filter by BGP admin state (start,stop,running...) bgp_family = Filter by BGP address Family (4,6) Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?hostname=host.example.com curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?asn=1234 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?remote_asn=1234 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?local_address=1.1.1.1&remote_address=2.2.2.2 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_descr=UPSTREAM curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_state=established curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_adminstate=start curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_family=6 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp?bgp_state=idle&bgp_descr=CORE&bgp_family=4 Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"bgp_sessions\" : [ { \"bgpPeer_id\" : 1260 , \"device_id\" : 7 , \"vrf_id\" : null , \"astext\" : \"Acme Ltd\" , \"bgpPeerIdentifier\" : \"2001:0DB8:0000:24cb:0000:0000:0000:0001\" , \"bgpPeerRemoteAs\" : 65432 , \"bgpPeerState\" : \"established\" , \"bgpPeerAdminStatus\" : \"start\" , \"bgpPeerLastErrorCode\" : 6 , \"bgpPeerLastErrorSubCode\" : 2 , \"bgpPeerLastErrorText\" : \"administrative shutdown\" , \"bgpPeerIface\" : 268 , \"bgpLocalAddr\" : \"2001:0DB8:0000:24cb:0000:0000:0000:0002\" , \"bgpPeerRemoteAddr\" : \"0.0.0.0\" , \"bgpPeerDescr\" : \"Another one #CORE\" , \"bgpPeerInUpdates\" : 283882969 , \"bgpPeerOutUpdates\" : 7008 , \"bgpPeerInTotalMessages\" : 283883031 , \"bgpPeerOutTotalMessages\" : 1386692 , \"bgpPeerFsmEstablishedTime\" : 1628487 , \"bgpPeerInUpdateElapsedTime\" : 0 , \"context_name\" : \"\" }, ... ], \"count\" : 100 }","title":"list_bgp"},{"location":"API/Routing/#get_bgp","text":"Retrieves a BGP session by ID Route: /api/v0/bgp/:id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/bgp/4 Output: { \"status\" : \"ok\" , \"bgp_session\" : [ { \"bgpPeer_id\" : \"4\" , \"device_id\" : \"2\" , \"astext\" : \"\" , \"bgpPeerIdentifier\" : \"1234:1b80:1:12::2\" , \"bgpPeerRemoteAs\" : \"54321\" , \"bgpPeerState\" : \"established\" , \"bgpPeerAdminStatus\" : \"running\" , \"bgpLocalAddr\" : \"1234:1b80:1:12::1\" , \"bgpPeerRemoteAddr\" : \"0.0.0.0\" , \"bgpPeerInUpdates\" : \"3\" , \"bgpPeerOutUpdates\" : \"1\" , \"bgpPeerInTotalMessages\" : \"0\" , \"bgpPeerOutTotalMessages\" : \"0\" , \"bgpPeerFsmEstablishedTime\" : \"0\" , \"bgpPeerInUpdateElapsedTime\" : \"0\" , \"context_name\" : \"\" } ], \"count\" : 1 }","title":"get_bgp"},{"location":"API/Routing/#edit_bgp_descr","text":"This is a POST type request Set the BGP session description by ID Route: /api/v0/bgp/:id Input: id = The id of the BGP Peer Session. bgp_descr = The description for the bgpPeerDescr field on the BGP Session. Example: curl -v -H 'X-Auth-Token: YOURAPITOKENHERE' --data '{\"bgp_descr\": \"Your description here\"}' https://librenms.org/api/v0/bgp/4 Output: { \"status\" : \"ok\" , \"message\" : \"BGP description for peer X.X.X.X on device 1 updated to Your description here\" }","title":"edit_bgp_descr"},{"location":"API/Routing/#list_cbgp","text":"List the current BGP sessions counters. Route: /api/v0/routing/bgp/cbgp Input: hostname = Either the devices hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/bgp/cbgp curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/bgp/cbgp?hostname=host.example.com Output: { \"status\" : \"ok\" , \"bgp_counters\" : [ { \"device_id\" : \"9\" , \"bgpPeerIdentifier\" : \"192.168.99.31\" , \"afi\" : \"ipv4\" , \"safi\" : \"multicast\" , \"AcceptedPrefixes\" : \"2\" , \"DeniedPrefixes\" : \"0\" , \"PrefixAdminLimit\" : \"0\" , \"PrefixThreshold\" : \"0\" , \"PrefixClearThreshold\" : \"0\" , \"AdvertisedPrefixes\" : \"11487\" , \"SuppressedPrefixes\" : \"0\" , \"WithdrawnPrefixes\" : \"10918\" , \"AcceptedPrefixes_delta\" : \"-2\" , \"AcceptedPrefixes_prev\" : \"2\" , \"DeniedPrefixes_delta\" : \"0\" , \"DeniedPrefixes_prev\" : \"0\" , \"AdvertisedPrefixes_delta\" : \"-11487\" , \"AdvertisedPrefixes_prev\" : \"11487\" , \"SuppressedPrefixes_delta\" : \"0\" , \"SuppressedPrefixes_prev\" : \"0\" , \"WithdrawnPrefixes_delta\" : \"-10918\" , \"WithdrawnPrefixes_prev\" : \"10918\" , \"context_name\" : \"\" }, ... ], \"count\" : 100 }","title":"list_cbgp"},{"location":"API/Routing/#list_ip_addresses","text":"List all IPv4 and IPv6 addresses. Route: /api/v0/resources/ip/addresses Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/addresses Output: { \"status\" : \"ok\" , \"ip_addresses\" : [ { \"ipv4_address_id\" : \"69\" , \"ipv4_address\" : \"127.0.0.1\" , \"ipv4_prefixlen\" : \"8\" , \"ipv4_network_id\" : \"55\" , \"port_id\" : \"135\" , \"context_name\" : \"\" }, ... ], \"count\" : 55 }","title":"list_ip_addresses"},{"location":"API/Routing/#get_network_ip_addresses","text":"Get all IPv4 and IPv6 addresses for particular network. Route: /api/v0/resources/ip/networks/:id/ip id must be integer Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/networks/55/ip Output: { \"status\" : \"ok\" , \"addresses\" : [ { \"ipv4_address_id\" : \"69\" , \"ipv4_address\" : \"127.0.0.1\" , \"ipv4_prefixlen\" : \"8\" , \"ipv4_network_id\" : \"55\" , \"port_id\" : \"135\" , \"context_name\" : \"\" } ], \"count\" : 1 }","title":"get_network_ip_addresses"},{"location":"API/Routing/#list_ip_networks","text":"List all IPv4 and IPv6 networks. Route: /api/v0/resources/ip/networks Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/ip/networks Output: { \"status\" : \"ok\" , \"ip_networks\" : [ { \"ipv4_network_id\" : \"1\" , \"ipv4_network\" : \"127.0.0.0/8\" , \"context_name\" : \"\" }, ... ], \"count\" : 100 }","title":"list_ip_networks"},{"location":"API/Routing/#list_ipsec","text":"List the current IPSec tunnels which are active. Route: /api/v0/routing/ipsec/data/:hostname hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/ipsec/data/localhost Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 0 , \"ipsec\" : [ \"tunnel_id\" : \"1\" , \"device_id\" : \"1\" , \"peer_port\" : \"0\" , \"peer_addr\" : \"127.0.0.1\" , \"local_addr\" : \"127.0.0.2\" , \"local_port\" : \"0\" , \"tunnel_name\" : \"\" , \"tunnel_status\" : \"active\" ] } Please note, this will only show active VPN sessions not all configured.","title":"list_ipsec"},{"location":"API/Routing/#list_ospf","text":"List the current OSPF neighbours. Route: /api/v0/ospf Input: hostname = Either the devices hostname or id. Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ospf curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ospf?hostname=host.example.com Output: { \"status\" : \"ok\" , \"ospf_neighbours\" : [ { \"device_id\" : \"1\" , \"port_id\" : \"0\" , \"ospf_nbr_id\" : \"172.16.1.145.0\" , \"ospfNbrIpAddr\" : \"172.16.1.145\" , \"ospfNbrAddressLessIndex\" : \"0\" , \"ospfNbrRtrId\" : \"172.16.0.140\" , \"ospfNbrOptions\" : \"82\" , \"ospfNbrPriority\" : \"1\" , \"ospfNbrState\" : \"full\" , \"ospfNbrEvents\" : \"5\" , \"ospfNbrLsRetransQLen\" : \"0\" , \"ospfNbmaNbrStatus\" : \"active\" , \"ospfNbmaNbrPermanence\" : \"dynamic\" , \"ospfNbrHelloSuppressed\" : \"false\" , \"context_name\" : \"\" } ], \"count\" : 1 }","title":"list_ospf"},{"location":"API/Routing/#list_ospf_ports","text":"List the current OSPF ports. Route: /api/v0/ospf_ports Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/ospf_ports Output: { \"status\" : \"ok\" , \"ospf_ports\" : [ { \"id\" : 189086 , \"device_id\" : 43 , \"port_id\" : 2838 , \"ospf_port_id\" : \"10.10.2.86.0\" , \"ospfIfIpAddress\" : \"10.10.2.86\" , \"ospfAddressLessIf\" : 0 , \"ospfIfAreaId\" : \"0.0.0.0\" , \"ospfIfType\" : \"pointToPoint\" , \"ospfIfAdminStat\" : \"enabled\" , \"ospfIfRtrPriority\" : 128 , \"ospfIfTransitDelay\" : 1 , \"ospfIfRetransInterval\" : 5 , \"ospfIfHelloInterval\" : 10 , \"ospfIfRtrDeadInterval\" : 40 , \"ospfIfPollInterval\" : 90 , \"ospfIfState\" : \"pointToPoint\" , \"ospfIfDesignatedRouter\" : \"0.0.0.0\" , \"ospfIfBackupDesignatedRouter\" : \"0.0.0.0\" , \"ospfIfEvents\" : 33 , \"ospfIfAuthKey\" : \"\" , \"ospfIfStatus\" : \"active\" , \"ospfIfMulticastForwarding\" : \"unicast\" , \"ospfIfDemand\" : \"false\" , \"ospfIfAuthType\" : \"0\" , \"ospfIfMetricIpAddress\" : \"10.10.2.86\" , \"ospfIfMetricAddressLessIf\" : 0 , \"ospfIfMetricTOS\" : 0 , \"ospfIfMetricValue\" : 10 , \"ospfIfMetricStatus\" : \"active\" , \"context_name\" : null } ], \"count\" : 1 }","title":"list_ospf_ports"},{"location":"API/Routing/#list_vrf","text":"List the current VRFs. Route: /api/v0/routing/vrf Input: hostname = Either the devices hostname or id OR vrfname = The VRF name you would like to filter by Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf?hostname=host.example.com curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf?vrfname=Mgmt-vrf Output: { \"status\" : \"ok\" , \"vrfs\" : [ { \"vrf_id\" : \"2\" , \"vrf_oid\" : \"8.77.103.109.116.45.118.114.102\" , \"vrf_name\" : \"Mgmt-vrf\" , \"mplsVpnVrfRouteDistinguisher\" : \"\" , \"mplsVpnVrfDescription\" : \"\" , \"device_id\" : \"8\" }, ... ], \"count\" : 100 }","title":"list_vrf"},{"location":"API/Routing/#get_vrf","text":"Retrieves VRF by ID Route: /api/v0/routing/vrf/:id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/vrf/2 Output: { \"status\" : \"ok\" , \"vrf\" : [ { \"vrf_id\" : \"2\" , \"vrf_oid\" : \"8.77.103.109.116.45.118.114.102\" , \"vrf_name\" : \"Mgmt-vrf\" , \"mplsVpnVrfRouteDistinguisher\" : \"\" , \"mplsVpnVrfDescription\" : \"\" , \"device_id\" : \"8\" } ], \"count\" : 1 }","title":"get_vrf"},{"location":"API/Routing/#list_mpls_services","text":"List MPLS services Route: /api/v0/routing/mpls/services Input: hostname = Either the devices hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/services curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/services?hostname=host.example.com Output: { \"status\" : \"ok\" , \"mpls_services\" : [ { \"svc_id\" : 1671 , \"svc_oid\" : 27 , \"device_id\" : 4 , \"svcRowStatus\" : \"active\" , \"svcType\" : \"tls\" , \"svcCustId\" : 1 , \"svcAdminStatus\" : \"up\" , \"svcOperStatus\" : \"up\" , \"svcDescription\" : \"\" , \"svcMtu\" : 9008 , \"svcNumSaps\" : 1 , \"svcNumSdps\" : 0 , \"svcLastMgmtChange\" : 2 , \"svcLastStatusChange\" : 168 , \"svcVRouterId\" : 0 , \"svcTlsMacLearning\" : \"enabled\" , \"svcTlsStpAdminStatus\" : \"disabled\" , \"svcTlsStpOperStatus\" : \"down\" , \"svcTlsFdbTableSize\" : 250 , \"svcTlsFdbNumEntries\" : 0 , \"hostname\" : \"host.example.com\" } ], \"count\" : 1 }","title":"list_mpls_services"},{"location":"API/Routing/#list_mpls_saps","text":"List MPLS SAPs Route: /api/v0/routing/mpls/saps Input: hostname = Either the devices hostname or id Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/saps curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/routing/mpls/saps?hostname=host.example.com Output: { \"status\" : \"ok\" , \"saps\" : [ { \"sap_id\" : 1935 , \"svc_id\" : 1660 , \"svc_oid\" : 7 , \"sapPortId\" : 16108921125 , \"ifName\" : \"1/1/c2/1\" , \"device_id\" : 3 , \"sapEncapValue\" : \"0\" , \"sapRowStatus\" : \"active\" , \"sapType\" : \"epipe\" , \"sapDescription\" : \"\" , \"sapAdminStatus\" : \"up\" , \"sapOperStatus\" : \"down\" , \"sapLastMgmtChange\" : 2 , \"sapLastStatusChange\" : 0 , \"hostname\" : \"hostname=host.example.com\" } ], \"count\" : 1 }","title":"list_mpls_saps"},{"location":"API/Services/","text":"list_services Retrieve all services Route: /api/v0/services Input: state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services?state=2 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services?state=0&type=tcp Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"services\" : [ [ { \"service_id\" : \"13\" , \"device_id\" : \"1\" , \"service_ip\" : \"demo1.yourdomian.net\" , \"service_type\" : \"ntp_peer\" , \"service_desc\" : \"NTP\" , \"service_param\" : \"-H 192.168.1.10\" , \"service_ignore\" : \"0\" , \"service_status\" : \"0\" , \"service_changed\" : \"1470962470\" , \"service_message\" : \"NTP OK: Offset -0.000717 secs\" , \"service_disabled\" : \"0\" , \"service_ds\" : \"{\\\"offset\\\":\\\"s\\\"}\" } ], [ { \"service_id\" : \"2\" , \"device_id\" : \"2\" , \"service_ip\" : \"demo2.yourdomian.net\" , \"service_type\" : \"esxi_hardware.py\" , \"service_desc\" : \"vmware hardware\" , \"service_param\" : \"-H 192.168.1.11 -U USER -P PASS -p\" , \"service_ignore\" : \"0\" , \"service_status\" : \"0\" , \"service_changed\" : \"1471702206\" , \"service_message\" : \"OK - Server: Supermicro X9SCL/X9SCM s/n: 0123456789 System BIOS: 2.2 2015-02-20\" , \"service_disabled\" : \"0\" , \"service_ds\" : \"{\\\"P2Vol_0_Processor_1_Vcore\\\":\\\"\\\",\\\"P2Vol_1_System_Board_1_-12V\\\":\\\"\\\",\\\"P2Vol_2_System_Board_1_12V\\\":\\\"\\\",\\\"P2Vol_3_System_Board_1_3.3VCC\\\":\\\"\\\",\\\"P2Vol_4_System_Board_1_5VCC\\\":\\\"\\\",\\\"P2Vol_5_System_Board_1_AVCC\\\":\\\"\\\",\\\"P2Vol_6_System_Board_1_VBAT\\\":\\\"\\\",\\\"P2Vol_7_System_Board_1_\" } ] ] } get_service_for_host Retrieve services for device Route: /api/v0/services/:hostname id or hostname is the specific device Input: state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/:hostname curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/:hostname?state=2 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/:hostname?state=0&type=tcp Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"services\" : [ [ { \"service_id\" : \"2\" , \"device_id\" : \"2\" , \"service_ip\" : \"demo2.yourdomian.net\" , \"service_type\" : \"esxi_hardware.py\" , \"service_desc\" : \"vmware hardware\" , \"service_param\" : \"-H 192.168.1.11 -U USER -P PASS -p\" , \"service_ignore\" : \"0\" , \"service_status\" : \"0\" , \"service_changed\" : \"1471702206\" , \"service_message\" : \"OK - Server: Supermicro X9SCL/X9SCM s/n: 0123456789 System BIOS: 2.2 2015-02-20\" , \"service_disabled\" : \"0\" , \"service_ds\" : \"{\\\"P2Vol_0_Processor_1_Vcore\\\":\\\"\\\",\\\"P2Vol_1_System_Board_1_-12V\\\":\\\"\\\",\\\"P2Vol_2_System_Board_1_12V\\\":\\\"\\\",\\\"P2Vol_3_System_Board_1_3.3VCC\\\":\\\"\\\",\\\"P2Vol_4_System_Board_1_5VCC\\\":\\\"\\\",\\\"P2Vol_5_System_Board_1_AVCC\\\":\\\"\\\",\\\"P2Vol_6_System_Board_1_VBAT\\\":\\\"\\\",\\\"P2Vol_7_System_Board_1_\" } ] ] } add_service_for_host Add a service for device Route: /api/v0/services/:hostname id or hostname is the specific device Input: type: service type ip: ip of the service desc: description for the service param: parameters for the service ignore: ignore the service for checks Example: curl -X POST -d '{\"type\":\"ping\",\"ip\": \"192.168.1.10\",\"desc\":\"test ping\",\"param\": \"-t 10 -c 5\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/192.168.1.10 Output: { \"status\" : \"ok\" , \"message\" : \"Service ping has been added to device 192.168.1.10 (#10)\" } edit_service_from_host Edits a service Route: /api/v0/services/:service_id service id Input: id: service id Example: curl -X PATCH -d '{\"service_disabled\":\"1\"}' 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/services/5 Output: { \"status\" : \"ok\" , \"message\" : \"Service updated successfully\" } delete_service_from_host Deletes service from device Route: /api/v0/services/:service_id service id Input: id: service id Example: curl -X DELETE -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/services/35 Output: { \"status\" : \"ok\" , \"message\" : \"Service has been deleted successfully\" }","title":"Services"},{"location":"API/Services/#list_services","text":"Retrieve all services Route: /api/v0/services Input: state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services?state=2 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services?state=0&type=tcp Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"services\" : [ [ { \"service_id\" : \"13\" , \"device_id\" : \"1\" , \"service_ip\" : \"demo1.yourdomian.net\" , \"service_type\" : \"ntp_peer\" , \"service_desc\" : \"NTP\" , \"service_param\" : \"-H 192.168.1.10\" , \"service_ignore\" : \"0\" , \"service_status\" : \"0\" , \"service_changed\" : \"1470962470\" , \"service_message\" : \"NTP OK: Offset -0.000717 secs\" , \"service_disabled\" : \"0\" , \"service_ds\" : \"{\\\"offset\\\":\\\"s\\\"}\" } ], [ { \"service_id\" : \"2\" , \"device_id\" : \"2\" , \"service_ip\" : \"demo2.yourdomian.net\" , \"service_type\" : \"esxi_hardware.py\" , \"service_desc\" : \"vmware hardware\" , \"service_param\" : \"-H 192.168.1.11 -U USER -P PASS -p\" , \"service_ignore\" : \"0\" , \"service_status\" : \"0\" , \"service_changed\" : \"1471702206\" , \"service_message\" : \"OK - Server: Supermicro X9SCL/X9SCM s/n: 0123456789 System BIOS: 2.2 2015-02-20\" , \"service_disabled\" : \"0\" , \"service_ds\" : \"{\\\"P2Vol_0_Processor_1_Vcore\\\":\\\"\\\",\\\"P2Vol_1_System_Board_1_-12V\\\":\\\"\\\",\\\"P2Vol_2_System_Board_1_12V\\\":\\\"\\\",\\\"P2Vol_3_System_Board_1_3.3VCC\\\":\\\"\\\",\\\"P2Vol_4_System_Board_1_5VCC\\\":\\\"\\\",\\\"P2Vol_5_System_Board_1_AVCC\\\":\\\"\\\",\\\"P2Vol_6_System_Board_1_VBAT\\\":\\\"\\\",\\\"P2Vol_7_System_Board_1_\" } ] ] }","title":"list_services"},{"location":"API/Services/#get_service_for_host","text":"Retrieve services for device Route: /api/v0/services/:hostname id or hostname is the specific device Input: state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/:hostname curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/:hostname?state=2 curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/:hostname?state=0&type=tcp Output: { \"status\" : \"ok\" , \"message\" : \"\" , \"count\" : 1 , \"services\" : [ [ { \"service_id\" : \"2\" , \"device_id\" : \"2\" , \"service_ip\" : \"demo2.yourdomian.net\" , \"service_type\" : \"esxi_hardware.py\" , \"service_desc\" : \"vmware hardware\" , \"service_param\" : \"-H 192.168.1.11 -U USER -P PASS -p\" , \"service_ignore\" : \"0\" , \"service_status\" : \"0\" , \"service_changed\" : \"1471702206\" , \"service_message\" : \"OK - Server: Supermicro X9SCL/X9SCM s/n: 0123456789 System BIOS: 2.2 2015-02-20\" , \"service_disabled\" : \"0\" , \"service_ds\" : \"{\\\"P2Vol_0_Processor_1_Vcore\\\":\\\"\\\",\\\"P2Vol_1_System_Board_1_-12V\\\":\\\"\\\",\\\"P2Vol_2_System_Board_1_12V\\\":\\\"\\\",\\\"P2Vol_3_System_Board_1_3.3VCC\\\":\\\"\\\",\\\"P2Vol_4_System_Board_1_5VCC\\\":\\\"\\\",\\\"P2Vol_5_System_Board_1_AVCC\\\":\\\"\\\",\\\"P2Vol_6_System_Board_1_VBAT\\\":\\\"\\\",\\\"P2Vol_7_System_Board_1_\" } ] ] }","title":"get_service_for_host"},{"location":"API/Services/#add_service_for_host","text":"Add a service for device Route: /api/v0/services/:hostname id or hostname is the specific device Input: type: service type ip: ip of the service desc: description for the service param: parameters for the service ignore: ignore the service for checks Example: curl -X POST -d '{\"type\":\"ping\",\"ip\": \"192.168.1.10\",\"desc\":\"test ping\",\"param\": \"-t 10 -c 5\"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/services/192.168.1.10 Output: { \"status\" : \"ok\" , \"message\" : \"Service ping has been added to device 192.168.1.10 (#10)\" }","title":"add_service_for_host"},{"location":"API/Services/#edit_service_from_host","text":"Edits a service Route: /api/v0/services/:service_id service id Input: id: service id Example: curl -X PATCH -d '{\"service_disabled\":\"1\"}' 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/services/5 Output: { \"status\" : \"ok\" , \"message\" : \"Service updated successfully\" }","title":"edit_service_from_host"},{"location":"API/Services/#delete_service_from_host","text":"Deletes service from device Route: /api/v0/services/:service_id service id Input: id: service id Example: curl -X DELETE -H 'X-Auth-Token:YOUR-API-TOKEN' https://librenms.org/api/v0/services/35 Output: { \"status\" : \"ok\" , \"message\" : \"Service has been deleted successfully\" }","title":"delete_service_from_host"},{"location":"API/Switching/","text":"list_vlans Get a list of all VLANs. Route: /api/v0/resources/vlans Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/vlans Output: { \"status\" : \"ok\" , \"vlans\" : [ { \"vlan_id\" : \"31\" , \"device_id\" : \"10\" , \"vlan_vlan\" : \"1\" , \"vlan_domain\" : \"1\" , \"vlan_name\" : \"default\" , \"vlan_type\" : \"ethernet\" , \"vlan_mtu\" : null }, ... ], \"count\" : 100 } get_vlans Get a list of all VLANs for a given device. Route: /api/v0/devices/:hostname/vlans hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/vlans Output: { \"status\" : \"ok\" , \"count\" : 0 , \"vlans\" : [ { \"vlan_vlan\" : \"1\" , \"vlan_domain\" : \"1\" , \"vlan_name\" : \"default\" , \"vlan_type\" : \"ethernet\" , \"vlan_mtu\" : null } ] } list_links Get a list of all Links. Route: /api/v0/resources/links Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/links Output: { \"status\" : \"ok\" , \"links\" : [ { \"id\" : 10 , \"local_port_id\" : 100 , \"local_device_id\" : 1 , \"remote_port_id\" : 200 , \"active\" : 1 , \"protocol\" : \"lldp\" , \"remote_hostname\" : \"host2.example.com\" , \"remote_device_id\" : 2 , \"remote_port\" : \"xe-0/0/1\" , \"remote_platform\" : null , \"remote_version\" : \"Example Router v.1.0\" }, ... ], \"count\" : 100 } get_links Get a list of Links per giver device. Route: /api/v0/devices/:hostname/links hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/links Output: { \"status\" : \"ok\" , \"links\" : [ { \"id\" : 10 , \"local_port_id\" : 100 , \"local_device_id\" : 1 , \"remote_port_id\" : 200 , \"active\" : 1 , \"protocol\" : \"lldp\" , \"remote_hostname\" : \"host2.example.com\" , \"remote_device_id\" : 2 , \"remote_port\" : \"xe-0/0/1\" , \"remote_platform\" : null , \"remote_version\" : \"Example Router v.1.0\" }, ... ], \"count\" : 10 } get_link Retrieves Link by ID Route: /api/v0/resources/links/:id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/links/10 Output: { \"status\" : \"ok\" , \"links\" : [ { \"id\" : 10 , \"local_port_id\" : 100 , \"local_device_id\" : 1 , \"remote_port_id\" : 200 , \"active\" : 1 , \"protocol\" : \"lldp\" , \"remote_hostname\" : \"host2.example.com\" , \"remote_device_id\" : 2 , \"remote_port\" : \"xe-0/0/1\" , \"remote_platform\" : null , \"remote_version\" : \"Example Router v.1.0\" } ], \"count\" : 1 } list_fdb Get a list of all ports FDB. Route: /api/v0/resources/fdb/:mac mac is the specific MAC address you would like to query Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/fdb curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/fdb/1aaa2bbb3ccc Output: { \"status\" : \"ok\" , \"ports_fdb\" : [ { \"ports_fdb_id\" : 10 , \"port_id\" : 10000 , \"mac_address\" : \"1aaa2bbb3ccc\" , \"vlan_id\" : 20000 , \"device_id\" : 1 , \"created_at\" : \"2019-01-1 01:01:01\" , \"updated_at\" : \"2019-01-1 01:01:01\" }, ... ], \"count\" : 100 } list_fdb_detail Get a list of all ports FDB with human readable device and interface names. Route: /api/v0/resources/fdb/:mac/detail mac is the specific MAC address you would like to query Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/fdb/1aaa2bbb3ccc/detail Output: { 'cou nt ' : 7 , 'mac' : ' 9 c : 93 : aa : bb : cc : dd' , 'mac_oui' : 'Xerox Corpora t io n ' , 'por ts _ f db' : [ { 'hos tna me' : 'hq - core 1 ' , 'i f Name' : 'ae 10 ' , 'las t _see n ' : ' 2 hours ago' , 'upda te d_a t ' : ' 2023-05-17 03 : 19 : 15 ' }, { 'hos tna me' : 'hq - sw 1 ' , 'i f Name' : 'ge -0 / 0 / 0 ' , 'las t _see n ' : ' 3 hours ago' , 'upda te d_a t ' : ' 2023-05-17 02 : 02 : 06 ' }, ... ], 's tatus ' : 'ok' }","title":"Switching"},{"location":"API/Switching/#list_vlans","text":"Get a list of all VLANs. Route: /api/v0/resources/vlans Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/vlans Output: { \"status\" : \"ok\" , \"vlans\" : [ { \"vlan_id\" : \"31\" , \"device_id\" : \"10\" , \"vlan_vlan\" : \"1\" , \"vlan_domain\" : \"1\" , \"vlan_name\" : \"default\" , \"vlan_type\" : \"ethernet\" , \"vlan_mtu\" : null }, ... ], \"count\" : 100 }","title":"list_vlans"},{"location":"API/Switching/#get_vlans","text":"Get a list of all VLANs for a given device. Route: /api/v0/devices/:hostname/vlans hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/vlans Output: { \"status\" : \"ok\" , \"count\" : 0 , \"vlans\" : [ { \"vlan_vlan\" : \"1\" , \"vlan_domain\" : \"1\" , \"vlan_name\" : \"default\" , \"vlan_type\" : \"ethernet\" , \"vlan_mtu\" : null } ] }","title":"get_vlans"},{"location":"API/Switching/#list_links","text":"Get a list of all Links. Route: /api/v0/resources/links Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/links Output: { \"status\" : \"ok\" , \"links\" : [ { \"id\" : 10 , \"local_port_id\" : 100 , \"local_device_id\" : 1 , \"remote_port_id\" : 200 , \"active\" : 1 , \"protocol\" : \"lldp\" , \"remote_hostname\" : \"host2.example.com\" , \"remote_device_id\" : 2 , \"remote_port\" : \"xe-0/0/1\" , \"remote_platform\" : null , \"remote_version\" : \"Example Router v.1.0\" }, ... ], \"count\" : 100 }","title":"list_links"},{"location":"API/Switching/#get_links","text":"Get a list of Links per giver device. Route: /api/v0/devices/:hostname/links hostname can be either the device hostname or id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/links Output: { \"status\" : \"ok\" , \"links\" : [ { \"id\" : 10 , \"local_port_id\" : 100 , \"local_device_id\" : 1 , \"remote_port_id\" : 200 , \"active\" : 1 , \"protocol\" : \"lldp\" , \"remote_hostname\" : \"host2.example.com\" , \"remote_device_id\" : 2 , \"remote_port\" : \"xe-0/0/1\" , \"remote_platform\" : null , \"remote_version\" : \"Example Router v.1.0\" }, ... ], \"count\" : 10 }","title":"get_links"},{"location":"API/Switching/#get_link","text":"Retrieves Link by ID Route: /api/v0/resources/links/:id Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/links/10 Output: { \"status\" : \"ok\" , \"links\" : [ { \"id\" : 10 , \"local_port_id\" : 100 , \"local_device_id\" : 1 , \"remote_port_id\" : 200 , \"active\" : 1 , \"protocol\" : \"lldp\" , \"remote_hostname\" : \"host2.example.com\" , \"remote_device_id\" : 2 , \"remote_port\" : \"xe-0/0/1\" , \"remote_platform\" : null , \"remote_version\" : \"Example Router v.1.0\" } ], \"count\" : 1 }","title":"get_link"},{"location":"API/Switching/#list_fdb","text":"Get a list of all ports FDB. Route: /api/v0/resources/fdb/:mac mac is the specific MAC address you would like to query Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/fdb curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/fdb/1aaa2bbb3ccc Output: { \"status\" : \"ok\" , \"ports_fdb\" : [ { \"ports_fdb_id\" : 10 , \"port_id\" : 10000 , \"mac_address\" : \"1aaa2bbb3ccc\" , \"vlan_id\" : 20000 , \"device_id\" : 1 , \"created_at\" : \"2019-01-1 01:01:01\" , \"updated_at\" : \"2019-01-1 01:01:01\" }, ... ], \"count\" : 100 }","title":"list_fdb"},{"location":"API/Switching/#list_fdb_detail","text":"Get a list of all ports FDB with human readable device and interface names. Route: /api/v0/resources/fdb/:mac/detail mac is the specific MAC address you would like to query Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/fdb/1aaa2bbb3ccc/detail Output: { 'cou nt ' : 7 , 'mac' : ' 9 c : 93 : aa : bb : cc : dd' , 'mac_oui' : 'Xerox Corpora t io n ' , 'por ts _ f db' : [ { 'hos tna me' : 'hq - core 1 ' , 'i f Name' : 'ae 10 ' , 'las t _see n ' : ' 2 hours ago' , 'upda te d_a t ' : ' 2023-05-17 03 : 19 : 15 ' }, { 'hos tna me' : 'hq - sw 1 ' , 'i f Name' : 'ge -0 / 0 / 0 ' , 'las t _see n ' : ' 3 hours ago' , 'upda te d_a t ' : ' 2023-05-17 02 : 02 : 06 ' }, ... ], 's tatus ' : 'ok' }","title":"list_fdb_detail"},{"location":"API/System/","text":"system Display Librenms instance information. Route: /api/v0/system Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/system Output: { \"status\" : \"ok\" , \"system\" : [ { \"local_ver\" : \"1.37-234-g19103ee\" , \"local_sha\" : \"19103ee36f68f009272c15be22e5a7e10a8b0b85\" , \"local_date\" : \"1526480966\" , \"local_branch\" : \"master\" , \"db_schema\" : 249 , \"php_ver\" : \"7.2.2\" , \"database_ver\" : \"MariaDB 5.5.56-MariaDB\" , \"rrdtool_ver\" : \"1.4.8\" , \"netsnmp_ver\" : \"NET-SNMP 5.7.2\" } ], \"count\" : 1 }","title":"System"},{"location":"API/System/#system","text":"Display Librenms instance information. Route: /api/v0/system Input: - Example: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/system Output: { \"status\" : \"ok\" , \"system\" : [ { \"local_ver\" : \"1.37-234-g19103ee\" , \"local_sha\" : \"19103ee36f68f009272c15be22e5a7e10a8b0b85\" , \"local_date\" : \"1526480966\" , \"local_branch\" : \"master\" , \"db_schema\" : 249 , \"php_ver\" : \"7.2.2\" , \"database_ver\" : \"MariaDB 5.5.56-MariaDB\" , \"rrdtool_ver\" : \"1.4.8\" , \"netsnmp_ver\" : \"NET-SNMP 5.7.2\" } ], \"count\" : 1 }","title":"system"},{"location":"Alerting/","text":"Introduction To get started, you first need some alert rules which will react to changes with your devices before raising an alert. Creating alert rules After that you also need to tell LibreNMS how to notify you when an alert is raised, this is done using Alert Transports . Configuring alert transports The next step is not strictly required but most people find it useful. Creating custom alert templates will help you get the benefit out of the alert system in general. Whilst we include a default template, it is limited in the data that you will receive in the alerts. Configuring alert templates Managing alerts When an alert has triggered you will see these in the Alerts -> Notifications page within the Web UI. This list has a couple of options available to it and we'll explain what these are here. ACK This column provides you visibility on the status of the alert: This alert is currently active and sending alerts. Click this icon to acknowledge the alert. This alert is currently acknowledged until the alert clears. Click this icon to un-acknowledge the alert. This alert is currently acknowledged until the alert worsens or gets better, at which stage it will be automatically unacknowledged and alerts will resume. Click this icon to un-acknowledge the alert. Notes This column will allow you access to the acknowledge/unacknowledge notes for this alert.","title":"Introduction"},{"location":"Alerting/#introduction","text":"To get started, you first need some alert rules which will react to changes with your devices before raising an alert. Creating alert rules After that you also need to tell LibreNMS how to notify you when an alert is raised, this is done using Alert Transports . Configuring alert transports The next step is not strictly required but most people find it useful. Creating custom alert templates will help you get the benefit out of the alert system in general. Whilst we include a default template, it is limited in the data that you will receive in the alerts. Configuring alert templates","title":"Introduction"},{"location":"Alerting/#managing-alerts","text":"When an alert has triggered you will see these in the Alerts -> Notifications page within the Web UI. This list has a couple of options available to it and we'll explain what these are here.","title":"Managing alerts"},{"location":"Alerting/#ack","text":"This column provides you visibility on the status of the alert: This alert is currently active and sending alerts. Click this icon to acknowledge the alert. This alert is currently acknowledged until the alert clears. Click this icon to un-acknowledge the alert. This alert is currently acknowledged until the alert worsens or gets better, at which stage it will be automatically unacknowledged and alerts will resume. Click this icon to un-acknowledge the alert.","title":"ACK"},{"location":"Alerting/#notes","text":"This column will allow you access to the acknowledge/unacknowledge notes for this alert.","title":"Notes"},{"location":"Alerting/Creating-Transport/","text":"Creating a new Transport File location All transports are located in LibreNMS\\Alert\\Transport and the files are named after the Transport name. I.e Discord.php for Discord. Transport structure The following functions are required for a new transport to pass the unit tests: deliverAlert() - This is function called within alerts to invoke the transport. Here you should do any post processing of the transport config to get it ready for use. contact$Transport() - This is named after the transport so for Discord it would be contactDiscord() . This is what actually interacts with the 3rd party API, invokes the mail command or whatever you want your alert to do. configTemplate() - This is used to define the form that will accept the transport config in the webui and then what data should be validated and how. Validation is done using Laravel validation The following function is not required for new Transports and is for legacy reasons only. deliverAlertOld() . Documentation Please don't forget to update the Transport file to include details of your new transport. A table should be provided to indicate the form values that we ask for and examples. I.e: Config Example Discord URL https://discordapp.com/api/webhooks/4515489001665127664/82-sf4385ysuhfn34u2fhfsdePGLrg8K7cP9wl553Fg6OlZuuxJGaa1d54fe Options username=myname","title":"Creating Transports"},{"location":"Alerting/Creating-Transport/#creating-a-new-transport","text":"","title":"Creating a new Transport"},{"location":"Alerting/Creating-Transport/#file-location","text":"All transports are located in LibreNMS\\Alert\\Transport and the files are named after the Transport name. I.e Discord.php for Discord.","title":"File location"},{"location":"Alerting/Creating-Transport/#transport-structure","text":"The following functions are required for a new transport to pass the unit tests: deliverAlert() - This is function called within alerts to invoke the transport. Here you should do any post processing of the transport config to get it ready for use. contact$Transport() - This is named after the transport so for Discord it would be contactDiscord() . This is what actually interacts with the 3rd party API, invokes the mail command or whatever you want your alert to do. configTemplate() - This is used to define the form that will accept the transport config in the webui and then what data should be validated and how. Validation is done using Laravel validation The following function is not required for new Transports and is for legacy reasons only. deliverAlertOld() .","title":"Transport structure"},{"location":"Alerting/Creating-Transport/#documentation","text":"Please don't forget to update the Transport file to include details of your new transport. A table should be provided to indicate the form values that we ask for and examples. I.e: Config Example Discord URL https://discordapp.com/api/webhooks/4515489001665127664/82-sf4385ysuhfn34u2fhfsdePGLrg8K7cP9wl553Fg6OlZuuxJGaa1d54fe Options username=myname","title":"Documentation"},{"location":"Alerting/Device-Dependencies/","text":"Device Dependencies It is possible to set one or more parents for a device. The aim for that is, if all parent devices are down, alert contacts will not receive redundant alerts for dependent devices. This is very useful when you have an outage, say in a branch office, where normally you'd receive hundreds of alerts, but when this is properly configured, you'd only receive an alert for the parent hosts. There are three ways to configure this feature. First one is from general settings of a device. The other two can be done in the 'Device Dependencies' item under 'Devices' menu. In this page, you can see all devices and with its parents. Clicking on the 'bin' icon will clear the dependency setting. Clicking on the 'pen' icon will let you edit or change the current setting for chosen device. There's also a 'Manage Device Dependencies' button on the top. This will let you set parents for multiple devices at once. For an intro on getting started with Device Dependencies, take a look at our Youtube video","title":"Device Dependencies"},{"location":"Alerting/Device-Dependencies/#device-dependencies","text":"It is possible to set one or more parents for a device. The aim for that is, if all parent devices are down, alert contacts will not receive redundant alerts for dependent devices. This is very useful when you have an outage, say in a branch office, where normally you'd receive hundreds of alerts, but when this is properly configured, you'd only receive an alert for the parent hosts. There are three ways to configure this feature. First one is from general settings of a device. The other two can be done in the 'Device Dependencies' item under 'Devices' menu. In this page, you can see all devices and with its parents. Clicking on the 'bin' icon will clear the dependency setting. Clicking on the 'pen' icon will let you edit or change the current setting for chosen device. There's also a 'Manage Device Dependencies' button on the top. This will let you set parents for multiple devices at once. For an intro on getting started with Device Dependencies, take a look at our Youtube video","title":"Device Dependencies"},{"location":"Alerting/Entities/","text":"Entities Entities as described earlier are based on the table and column names within the database, if you are unsure of what the entity is you want then have a browse around inside MySQL using show tables and desc . Below are some common entities that you can use within the alerting system. This list is not exhaustive and you should look at the MySQL database schema for the full list. Devices Entity Description devices.hostname The device hostname devices.sysName The device sysName devices.sysDescr The device sysDescr devices.hardware The device hardware devices.version The device os version devices.location The device location devices.status The status of the device, 1 devices.status_reason The reason the device was detected as down (icmp or snmp) devices.ignore If the device is ignored this will be set to 1 devices.disabled If the device is disabled this will be set to 1 devices.last_polled The the last polled datetime (yyyy-mm-dd hh:mm:ss) devices.type The device type such as network, server, firewall, etc. BGP Peers Entity Description bgpPeers.astext This is the description of the BGP Peer bgpPeers.bgpPeerIdentifier The IP address of the BGP Peer bgpPeers.bgpPeerRemoteAs The AS number of the BGP Peer bgpPeers.bgpPeerState The operational state of the BGP session bgpPeers.bgpPeerAdminStatus The administrative state of the BGP session bgpPeers.bgpLocalAddr The local address of the BGP session. IPSec Tunnels Entity Description ipsec_tunnels.peer_addr The remote VPN peer address ipsec_tunnels.local_addr The local VPN address ipsec_tunnels.tunnel_status The VPN tunnels operational status. Memory pools Entity | Description |---|---| mempools.mempool_type | The memory pool type such as hrstorage, cmp and cemp mempools.mempool_descr | The description of the pool such as Physical memory, Virtual memory and System memory mempools.mempool_perc | The used percentage of the memory pool. Ports Entity Description ports.ifDescr The interface description ports.ifName The interface name ports.ifSpeed The port speed in bps ports.ifHighSpeed The port speed in mbps ports.ifOperStatus The operational status of the port (up or down) ports.ifAdminStatus The administrative status of the port (up or down) ports.ifDuplex Duplex setting of the port ports.ifMtu The MTU setting of the port. Processors Entity Description processors.processor_usage The usage of the processor as a percentage processors.processor_descr The description of the processor. Storage Entity Description storage.storage_descr The description of the storage storage.storage_perc The usage of the storage as a percentage. Health / Sensors Entity Description sensors.sensor_desc The sensors description. sensors.sensor_current The current sensors value. sensors.sensor_prev The previous sensor value. sensors.lastupdate The sensors last updated datetime stamp.","title":"Entities"},{"location":"Alerting/Entities/#entities","text":"Entities as described earlier are based on the table and column names within the database, if you are unsure of what the entity is you want then have a browse around inside MySQL using show tables and desc . Below are some common entities that you can use within the alerting system. This list is not exhaustive and you should look at the MySQL database schema for the full list.","title":"Entities"},{"location":"Alerting/Entities/#devices","text":"Entity Description devices.hostname The device hostname devices.sysName The device sysName devices.sysDescr The device sysDescr devices.hardware The device hardware devices.version The device os version devices.location The device location devices.status The status of the device, 1 devices.status_reason The reason the device was detected as down (icmp or snmp) devices.ignore If the device is ignored this will be set to 1 devices.disabled If the device is disabled this will be set to 1 devices.last_polled The the last polled datetime (yyyy-mm-dd hh:mm:ss) devices.type The device type such as network, server, firewall, etc.","title":"Devices"},{"location":"Alerting/Entities/#bgp-peers","text":"Entity Description bgpPeers.astext This is the description of the BGP Peer bgpPeers.bgpPeerIdentifier The IP address of the BGP Peer bgpPeers.bgpPeerRemoteAs The AS number of the BGP Peer bgpPeers.bgpPeerState The operational state of the BGP session bgpPeers.bgpPeerAdminStatus The administrative state of the BGP session bgpPeers.bgpLocalAddr The local address of the BGP session.","title":"BGP Peers"},{"location":"Alerting/Entities/#ipsec-tunnels","text":"Entity Description ipsec_tunnels.peer_addr The remote VPN peer address ipsec_tunnels.local_addr The local VPN address ipsec_tunnels.tunnel_status The VPN tunnels operational status.","title":"IPSec Tunnels"},{"location":"Alerting/Entities/#memory-pools","text":"Entity | Description |---|---| mempools.mempool_type | The memory pool type such as hrstorage, cmp and cemp mempools.mempool_descr | The description of the pool such as Physical memory, Virtual memory and System memory mempools.mempool_perc | The used percentage of the memory pool.","title":"Memory pools"},{"location":"Alerting/Entities/#ports","text":"Entity Description ports.ifDescr The interface description ports.ifName The interface name ports.ifSpeed The port speed in bps ports.ifHighSpeed The port speed in mbps ports.ifOperStatus The operational status of the port (up or down) ports.ifAdminStatus The administrative status of the port (up or down) ports.ifDuplex Duplex setting of the port ports.ifMtu The MTU setting of the port.","title":"Ports"},{"location":"Alerting/Entities/#processors","text":"Entity Description processors.processor_usage The usage of the processor as a percentage processors.processor_descr The description of the processor.","title":"Processors"},{"location":"Alerting/Entities/#storage","text":"Entity Description storage.storage_descr The description of the storage storage.storage_perc The usage of the storage as a percentage.","title":"Storage"},{"location":"Alerting/Entities/#health-sensors","text":"Entity Description sensors.sensor_desc The sensors description. sensors.sensor_current The current sensors value. sensors.sensor_prev The previous sensor value. sensors.lastupdate The sensors last updated datetime stamp.","title":"Health / Sensors"},{"location":"Alerting/Macros/","text":"Macros Macros are shorthands to either portion of rules or pure SQL enhanced with placeholders. You can define your own macros in your config.php . Example macro-implementation of Debian-Devices $config [ 'alert' ][ 'macros' ][ 'rule' ][ 'is_debian' ] = 'devices.features ~ \"@debian@\"' ; And in the Rule: ... macros.is_debian = 1 ... This Example-macro is a Boolean-macro, it applies a form of filter to the set of results defined by the rule. All macros that are not unary should return Boolean. Device (Boolean) Entity: macros.device Description: Only select devices that aren't deleted, ignored or disabled. Source: (devices.disabled = 0 AND devices.ignore = 0) Device is up (Boolean) Entity: macros.device_up Description: Only select devices that are up. Implies: macros.device Source: (devices.status = 1 AND macros.device) Device is down (Boolean) Entity: macros.device_down Description: Only select devices that are down. Implies: macros.device Source: (devices.status = 0 AND macros.device) Port (Boolean) Entity: macros.port Description: Only select ports that aren't deleted, ignored or disabled. Source: (ports.deleted = 0 AND ports.ignore = 0 AND ports.disabled = 0) Port is up (Boolean) Entity: macros.port_up Description: Only select ports that are up and also should be up. Implies: macros.port Source: (ports.ifOperStatus = up AND ports.ifAdminStatus = up AND macros.port) Port is down (Boolean) Entity: macros.port_down Description: Only select ports that are down. Implies: macros.port Source: (ports.ifOperStatus != \"up\" AND ports.ifAdminStatus != \"down\" AND macros.port) Port-Usage in Percent (Decimal) Entity: macros.port_usage_perc Description: Return port-usage (max value of in and out) in percent. Source: ((SELECT IF(ports.ifOutOctets_rate>ports.ifInOctets_rate, ports.ifOutOctets_rate, ports.ifInOctets_rate)*8) / ports.ifSpeed)*100 Time Now (Datetime) Entity: macros.now Description: Alias of MySQL's NOW() Source: NOW() Past N Minutes (Datetime) Entity: macros.past_$m Description: Returns a MySQL Timestamp dated $ Minutes in the past. $ can only be a supported Resolution. Example: macros.past_5m is Last 5 Minutes. Resolution: 5,10,15,30,60 Source: DATE_SUB(NOW(),INTERVAL $ MINUTE) Sensors (Boolean) Entity: macros.sensor Description: Only select sensors that aren't ignored. Source: (sensors.sensor_alert = 1) Entity: macros.sensor_port_link = 1 Description: Only selects sensors that have a port linked to them, the port is up and the device is up. Source: (sensors.entity_link_type = \"port\" AND sensors.entity_link_index = ports.ifIndex AND macros.port_up AND macros.device_up)) State Sensors (Boolean) Entity: macros.state_sensor_ok , macros.state_sensor_warning , macros.state_sensor_critical , macros.state_sensor_unknown Description: Select state sensors by their generic status ok (0), warning (1), critical (2), unknown (3) Source: (sensors.sensor_current = state_translations.state_value AND state_translations.state_generic_value = 2) Misc (Boolean) Packet Loss Entity: (macros.packet_loss_5m) Description: Packet loss % value for the device within the last 5 minutes. Example: macros.packet_loss_5m > 50 Entity: (macros.packet_loss_15m) Description: Packet loss % value for the device within the last 15 minutes. Example: macros.packet_loss_15m > 50 Ports in usage perc (Int) Entity: ((ports.ifInOctets_rate*8)/ports.ifSpeed)*100 Description: Port in used more than 50% Example: `macros.port_in_usage_perc > 50 Ports out usage perc (Int) Entity: ((ports.ifOutOctets_rate*8)/ports.ifSpeed)*100 Description: Port out used more than 50% Example: `macros.port_out_usage_perc > 50 Ports now down (Boolean) Entity: ports.ifOperStatus != ports.ifOperStatus_prev AND ports.ifOperStatus_prev = \"up\" AND ports.ifAdminStatus = \"up\" Description: Ports that were previously up and have now gone down. Example: macros.port_now_down = 1 Port has xDP neighbour (Boolean) Entity: %macros.port AND %links.local_port_id = %ports.port_id Description: Ports that have an xDP (lldp, cdp, etc) neighbour. Example: macros.port_has_xdp_neighbours = 1 Port has xDP neighbour already known in LibreNMS (Boolean) Entity: %macros.port_has_neighbours AND (%links.remote_port_id IS NOT NULL) Description: Ports that have an xDP (lldp, cdp, etc) neighbour that is already known in libreNMS. Example: macros.port_has_xdp_neighbours_device = 1 Device component down [JunOS] Entity: sensors.sensor_class = \"state\" AND sensors.sensor_current != \"6\" AND sensors.sensor_type = \"jnxFruState\" AND sensors.sensor_current != \"2\" Description: Device component is down such as Fan, PSU, etc for JunOS devices. Example: macros.device_component_down_junos = 1 Device component down [Cisco] Entity: sensors.sensor_current != 1 AND sensors.sensor_current != 5 AND sensors.sensor_type ~ \"^cisco.*State$\" Description: Device component is down such as Fan, PSU, etc for Cisco devices. Example: macros.device_component_down_cisco = 1 PDU over amperage [APC] Entity: sensors.sensor_class = \"current\" AND sensors.sensor_descr = \"Bank Total\" AND sensors.sensor_current > sensors.sensor_limit AND devices.os = \"apc\" Description: APC PDU over amperage Example: macros.pdu_over_amperage_apc = 1","title":"Macros"},{"location":"Alerting/Macros/#macros","text":"Macros are shorthands to either portion of rules or pure SQL enhanced with placeholders. You can define your own macros in your config.php . Example macro-implementation of Debian-Devices $config [ 'alert' ][ 'macros' ][ 'rule' ][ 'is_debian' ] = 'devices.features ~ \"@debian@\"' ; And in the Rule: ... macros.is_debian = 1 ... This Example-macro is a Boolean-macro, it applies a form of filter to the set of results defined by the rule. All macros that are not unary should return Boolean.","title":"Macros"},{"location":"Alerting/Macros/#device-boolean","text":"Entity: macros.device Description: Only select devices that aren't deleted, ignored or disabled. Source: (devices.disabled = 0 AND devices.ignore = 0)","title":"Device (Boolean)"},{"location":"Alerting/Macros/#device-is-up-boolean","text":"Entity: macros.device_up Description: Only select devices that are up. Implies: macros.device Source: (devices.status = 1 AND macros.device)","title":"Device is up (Boolean)"},{"location":"Alerting/Macros/#device-is-down-boolean","text":"Entity: macros.device_down Description: Only select devices that are down. Implies: macros.device Source: (devices.status = 0 AND macros.device)","title":"Device is down (Boolean)"},{"location":"Alerting/Macros/#port-boolean","text":"Entity: macros.port Description: Only select ports that aren't deleted, ignored or disabled. Source: (ports.deleted = 0 AND ports.ignore = 0 AND ports.disabled = 0)","title":"Port (Boolean)"},{"location":"Alerting/Macros/#port-is-up-boolean","text":"Entity: macros.port_up Description: Only select ports that are up and also should be up. Implies: macros.port Source: (ports.ifOperStatus = up AND ports.ifAdminStatus = up AND macros.port)","title":"Port is up (Boolean)"},{"location":"Alerting/Macros/#port-is-down-boolean","text":"Entity: macros.port_down Description: Only select ports that are down. Implies: macros.port Source: (ports.ifOperStatus != \"up\" AND ports.ifAdminStatus != \"down\" AND macros.port)","title":"Port is down (Boolean)"},{"location":"Alerting/Macros/#port-usage-in-percent-decimal","text":"Entity: macros.port_usage_perc Description: Return port-usage (max value of in and out) in percent. Source: ((SELECT IF(ports.ifOutOctets_rate>ports.ifInOctets_rate, ports.ifOutOctets_rate, ports.ifInOctets_rate)*8) / ports.ifSpeed)*100","title":"Port-Usage in Percent (Decimal)"},{"location":"Alerting/Macros/#time","text":"","title":"Time"},{"location":"Alerting/Macros/#now-datetime","text":"Entity: macros.now Description: Alias of MySQL's NOW() Source: NOW()","title":"Now (Datetime)"},{"location":"Alerting/Macros/#past-n-minutes-datetime","text":"Entity: macros.past_$m Description: Returns a MySQL Timestamp dated $ Minutes in the past. $ can only be a supported Resolution. Example: macros.past_5m is Last 5 Minutes. Resolution: 5,10,15,30,60 Source: DATE_SUB(NOW(),INTERVAL $ MINUTE)","title":"Past N Minutes (Datetime)"},{"location":"Alerting/Macros/#sensors-boolean","text":"Entity: macros.sensor Description: Only select sensors that aren't ignored. Source: (sensors.sensor_alert = 1) Entity: macros.sensor_port_link = 1 Description: Only selects sensors that have a port linked to them, the port is up and the device is up. Source: (sensors.entity_link_type = \"port\" AND sensors.entity_link_index = ports.ifIndex AND macros.port_up AND macros.device_up))","title":"Sensors (Boolean)"},{"location":"Alerting/Macros/#state-sensors-boolean","text":"Entity: macros.state_sensor_ok , macros.state_sensor_warning , macros.state_sensor_critical , macros.state_sensor_unknown Description: Select state sensors by their generic status ok (0), warning (1), critical (2), unknown (3) Source: (sensors.sensor_current = state_translations.state_value AND state_translations.state_generic_value = 2)","title":"State Sensors (Boolean)"},{"location":"Alerting/Macros/#misc-boolean","text":"","title":"Misc (Boolean)"},{"location":"Alerting/Macros/#packet-loss","text":"Entity: (macros.packet_loss_5m) Description: Packet loss % value for the device within the last 5 minutes. Example: macros.packet_loss_5m > 50 Entity: (macros.packet_loss_15m) Description: Packet loss % value for the device within the last 15 minutes. Example: macros.packet_loss_15m > 50","title":"Packet Loss"},{"location":"Alerting/Macros/#ports-in-usage-perc-int","text":"Entity: ((ports.ifInOctets_rate*8)/ports.ifSpeed)*100 Description: Port in used more than 50% Example: `macros.port_in_usage_perc > 50","title":"Ports in usage perc (Int)"},{"location":"Alerting/Macros/#ports-out-usage-perc-int","text":"Entity: ((ports.ifOutOctets_rate*8)/ports.ifSpeed)*100 Description: Port out used more than 50% Example: `macros.port_out_usage_perc > 50","title":"Ports out usage perc (Int)"},{"location":"Alerting/Macros/#ports-now-down-boolean","text":"Entity: ports.ifOperStatus != ports.ifOperStatus_prev AND ports.ifOperStatus_prev = \"up\" AND ports.ifAdminStatus = \"up\" Description: Ports that were previously up and have now gone down. Example: macros.port_now_down = 1","title":"Ports now down (Boolean)"},{"location":"Alerting/Macros/#port-has-xdp-neighbour-boolean","text":"Entity: %macros.port AND %links.local_port_id = %ports.port_id Description: Ports that have an xDP (lldp, cdp, etc) neighbour. Example: macros.port_has_xdp_neighbours = 1","title":"Port has xDP neighbour (Boolean)"},{"location":"Alerting/Macros/#port-has-xdp-neighbour-already-known-in-librenms-boolean","text":"Entity: %macros.port_has_neighbours AND (%links.remote_port_id IS NOT NULL) Description: Ports that have an xDP (lldp, cdp, etc) neighbour that is already known in libreNMS. Example: macros.port_has_xdp_neighbours_device = 1","title":"Port has xDP neighbour already known in LibreNMS (Boolean)"},{"location":"Alerting/Macros/#device-component-down-junos","text":"Entity: sensors.sensor_class = \"state\" AND sensors.sensor_current != \"6\" AND sensors.sensor_type = \"jnxFruState\" AND sensors.sensor_current != \"2\" Description: Device component is down such as Fan, PSU, etc for JunOS devices. Example: macros.device_component_down_junos = 1","title":"Device component down [JunOS]"},{"location":"Alerting/Macros/#device-component-down-cisco","text":"Entity: sensors.sensor_current != 1 AND sensors.sensor_current != 5 AND sensors.sensor_type ~ \"^cisco.*State$\" Description: Device component is down such as Fan, PSU, etc for Cisco devices. Example: macros.device_component_down_cisco = 1","title":"Device component down [Cisco]"},{"location":"Alerting/Macros/#pdu-over-amperage-apc","text":"Entity: sensors.sensor_class = \"current\" AND sensors.sensor_descr = \"Bank Total\" AND sensors.sensor_current > sensors.sensor_limit AND devices.os = \"apc\" Description: APC PDU over amperage Example: macros.pdu_over_amperage_apc = 1","title":"PDU over amperage [APC]"},{"location":"Alerting/Rules/","text":"Rules Rules are defined using a logical language. The GUI provides a simple way of creating rules. Creating more complicated rules which may include maths calculations and MySQL queries can be done using macros Syntax Rules must consist of at least 3 elements: An Entity , a Condition and a Value . Rules can contain braces and Glues . Entities are provided from Table and Field from the database. For Example: ports.ifOperStatus . Conditions can be any of: Equals = Not Equals != In IN Not In NOT IN Begins with LIKE ('...%') Doesn't begin with NOT LIKE ('...%') Contains LIKE ('%...%') Doesn't Contain NOT LIKE ('%...%') Ends with LIKE ('%...') Doesn't end with NOT LIKE ('%...') Between BETWEEN Not Between NOT BETWEEN Is Empty = '' Is Not Empty != ''' Is Null IS NULL Is Not Null IS NOT NULL Greater > Greater or Equal >= Less < Less or Equal <= Regex REGEXP Values can be an entity or any data. If using macros as value you must include the macro name into backticks. i.e. `macros.past_60m` Note : Regex supports MySQL Regular expressions. Arithmetics are allowed as well. Options Here are some of the other options available when adding an alerting rule: Rule name: The name associated with the rule. Severity: How \"important\" the rule is. Max alerts: The maximum number of alerts sent for the event. -1 means unlimited. Delay: The amount of time in seconds to wait after a rule is matched before sending an alert out transport. Interval: The interval of time in seconds between alerts for an event until Max alert is reached. Mute alerts: Disables sending alert rule through alert transport. But will still show the alert in the Web UI. Invert match: Invert the matching rule (ie. alert on items that _don't match the rule). Recovery alerts: This will disable the recovery notification from being sent if turned off. Advanced On the Advanced tab, you can specify some additional options for the alert rule: Override SQL: Enable this if you using a custom query Query: The query to be used for the alert. An example of this would be an average rule for all CPUs over 10% SELECT devices . device_id , devices . status , devices . disabled , devices . ignore , AVG ( processors . processor_usage ) AS cpu_avg FROM devices INNER JOIN processors ON devices . device_id = processors . device_id WHERE devices . device_id = ? AND devices . status = 1 AND devices . disabled = 0 AND devices . ignore = 0 GROUP BY devices . device_id , devices . status , devices . disabled , devices . ignore HAVING AVG ( processors . processor_usage ) > 10 The 10 would then contain the average CPU usage value, you can change this value to be whatever you like. You will to need copy and paste this into the Alert Rule under Advanced then paste into Query box and switch the Override SQL. Procedure You can associate a rule to a procedure by giving the URL of the procedure when creating the rule. Only links like \"http://\" are supported, otherwise an error will be returned. Once configured, procedure can be opened from the Alert widget through the \"Open\" button, which can be shown/hidden from the widget configuration box. Examples Alert when: Device goes down: devices.status != 1 Any port changes: ports.ifOperStatus != 'up' Root-directory gets too full: storage.storage_descr = '/' AND storage.storage_perc >= '75' Any storage gets fuller than the 'warning': storage.storage_perc >= storage_perc_warn If device is a server and the used storage is above the warning level, but ignore /boot partitions: storage.storage_perc > storage.storage_perc_warn AND devices.type = \"server\" AND storage.storage_descr != \"/boot\" VMware LAG is not using \"Source ip address hash\" load balancing: devices.os = \"vmware\" AND ports.ifType = \"ieee8023adLag\" AND ports.ifDescr REGEXP \"Link Aggregation .*, load balancing algorithm: Source ip address hash\" Syslog, authentication failure during the last 5m: syslog.timestamp >= macros.past_5m AND syslog.msg REGEXP \".*authentication failure.*\" High memory usage: macros.device_up = 1 AND mempools.mempool_perc >= 90 AND mempools.mempool_descr REGEXP \"Virtual.*\" High CPU usage(per core usage, not overall): macros.device_up = 1 AND processors.processor_usage >= 90 High port usage, where description is not client & ifType is not softwareLoopback: macros.port_usage_perc >= 80 AND port.port_descr_type != \"client\" AND ports.ifType != \"softwareLoopback\" Alert when mac address is located on your network ipv4_mac.mac_address = \"2c233a756912\" Alert Rules Collection You can also select Alert Rule from the Alerts Collection. These Alert Rules are submitted by users in the community :) If would like to submit your alert rules to the collection, please submit them here Alert Rules Collection","title":"Rules"},{"location":"Alerting/Rules/#rules","text":"Rules are defined using a logical language. The GUI provides a simple way of creating rules. Creating more complicated rules which may include maths calculations and MySQL queries can be done using macros","title":"Rules"},{"location":"Alerting/Rules/#syntax","text":"Rules must consist of at least 3 elements: An Entity , a Condition and a Value . Rules can contain braces and Glues . Entities are provided from Table and Field from the database. For Example: ports.ifOperStatus . Conditions can be any of: Equals = Not Equals != In IN Not In NOT IN Begins with LIKE ('...%') Doesn't begin with NOT LIKE ('...%') Contains LIKE ('%...%') Doesn't Contain NOT LIKE ('%...%') Ends with LIKE ('%...') Doesn't end with NOT LIKE ('%...') Between BETWEEN Not Between NOT BETWEEN Is Empty = '' Is Not Empty != ''' Is Null IS NULL Is Not Null IS NOT NULL Greater > Greater or Equal >= Less < Less or Equal <= Regex REGEXP Values can be an entity or any data. If using macros as value you must include the macro name into backticks. i.e. `macros.past_60m` Note : Regex supports MySQL Regular expressions. Arithmetics are allowed as well.","title":"Syntax"},{"location":"Alerting/Rules/#options","text":"Here are some of the other options available when adding an alerting rule: Rule name: The name associated with the rule. Severity: How \"important\" the rule is. Max alerts: The maximum number of alerts sent for the event. -1 means unlimited. Delay: The amount of time in seconds to wait after a rule is matched before sending an alert out transport. Interval: The interval of time in seconds between alerts for an event until Max alert is reached. Mute alerts: Disables sending alert rule through alert transport. But will still show the alert in the Web UI. Invert match: Invert the matching rule (ie. alert on items that _don't match the rule). Recovery alerts: This will disable the recovery notification from being sent if turned off.","title":"Options"},{"location":"Alerting/Rules/#advanced","text":"On the Advanced tab, you can specify some additional options for the alert rule: Override SQL: Enable this if you using a custom query Query: The query to be used for the alert. An example of this would be an average rule for all CPUs over 10% SELECT devices . device_id , devices . status , devices . disabled , devices . ignore , AVG ( processors . processor_usage ) AS cpu_avg FROM devices INNER JOIN processors ON devices . device_id = processors . device_id WHERE devices . device_id = ? AND devices . status = 1 AND devices . disabled = 0 AND devices . ignore = 0 GROUP BY devices . device_id , devices . status , devices . disabled , devices . ignore HAVING AVG ( processors . processor_usage ) > 10 The 10 would then contain the average CPU usage value, you can change this value to be whatever you like. You will to need copy and paste this into the Alert Rule under Advanced then paste into Query box and switch the Override SQL.","title":"Advanced"},{"location":"Alerting/Rules/#procedure","text":"You can associate a rule to a procedure by giving the URL of the procedure when creating the rule. Only links like \"http://\" are supported, otherwise an error will be returned. Once configured, procedure can be opened from the Alert widget through the \"Open\" button, which can be shown/hidden from the widget configuration box.","title":"Procedure"},{"location":"Alerting/Rules/#examples","text":"Alert when: Device goes down: devices.status != 1 Any port changes: ports.ifOperStatus != 'up' Root-directory gets too full: storage.storage_descr = '/' AND storage.storage_perc >= '75' Any storage gets fuller than the 'warning': storage.storage_perc >= storage_perc_warn If device is a server and the used storage is above the warning level, but ignore /boot partitions: storage.storage_perc > storage.storage_perc_warn AND devices.type = \"server\" AND storage.storage_descr != \"/boot\" VMware LAG is not using \"Source ip address hash\" load balancing: devices.os = \"vmware\" AND ports.ifType = \"ieee8023adLag\" AND ports.ifDescr REGEXP \"Link Aggregation .*, load balancing algorithm: Source ip address hash\" Syslog, authentication failure during the last 5m: syslog.timestamp >= macros.past_5m AND syslog.msg REGEXP \".*authentication failure.*\" High memory usage: macros.device_up = 1 AND mempools.mempool_perc >= 90 AND mempools.mempool_descr REGEXP \"Virtual.*\" High CPU usage(per core usage, not overall): macros.device_up = 1 AND processors.processor_usage >= 90 High port usage, where description is not client & ifType is not softwareLoopback: macros.port_usage_perc >= 80 AND port.port_descr_type != \"client\" AND ports.ifType != \"softwareLoopback\" Alert when mac address is located on your network ipv4_mac.mac_address = \"2c233a756912\"","title":"Examples"},{"location":"Alerting/Rules/#alert-rules-collection","text":"You can also select Alert Rule from the Alerts Collection. These Alert Rules are submitted by users in the community :) If would like to submit your alert rules to the collection, please submit them here Alert Rules Collection","title":"Alert Rules Collection"},{"location":"Alerting/Templates/","text":"Templates This page is for installs running version 1.42 or later. You can find the older docs here Templates can be assigned to a single or a group of rules and can contain any kind of text. There is also a default template which is used for any rule that isn't associated with a template. This template can be found under Alert Templates page and can be edited. It also has an option revert it back to its default content. To attach a template to a rule just open the Alert Templates settings page, choose the template to assign and click the yellow button in the Actions column. In the appearing popupbox select the rule(s) you want the template to be assigned to and click the Attach button. You might hold down the CTRL key to select multiple rules at once. The templating engine in use is Laravel Blade. We will cover some of the basics here, however the official Laravel docs will have more information here Syntax Controls: if-else (Else can be omitted): @if ($alert->placeholder == 'value') Some Text @else Other Text @endif foreach-loop: @foreach ($alert->faults as $key => $value) Key: $key Value: $value @endforeach Placeholders: Placeholders are special variables that if used within the template will be replaced with the relevant data, I.e: The device {{ $alert->hostname }} has been up for {{ $alert->uptime }} seconds would result in the following The device localhost has been up for 30344 seconds . When using placeholders to echo data, you need to wrap the placeholder in {{ }} . I.e {{ $alert->hostname }} . Device ID: $alert->device_id Hostname of the Device: $alert->hostname sysName of the Device: $alert->sysName sysDescr of the Device: $alert->sysDescr display name of the Device: $alert->display sysContact of the Device: $alert->sysContact OS of the Device: $alert->os Type of Device: $alert->type IP of the Device: $alert->ip Hardware of the Device: $alert->hardware Software version of the Device: $alert->version Features of the Device: $alert->features Serial number of the Device: $alert->serial Location of the Device: $alert->location uptime of the Device (in seconds): $alert->uptime Short uptime of the Device (28d 22h 30m 7s): $alert->uptime_short Long uptime of the Device (28 days, 22h 30m 7s): $alert->uptime_long Description (purpose db field) of the Device: $alert->description Notes of the Device: $alert->notes Notes of the alert (ack notes): $alert->alert_notes ping timestamp (if icmp enabled): $alert->ping_timestamp ping loss (if icmp enabled): $alert->ping_loss ping min (if icmp enabled): $alert->ping_min ping max (if icmp enabled): $alert->ping_max ping avg (if icmp enabled): $alert->ping_avg debug (array) poller_name - name of poller (for distributed setups) If $config['debug']['run_trace] = true; is set then this will contain: traceroute (if enabled you will receive traceroute output): $alert->debug['traceroute'] traceroute_output (if the traceroute fails this will contain why): $alert->debug['traceroute_output'] Title for the Alert: $alert->title Time Elapsed, Only available on recovery ( $alert->state == 0 ): $alert->elapsed Rule Builder (the actual rule) (use {!! $alert->builder !!} ): $alert->builder Alert-ID: $alert->id Unique-ID: $alert->uid Faults, Only available on alert ( $alert->state != 0 ), must be iterated in a foreach ( @foreach ($alert->faults as $key => $value) @endforeach ). Holds all available information about the Fault, accessible in the format $value['Column'] , for example: $value['ifDescr'] . Special field $value['string'] has most Identification-information (IDs, Names, Descrs) as single string, this is the equivalent of the default used and must be encased in {{ }} State: $alert->state Severity: $alert->severity Rule: $alert->rule Rule-Name: $alert->name Procedure URL: $alert->proc Timestamp: $alert->timestamp Transport type: $alert->transport Transport name: $alert->transport_name Contacts, must be iterated in a foreach, $key holds email and $value holds name: $alert->contacts Placeholders can be used within the subjects for templates as well although $faults is most likely going to be worthless. The Default Template is a 'one-size-fit-all'. We highly recommend defining your own templates for your rules to include more specific information. Base Templates If you'd like to reuse a common template for your alerts follow below A default file is located in resources/views/alerts/templates/default.blade.php Displays the following: LibreNMS Alert @yield('content') The important part being the @yield('content') You can use plain text or html as per Alert templates and this will form the basis of your common template, feel free to make as many templates in the directory as needed. In your alert template just use @extends('alerts.templates.default') @section('content') {{ $alert->title }} Severity: {{ $alert->severity }} ... @endsection More info: https://laravel.com/docs/blade#extending-a-layout Examples Default Template {{ $alert->title }} Severity: {{ $alert->severity }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Unique-ID: {{ $alert->uid }} Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif @if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) {{ $key }}: {{ $value['string'] }} @endforeach @endif Alert sent to: @foreach ($alert->contacts as $key => $value) {{ $value }} <{{ $key }}> @endforeach Ports Utilization Template {{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif @foreach ($alert->faults as $key => $value) Physical Interface: {{ $value['ifDescr'] }} Interface Description: {{ $value['ifAlias'] }} Interface Speed: {{ ($value['ifSpeed']/1000000000) }} Gbs Inbound Utilization: {{ (($value['ifInOctets_rate']*8)/$value['ifSpeed'])*100 }} Outbound Utilization: {{ (($value['ifOutOctets_rate']*8)/$value['ifSpeed'])*100 }} @endforeach Storage {{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} Uptime: {{ $alert->uptime_short }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Location: {{ $alert->location }} Description: {{ $alert->description }} Features: {{ $alert->features }} Notes: {{ $alert->notes }} Server: {{ $alert->sysName }} @foreach ($alert->faults as $key => $value) Mount Point: {{ $value['storage_descr'] }} Percent Utilized: {{ $value['storage_perc'] }} @endforeach Value Sensors (Temperature, Humidity, Fanspeed, ...) {{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} Timestamp: {{ $alert->timestamp }} Uptime: {{ $alert->uptime_short }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Location: {{ $alert->location }} Description: {{ $alert->description }} Features: {{ $alert->features }} Notes: {{ $alert->notes }} Rule: {{ $alert->name ?? $alert->rule }} @if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) @php($unit = __(\"sensors.${value[\"sensor_class\"]}.unit\")) #{{ $key }}: {{ $value['sensor_descr'] ?? 'Sensor' }} Current: {{ $value['sensor_current'].$unit }} Previous: {{ $value['sensor_prev'].$unit }} Limit: {{ $value['sensor_limit'].$unit }} Over Limit: {{ round($value['sensor_current']-$value['sensor_limit'], 2).$unit }} @endforeach @endif Memory Alert {{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} Uptime: {{ $alert->uptime_short }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Location: {{ $alert->location }} Description: {{ $alert->description }} Notes: {{ $alert->notes }} Server: {{ $alert->hostname }} @foreach ($alert->faults as $key => $value) Memory Description: {{ $value['mempool_descr'] }} Percent Utilized: {{ $value['mempool_perc'] }} @endforeach Advanced options Conditional formatting Conditional formatting example, will display a link to the host in email or just the hostname in any other transport: @if ($alert->transport == 'mail')hostname }}/\">{{ $alert->hostname }} @else {{ $alert->hostname }} @endif Traceroute debugs @if ($alert->status == 0) @if ($alert->status_reason == 'icmp') {{ $alert->debug['traceroute'] }} @endif @endif Examples HTML Note: To use HTML emails you must set HTML email to Yes in the WebUI under Global Settings > Alerting Settings > Email transport > Use HTML emails Graphs There are two helpers for graphs that will use a signed url to allow secure external access. Anyone using the signed url will be able to view the graph. Your LibreNMS web must be accessible from the location where the graph is viewed. Some alert transports require publicly accessible urls. APP_URL must be set in .env to use signed graphs. Changing APP_KEY will invalidate all previously issued singed urls. You may specify the graph one of two ways, a php array of parameters, or a direct url to a graph. Note that to and from can be specified either as timestamps with time() or as relative time -3d or -36h . When using relative time, the graph will show based on when the user views the graph, not when the event happened. Sharing a graph image with a relative time will always give the recipient access to current data, where a specific timestamp will only allow access to that timeframe. @signedGraphTag This will insert a specially formatted html img tag linking to the graph. Some transports may search the template for this tag to attach images properly for that transport. @signedGraphTag([ 'id' => $value['port_id'], 'type' => 'port_bits', 'from' => time() - 43200, 'to' => time(), 'width' => 700, 'height' => 250 ]) Output: < img class = \"librenms-graph\" src = \"https://librenms.org/graph?from=1662176216&height=250&id=20425&to=1662219416&type=port_bits&width=700&signature=f6e516e8fd893c772eeaba165d027cb400e15a515254de561a05b63bc6f360a4\" > Specific graph using url input: @signedGraphTag('https://librenms.org/graph.php?type=device_processor&from=-2d&device=2&legend=no&height=400&width=1200') @signedGraphUrl This is used when you need the url directly. One example is using the API Transport, you may want to include the url only instead of a html tag. @signedGraphUrl([ 'id' => $value['port_id'], 'type' => 'port_bits', 'from' => time() - 43200, 'to' => time(), ]) Using models for optional data If some value does not exist within the $faults[] -array, you may query fields from the database using Laravel models. You may use models to query additional values and use them on the template by placing the model and the value to search for within the braces. For example, ISIS-alerts do have a port_id value associated with the alert but ifName is not directly accessible from the $faults[] -array. If the name of the port was needed, it's value could be queried using a template such as: {{ $alert->title }} Severity: {{ $alert->severity }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif @if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) Local interface: {{ \\App\\Models\\Port::find($value['port_id'])->ifName }} Adjacent IP: {{ $value['isisISAdjIPAddrAddress'] }} Adjacent state: {{ $value['isisISAdjState'] }} @endforeach @endif Service Alert @if ($alert->state == 1) {{ $alert->severity }} @endif @if ($alert->state == 2) acknowledged @endif @if ($alert->state == 3) recovering @endif @if ($alert->state == 0) recovered @endif
Host: {{ $alert->hostname }}
Duration: {{ $alert->elapsed }}
@if ($alert->faults) @foreach ($alert->faults as $key => $value) {{ $value['service_desc'] }} - {{ $value['service_type'] }}
{{ $value['service_message'] }}
@endforeach @endif Processor Alert with Graph {{ $alert->title }}
Severity: {{ $alert->severity }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }}
Alert-ID: {{ $alert->id }}
Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif
@if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) {{ $key }}: {{ $value['string'] }}
@endforeach @if ($alert->faults) Faults:
@foreach ($alert->faults as $key => $value) @signedGraphTag(['device' => $value['device_id'], 'type' => 'device_processor', 'width' => 459, 'height' => 213, 'from' => time() - 259200])
https://server/graphs/device={{ $value['device_id'] }}/type=device_processor/
@endforeach Template: CPU alert
@endif @endif Included We include a few templates for you to use, these are specific to the type of alert rules you are creating. For example if you create a rule that would alert on BGP sessions then you can assign the BGP template to this rule to provide more information. The included templates apart from the default template are: BGP Sessions Ports Temperature Other Examples Microsoft Teams - Markdown [{{ $alert->title }}](https://your.librenms.url/device/device={{ $alert->device_id }}/) **Device name:** {{ $alert->sysName }} **Severity:** {{ $alert->severity }} @if ($alert->state == 0) **Time elapsed:** {{ $alert->elapsed }} @endif **Timestamp:** {{ $alert->timestamp }} **Unique-ID:** {{ $alert->uid }} @if ($alert->name) **Rule:** {{ $alert->name }} @else **Rule:** {{ $alert->rule }} @endif @if ($alert->faults) **Faults:**@foreach ($alert->faults as $key => $value) {{ $key }}: {{ $value['string'] }} @endforeach @endif Microsoft Teams - JSON { \"@context\": \"https://schema.org/extensions\", \"@type\": \"MessageCard\", \"title\": \"{{ $alert->title }}\", @if ($alert->state === 0) \"themeColor\": \"00FF00\", @elseif ($alert->state === 1) \"themeColor\": \"FF0000\", @elseif ($alert->state === 2) \"themeColor\": \"337AB7\", @elseif ($alert->state === 3) \"themeColor\": \"FF0000\", @elseif ($alert->state === 4) \"themeColor\": \"F0AD4E\", @else \"themeColor\": \"337AB7\", @endif \"summary\": \"LibreNMS\", \"sections\": [ { @if ($alert->name) \"facts\": [ { \"name\": \"Rule:\", \"value\": \"[{{ $alert->name }}](https://your.librenms.url/device/device={{ $alert->device_id }}/tab=alert/)\" }, @else { \"name\": \"Rule:\", \"value\": \"[{{ $alert->rule }}](https://your.librenms.url/device/device={{ $alert->device_id }}/tab=alert/)\" }, @endif { \"name\": \"Severity:\", \"value\": \"{{ $alert->severity }}\" }, { \"name\": \"Unique-ID:\", \"value\": \"{{ $alert->uid }}\" }, { \"name\": \"Timestamp:\", \"value\": \"{{ $alert->timestamp }}\" }, @if ($alert->state == 0) { \"name\": \"Time elapsed:\", \"value\": \"{{ $alert->elapsed }}\" }, @endif { \"name\": \"Hostname:\", \"value\": \"[{{ $alert->hostname }}](https://your.librenms.url/device/device={{ $alert->device_id }}/)\" }, { \"name\": \"Hardware:\", \"value\": \"{{ $alert->hardware }}\" }, { \"name\": \"IP:\", \"value\": \"{{ $alert->ip }}\" }, { \"name\": \"Faults:\", \"value\": \" \" } ] @if ($alert->faults) @foreach ($alert->faults as $key => $value) }, { \"facts\": [ { \"name\": \"Port:\", \"value\": \"[{{ $value['ifName'] }}](https://your.librenms.url/device/device={{ $alert->device_id }}/tab=port/port={{ $value['port_id'] }}/)\" }, { \"name\": \"Description:\", \"value\": \"{{ $value['ifAlias'] }}\" }, @if ($alert->state != 0) { \"name\": \"Status:\", \"value\": \"down\" } ] @else { \"name\": \"Status:\", \"value\": \"up\" } ] @endif @endforeach @endif } ] }","title":"Templates"},{"location":"Alerting/Templates/#templates","text":"This page is for installs running version 1.42 or later. You can find the older docs here Templates can be assigned to a single or a group of rules and can contain any kind of text. There is also a default template which is used for any rule that isn't associated with a template. This template can be found under Alert Templates page and can be edited. It also has an option revert it back to its default content. To attach a template to a rule just open the Alert Templates settings page, choose the template to assign and click the yellow button in the Actions column. In the appearing popupbox select the rule(s) you want the template to be assigned to and click the Attach button. You might hold down the CTRL key to select multiple rules at once. The templating engine in use is Laravel Blade. We will cover some of the basics here, however the official Laravel docs will have more information here","title":"Templates"},{"location":"Alerting/Templates/#syntax","text":"Controls: if-else (Else can be omitted): @if ($alert->placeholder == 'value') Some Text @else Other Text @endif foreach-loop: @foreach ($alert->faults as $key => $value) Key: $key Value: $value @endforeach Placeholders: Placeholders are special variables that if used within the template will be replaced with the relevant data, I.e: The device {{ $alert->hostname }} has been up for {{ $alert->uptime }} seconds would result in the following The device localhost has been up for 30344 seconds . When using placeholders to echo data, you need to wrap the placeholder in {{ }} . I.e {{ $alert->hostname }} . Device ID: $alert->device_id Hostname of the Device: $alert->hostname sysName of the Device: $alert->sysName sysDescr of the Device: $alert->sysDescr display name of the Device: $alert->display sysContact of the Device: $alert->sysContact OS of the Device: $alert->os Type of Device: $alert->type IP of the Device: $alert->ip Hardware of the Device: $alert->hardware Software version of the Device: $alert->version Features of the Device: $alert->features Serial number of the Device: $alert->serial Location of the Device: $alert->location uptime of the Device (in seconds): $alert->uptime Short uptime of the Device (28d 22h 30m 7s): $alert->uptime_short Long uptime of the Device (28 days, 22h 30m 7s): $alert->uptime_long Description (purpose db field) of the Device: $alert->description Notes of the Device: $alert->notes Notes of the alert (ack notes): $alert->alert_notes ping timestamp (if icmp enabled): $alert->ping_timestamp ping loss (if icmp enabled): $alert->ping_loss ping min (if icmp enabled): $alert->ping_min ping max (if icmp enabled): $alert->ping_max ping avg (if icmp enabled): $alert->ping_avg debug (array) poller_name - name of poller (for distributed setups) If $config['debug']['run_trace] = true; is set then this will contain: traceroute (if enabled you will receive traceroute output): $alert->debug['traceroute'] traceroute_output (if the traceroute fails this will contain why): $alert->debug['traceroute_output'] Title for the Alert: $alert->title Time Elapsed, Only available on recovery ( $alert->state == 0 ): $alert->elapsed Rule Builder (the actual rule) (use {!! $alert->builder !!} ): $alert->builder Alert-ID: $alert->id Unique-ID: $alert->uid Faults, Only available on alert ( $alert->state != 0 ), must be iterated in a foreach ( @foreach ($alert->faults as $key => $value) @endforeach ). Holds all available information about the Fault, accessible in the format $value['Column'] , for example: $value['ifDescr'] . Special field $value['string'] has most Identification-information (IDs, Names, Descrs) as single string, this is the equivalent of the default used and must be encased in {{ }} State: $alert->state Severity: $alert->severity Rule: $alert->rule Rule-Name: $alert->name Procedure URL: $alert->proc Timestamp: $alert->timestamp Transport type: $alert->transport Transport name: $alert->transport_name Contacts, must be iterated in a foreach, $key holds email and $value holds name: $alert->contacts Placeholders can be used within the subjects for templates as well although $faults is most likely going to be worthless. The Default Template is a 'one-size-fit-all'. We highly recommend defining your own templates for your rules to include more specific information.","title":"Syntax"},{"location":"Alerting/Templates/#base-templates","text":"If you'd like to reuse a common template for your alerts follow below A default file is located in resources/views/alerts/templates/default.blade.php Displays the following: LibreNMS Alert @yield('content') The important part being the @yield('content') You can use plain text or html as per Alert templates and this will form the basis of your common template, feel free to make as many templates in the directory as needed. In your alert template just use @extends('alerts.templates.default') @section('content') {{ $alert->title }} Severity: {{ $alert->severity }} ... @endsection More info: https://laravel.com/docs/blade#extending-a-layout","title":"Base Templates"},{"location":"Alerting/Templates/#examples","text":"","title":"Examples"},{"location":"Alerting/Templates/#default-template","text":"{{ $alert->title }} Severity: {{ $alert->severity }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Unique-ID: {{ $alert->uid }} Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif @if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) {{ $key }}: {{ $value['string'] }} @endforeach @endif Alert sent to: @foreach ($alert->contacts as $key => $value) {{ $value }} <{{ $key }}> @endforeach","title":"Default Template"},{"location":"Alerting/Templates/#ports-utilization-template","text":"{{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif @foreach ($alert->faults as $key => $value) Physical Interface: {{ $value['ifDescr'] }} Interface Description: {{ $value['ifAlias'] }} Interface Speed: {{ ($value['ifSpeed']/1000000000) }} Gbs Inbound Utilization: {{ (($value['ifInOctets_rate']*8)/$value['ifSpeed'])*100 }} Outbound Utilization: {{ (($value['ifOutOctets_rate']*8)/$value['ifSpeed'])*100 }} @endforeach","title":"Ports Utilization Template"},{"location":"Alerting/Templates/#storage","text":"{{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} Uptime: {{ $alert->uptime_short }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Location: {{ $alert->location }} Description: {{ $alert->description }} Features: {{ $alert->features }} Notes: {{ $alert->notes }} Server: {{ $alert->sysName }} @foreach ($alert->faults as $key => $value) Mount Point: {{ $value['storage_descr'] }} Percent Utilized: {{ $value['storage_perc'] }} @endforeach","title":"Storage"},{"location":"Alerting/Templates/#value-sensors-temperature-humidity-fanspeed","text":"{{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} Timestamp: {{ $alert->timestamp }} Uptime: {{ $alert->uptime_short }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Location: {{ $alert->location }} Description: {{ $alert->description }} Features: {{ $alert->features }} Notes: {{ $alert->notes }} Rule: {{ $alert->name ?? $alert->rule }} @if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) @php($unit = __(\"sensors.${value[\"sensor_class\"]}.unit\")) #{{ $key }}: {{ $value['sensor_descr'] ?? 'Sensor' }} Current: {{ $value['sensor_current'].$unit }} Previous: {{ $value['sensor_prev'].$unit }} Limit: {{ $value['sensor_limit'].$unit }} Over Limit: {{ round($value['sensor_current']-$value['sensor_limit'], 2).$unit }} @endforeach @endif","title":"Value Sensors (Temperature, Humidity, Fanspeed, ...)"},{"location":"Alerting/Templates/#memory-alert","text":"{{ $alert->title }} Device Name: {{ $alert->hostname }} Severity: {{ $alert->severity }} Uptime: {{ $alert->uptime_short }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Location: {{ $alert->location }} Description: {{ $alert->description }} Notes: {{ $alert->notes }} Server: {{ $alert->hostname }} @foreach ($alert->faults as $key => $value) Memory Description: {{ $value['mempool_descr'] }} Percent Utilized: {{ $value['mempool_perc'] }} @endforeach","title":"Memory Alert"},{"location":"Alerting/Templates/#advanced-options","text":"","title":"Advanced options"},{"location":"Alerting/Templates/#conditional-formatting","text":"Conditional formatting example, will display a link to the host in email or just the hostname in any other transport: @if ($alert->transport == 'mail')hostname }}/\">{{ $alert->hostname }} @else {{ $alert->hostname }} @endif","title":"Conditional formatting"},{"location":"Alerting/Templates/#traceroute-debugs","text":"@if ($alert->status == 0) @if ($alert->status_reason == 'icmp') {{ $alert->debug['traceroute'] }} @endif @endif","title":"Traceroute debugs"},{"location":"Alerting/Templates/#examples-html","text":"Note: To use HTML emails you must set HTML email to Yes in the WebUI under Global Settings > Alerting Settings > Email transport > Use HTML emails","title":"Examples HTML"},{"location":"Alerting/Templates/#graphs","text":"There are two helpers for graphs that will use a signed url to allow secure external access. Anyone using the signed url will be able to view the graph. Your LibreNMS web must be accessible from the location where the graph is viewed. Some alert transports require publicly accessible urls. APP_URL must be set in .env to use signed graphs. Changing APP_KEY will invalidate all previously issued singed urls. You may specify the graph one of two ways, a php array of parameters, or a direct url to a graph. Note that to and from can be specified either as timestamps with time() or as relative time -3d or -36h . When using relative time, the graph will show based on when the user views the graph, not when the event happened. Sharing a graph image with a relative time will always give the recipient access to current data, where a specific timestamp will only allow access to that timeframe.","title":"Graphs"},{"location":"Alerting/Templates/#signedgraphtag","text":"This will insert a specially formatted html img tag linking to the graph. Some transports may search the template for this tag to attach images properly for that transport. @signedGraphTag([ 'id' => $value['port_id'], 'type' => 'port_bits', 'from' => time() - 43200, 'to' => time(), 'width' => 700, 'height' => 250 ]) Output: < img class = \"librenms-graph\" src = \"https://librenms.org/graph?from=1662176216&height=250&id=20425&to=1662219416&type=port_bits&width=700&signature=f6e516e8fd893c772eeaba165d027cb400e15a515254de561a05b63bc6f360a4\" > Specific graph using url input: @signedGraphTag('https://librenms.org/graph.php?type=device_processor&from=-2d&device=2&legend=no&height=400&width=1200')","title":"@signedGraphTag"},{"location":"Alerting/Templates/#signedgraphurl","text":"This is used when you need the url directly. One example is using the API Transport, you may want to include the url only instead of a html tag. @signedGraphUrl([ 'id' => $value['port_id'], 'type' => 'port_bits', 'from' => time() - 43200, 'to' => time(), ])","title":"@signedGraphUrl"},{"location":"Alerting/Templates/#using-models-for-optional-data","text":"If some value does not exist within the $faults[] -array, you may query fields from the database using Laravel models. You may use models to query additional values and use them on the template by placing the model and the value to search for within the braces. For example, ISIS-alerts do have a port_id value associated with the alert but ifName is not directly accessible from the $faults[] -array. If the name of the port was needed, it's value could be queried using a template such as: {{ $alert->title }} Severity: {{ $alert->severity }} @if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }} Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif @if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) Local interface: {{ \\App\\Models\\Port::find($value['port_id'])->ifName }} Adjacent IP: {{ $value['isisISAdjIPAddrAddress'] }} Adjacent state: {{ $value['isisISAdjState'] }} @endforeach @endif","title":"Using models for optional data"},{"location":"Alerting/Templates/#service-alert","text":" @if ($alert->state == 1) {{ $alert->severity }} @endif @if ($alert->state == 2) acknowledged @endif @if ($alert->state == 3) recovering @endif @if ($alert->state == 0) recovered @endif
Host: {{ $alert->hostname }}
Duration: {{ $alert->elapsed }}
@if ($alert->faults) @foreach ($alert->faults as $key => $value) {{ $value['service_desc'] }} - {{ $value['service_type'] }}
{{ $value['service_message'] }}
@endforeach @endif ","title":"Service Alert"},{"location":"Alerting/Templates/#processor-alert-with-graph","text":"{{ $alert->title }}
Severity: {{ $alert->severity }}
@if ($alert->state == 0) Time elapsed: {{ $alert->elapsed }} @endif Timestamp: {{ $alert->timestamp }}
Alert-ID: {{ $alert->id }}
Rule: @if ($alert->name) {{ $alert->name }} @else {{ $alert->rule }} @endif
@if ($alert->faults) Faults: @foreach ($alert->faults as $key => $value) {{ $key }}: {{ $value['string'] }}
@endforeach @if ($alert->faults) Faults:
@foreach ($alert->faults as $key => $value) @signedGraphTag(['device' => $value['device_id'], 'type' => 'device_processor', 'width' => 459, 'height' => 213, 'from' => time() - 259200])
https://server/graphs/device={{ $value['device_id'] }}/type=device_processor/
@endforeach Template: CPU alert
@endif @endif","title":"Processor Alert with Graph"},{"location":"Alerting/Templates/#included","text":"We include a few templates for you to use, these are specific to the type of alert rules you are creating. For example if you create a rule that would alert on BGP sessions then you can assign the BGP template to this rule to provide more information. The included templates apart from the default template are: BGP Sessions Ports Temperature","title":"Included"},{"location":"Alerting/Templates/#other-examples","text":"","title":"Other Examples"},{"location":"Alerting/Templates/#microsoft-teams-markdown","text":"[{{ $alert->title }}](https://your.librenms.url/device/device={{ $alert->device_id }}/) **Device name:** {{ $alert->sysName }} **Severity:** {{ $alert->severity }} @if ($alert->state == 0) **Time elapsed:** {{ $alert->elapsed }} @endif **Timestamp:** {{ $alert->timestamp }} **Unique-ID:** {{ $alert->uid }} @if ($alert->name) **Rule:** {{ $alert->name }} @else **Rule:** {{ $alert->rule }} @endif @if ($alert->faults) **Faults:**@foreach ($alert->faults as $key => $value) {{ $key }}: {{ $value['string'] }} @endforeach @endif","title":"Microsoft Teams - Markdown"},{"location":"Alerting/Templates/#microsoft-teams-json","text":"{ \"@context\": \"https://schema.org/extensions\", \"@type\": \"MessageCard\", \"title\": \"{{ $alert->title }}\", @if ($alert->state === 0) \"themeColor\": \"00FF00\", @elseif ($alert->state === 1) \"themeColor\": \"FF0000\", @elseif ($alert->state === 2) \"themeColor\": \"337AB7\", @elseif ($alert->state === 3) \"themeColor\": \"FF0000\", @elseif ($alert->state === 4) \"themeColor\": \"F0AD4E\", @else \"themeColor\": \"337AB7\", @endif \"summary\": \"LibreNMS\", \"sections\": [ { @if ($alert->name) \"facts\": [ { \"name\": \"Rule:\", \"value\": \"[{{ $alert->name }}](https://your.librenms.url/device/device={{ $alert->device_id }}/tab=alert/)\" }, @else { \"name\": \"Rule:\", \"value\": \"[{{ $alert->rule }}](https://your.librenms.url/device/device={{ $alert->device_id }}/tab=alert/)\" }, @endif { \"name\": \"Severity:\", \"value\": \"{{ $alert->severity }}\" }, { \"name\": \"Unique-ID:\", \"value\": \"{{ $alert->uid }}\" }, { \"name\": \"Timestamp:\", \"value\": \"{{ $alert->timestamp }}\" }, @if ($alert->state == 0) { \"name\": \"Time elapsed:\", \"value\": \"{{ $alert->elapsed }}\" }, @endif { \"name\": \"Hostname:\", \"value\": \"[{{ $alert->hostname }}](https://your.librenms.url/device/device={{ $alert->device_id }}/)\" }, { \"name\": \"Hardware:\", \"value\": \"{{ $alert->hardware }}\" }, { \"name\": \"IP:\", \"value\": \"{{ $alert->ip }}\" }, { \"name\": \"Faults:\", \"value\": \" \" } ] @if ($alert->faults) @foreach ($alert->faults as $key => $value) }, { \"facts\": [ { \"name\": \"Port:\", \"value\": \"[{{ $value['ifName'] }}](https://your.librenms.url/device/device={{ $alert->device_id }}/tab=port/port={{ $value['port_id'] }}/)\" }, { \"name\": \"Description:\", \"value\": \"{{ $value['ifAlias'] }}\" }, @if ($alert->state != 0) { \"name\": \"Status:\", \"value\": \"down\" } ] @else { \"name\": \"Status:\", \"value\": \"up\" } ] @endif @endforeach @endif } ] }","title":"Microsoft Teams - JSON"},{"location":"Alerting/Testing/","text":"Rules The simplest way of testing if an alert rule will match a device is by going to the device, clicking edit (the cog), select Capture. From this new screen choose Alerts and click run. The output will cycle through all alerts applicable to this device and show you the Rule name, rule, MySQL query and if the rule matches. See Device Troubleshooting Transports You can test your transports by forcing an actual active alert to run regardless of the interval or delay values. ./scripts/test-alert.php . This script accepts -r for the rule id, -h for the device id or hostname and -d for debug. Templates It's possible to test your new template before assigning it to a rule. To do so you can run ./scripts/test-template.php . The script will provide the help info when ran without any parameters. As an example, if you wanted to test template ID 10 against localhost running rule ID 2 then you would run: ./scripts/test-template.php -t 10 -d -h localhost -r 2 If the rule is currently alerting for localhost then you will get the full template as expected to see on email, if it's not then you will just see the template without any fault information.","title":"Testing"},{"location":"Alerting/Testing/#rules","text":"The simplest way of testing if an alert rule will match a device is by going to the device, clicking edit (the cog), select Capture. From this new screen choose Alerts and click run. The output will cycle through all alerts applicable to this device and show you the Rule name, rule, MySQL query and if the rule matches. See Device Troubleshooting","title":"Rules"},{"location":"Alerting/Testing/#transports","text":"You can test your transports by forcing an actual active alert to run regardless of the interval or delay values. ./scripts/test-alert.php . This script accepts -r for the rule id, -h for the device id or hostname and -d for debug.","title":"Transports"},{"location":"Alerting/Testing/#templates","text":"It's possible to test your new template before assigning it to a rule. To do so you can run ./scripts/test-template.php . The script will provide the help info when ran without any parameters. As an example, if you wanted to test template ID 10 against localhost running rule ID 2 then you would run: ./scripts/test-template.php -t 10 -d -h localhost -r 2 If the rule is currently alerting for localhost then you will get the full template as expected to see on email, if it's not then you will just see the template without any fault information.","title":"Templates"},{"location":"Alerting/Transports/","text":"Transports Transports are located within LibreNMS/Alert/Transport/ and can be configured within the WebUI under Alerts -> Alert Transports. Contacts will be gathered automatically and passed to the configured transports. By default the Contacts will be only gathered when the alert triggers and will ignore future changes in contacts for the incident. If you want contacts to be re-gathered before each dispatch, please set 'Updates to contact email addresses not honored' to Off in the WebUI. The contacts will always include the SysContact defined in the Device's SNMP configuration and also every LibreNMS user that has at least read -permissions on the entity that is to be alerted. At the moment LibreNMS only supports Port or Device permissions. You can exclude the SysContact by toggling 'Issue alerts to sysContact'. To include users that have Global-Read , Administrator or Normal-User permissions it is required to toggle the options: Issue alerts to admins. Issue alerts to read only users Issue alerts to normal users. Using a Proxy Proxy Configuration Using a AMQP based Transport You need to install an additional php module : bcmath Alerta The alerta monitoring system is a tool used to consolidate and de-duplicate alerts from multiple sources for quick \u2018at-a-glance\u2019 visualisation. With just one system you can monitor alerts from many other monitoring tools on a single screen. Example: Config Example API Endpoint http://alerta.example.com/api/alert Environment Production Apy key api key with write permission Alert state critical Recover state cleared Alertmanager Alertmanager is an alert handling software, initially developed for alert processing sent by Prometheus. It has built-in functionality for deduplicating, grouping and routing alerts based on configurable criteria. LibreNMS uses alert grouping by alert rule, which can produce an array of alerts of similar content for an array of hosts, whereas Alertmanager can group them by alert meta, ideally producing one single notice in case an issue occurs. It is possible to configure as many label values as required in Alertmanager Options section. Every label and its value should be entered as a new line. Labels can be a fixed string or a dynamic variable from the alert. To set a dynamic variable your label must start with extra_ then complete with the name of your label (only characters, figures and underscore are allowed here). The value must be the name of the variable you want to get (you can see all the variables in Alerts->Notifications by clicking on the Details icon of your alert when it is pending). If the variable's name does not match with an existing value the label's value will be the string you provided just as it was a fixed string. Multiple Alertmanager URLs (comma separated) are supported. Each URL will be tried and the search will stop at the first success. Basic HTTP authentication with a username and a password is supported. If you let those value blank, no authentication will be used. Alertmanager Docs Example: Config Example Alertmanager URL(s) http://alertmanager1.example.com,http://alertmanager2.example.com Alertmanager Username myUsername Alertmanager Password myPassword Alertmanager Options: source=librenms customlabel=value extra_dynamic_value=variable_name API The API transport allows to reach any service provider using POST, PUT or GET URLs (Like SMS provider, etc). It can be used in multiple ways: The same text built from the Alert template is available in the variable $msg , which can then be sent as an option to the API. Be carefull that HTTP GET requests are usually limited in length. The API-Option fields can be directly built from the variables defined in Template-Syntax but without the 'alert->' prefix. For instance, $alert->uptime is available as $uptime in the API transport The API-Headers allows you to add the headers that the api endpoint requires. The API-body allow sending data in the format required by the API endpoint. A few variables commonly used : Variable Description {{ $hostname }} Hostname {{ $sysName }} SysName {{ $sysDescr }} SysDescr {{ $os }} OS of device (librenms defined) {{ $type }} Type of device (librenms defined) {{ $ip }} IP Address {{ $hardware }} Hardware {{ $version }} Version {{ $uptime }} Uptime in seconds {{ $uptime_short }} Uptime in human-readable format {{ $timestamp }} Timestamp of alert {{ $description }} Description of device {{ $title }} Title (as built from the Alert Template) {{ $msg }} Body text (as built from the Alert Template) Example: The example below will use the API named sms-api of my.example.com and send the title of the alert to the provided number using the provided service key. Refer to your service documentation to configure it properly. Config Example API Method GET API URL http://my.example.com/sms-api API Options rcpt=0123456789 key=0987654321abcdef msg=(LNMS) {{ $title }} API Username myUsername API Password myPassword The example below will use the API named wall-display of my.example.com and send the title and text of the alert to a screen in the Network Operation Center. Config Example API Method POST API URL http://my.example.com/wall-display API Options title={{ $title }} msg={{ $msg }} The example below will use the API named component of my.example.com with id 1, body as json status value and headers send token authentication and content type required. Config Example API Method PUT API URL http://my.example.com/comonent/1 API Headers X-Token=HASH Content-Type=application/json API Body { \"status\": 2 } aspSMS aspSMS is a SMS provider that can be configured by using the generic API Transport. You need a token you can find on your personnal space. aspSMS docs Example: Config Example Transport type Api API Method POST API URL https://soap.aspsms.com/aspsmsx.asmx/SimpleTextSMS Options UserKey=USERKEY Password=APIPASSWORD Recipient=RECIPIENT Originator=ORIGINATOR MessageText={{ $msg }} Browser Push Browser push notifications can send a notification to the user's device even when the browser is not open. This requires HTTPS, the PHP GMP extension, Push API support, and permissions on each device to send alerts. Simply configure an alert transport and allow notification permission on the device(s) you wish to receive alerts on. You may disable alerts on a browser on the user preferences page. Canopsis Canopsis is a hypervision tool. LibreNMS can send alerts to Canopsis which are then converted to canopsis events. Canopsis Docs Example: Config Example Hostname www.xxx.yyy.zzz Port Number 5672 User admin Password my_password Vhost canopsis Cisco Spark (aka Webex Teams) Cisco Spark (now known as Webex Teams). LibreNMS can send alerts to a Cisco Spark room. To make this possible you need to have a RoomID and a token. You can also choose to send alerts using Markdown syntax. Enabling this option provides for more richly formatted alerts, but be sure to adjust your alert template to account for the Markdown syntax. For more information about Cisco Spark RoomID and token, take a look here : Getting started Rooms Example: Config Example API Token ASd23r23edewda RoomID 34243243251 Use Markdown? x Clickatell Clickatell provides a REST-API requiring an Authorization-Token and at least one Cellphone number. Clickatell Docs Here an example using 3 numbers, any amount of numbers is supported: Example: Config Example Token dsaWd3rewdwea Mobile Numbers +1234567890,+1234567891,+1234567892 Discord The Discord transport will POST the alert message to your Discord Incoming WebHook. Simple html tags are stripped from the message. The only required value is for url, without this no call to Discord will be made. The Options field supports the JSON/Form Params listed in the Discord Docs below. Discord Docs Example: Config Example Discord URL https://discordapp.com/api/webhooks/4515489001665127664/82-sf4385ysuhfn34u2fhfsdePGLrg8K7cP9wl553Fg6OlZuuxJGaa1d54fe Options username=myname Elasticsearch You can have LibreNMS send alerts to an elasticsearch database. Each fault will be sent as a separate document. Example: Config Example Host 127.0.0.1 Port 9200 Index Pattern \\l\\i\\b\\r\\e\\n\\m\\s-Y.m.d GitLab LibreNMS will create issues for warning and critical level alerts however only title and description are set. Uses Personal access tokens to authenticate with GitLab and will store the token in cleartext. Example: Config Example Host http://gitlab.host.tld Project ID 1 Personal Access Token AbCdEf12345 Grafana Oncall Send alerts to Grafana Oncall using a Formatted Webhook Example: Config Example Webhook URL https://a-prod-us-central-0.grafana.net/integrations/v1/formatted_webhook/m12xmIjOcgwH74UF8CN4dk0Dh/ HipChat See the HipChat API Documentation for rooms/message for details on acceptable values. You may notice that the link points at the \"deprecated\" v1 API. This is because the v2 API is still in beta. Example: Config Example API URL https://api.hipchat.com/v1/rooms/message?auth_token=109jawregoaihj Room ID 7654321 From Name LibreNMS Options color=red At present the following options are supported: color . Note: The default message format for HipChat messages is HTML. It is recommended that you specify the text message format to prevent unexpected results, such as HipChat attempting to interpret angled brackets ( < and > ). IRC The IRC transports only works together with the LibreNMS IRC-Bot. Configuration of the LibreNMS IRC-Bot is described here . Example: Config Example IRC enabled JIRA You can have LibreNMS create issues on a Jira instance for critical and warning alerts using either the Jira REST API or webhooks. Custom fields allow you to add any required fields beyond summary and description fields in case mandatory fields are required by your Jira project/issue type configuration. Custom fields are defined in JSON format but ustom fields allow you to add any required fields beyond summary and description fields in case mandatory fields are required by your Jira project/issue type configuration. Custom fields are defined in JSON format. Currently http authentication is used to access Jira and Jira username and password will be stored as cleartext in the LibreNMS database. REST API The config fields that need to set for Jira REST API are: Jira Open URL, Jira username, Jira password, Project key, and issue type. Note: REST API is that it is only able to open new tickets. Webhooks The config fields that need to set for webhooks are: Jira Open URL, Jira Close URL, Jira username, Jira password and webhook ID. Note: Webhooks allow more control over how alerts are handled in Jira. With webhooks, recovery messages can be sent to a different URL than alerts. Additionally, a custom conditional logic can be built using the webhook payload and ID to automatically close an open ticket if predefined conditions are met. Jira Issue Types Jira Webhooks Example: Config Example Project Key JIRAPROJECTKEY Issue Type Myissuetype Open URL https://myjira.mysite.com / https://webhook-open-url Close URL https://webhook-close-url Jira Username myjirauser Jira Password myjirapass Enable webhook ON/OFF Webhook ID alert_id Custom Fileds {\"components\":[{\"id\":\"00001\"}], \"source\": \"LibrenNMS\"} Jira Service Management Using Jira Service Management LibreNMS integration, LibreNMS forwards alerts to Jira Service Management with detailed information. Jira Service Management acts as a dispatcher for LibreNMS alerts, determines the right people to notify based on on-call schedules and notifies via email, text messages (SMS), phone calls and iOS & Android push notifications. Then escalates alerts until the alert is acknowledged or closed. :warning: If the feature isn\u2019t available on your site, keep checking Jira Service Management for updates. Example: Config Example WebHook URL https://url/path/to/webhook LINE Messaging API LINE Messaging API Docs Here is the step for setup a LINE bot and using it in LibreNMS. Use your real LINE account register in developer protal . Add a new channel, choose Messaging API and continue fill up the forms, note that Channel name cannot edit later. Go to \"Messaging API\" tab of your channel, here listing some important value. Bot basic ID and QR code is your LINE bot's ID and QR code. Channel access token (long-lived) , will use it in LibreNMS, keep it safe. Use your real Line account add your LINE bot as a friend. Recipient ID can be groupID , userID or roomID , it will be used in LibreNMS to send message to a group or a user. Use the following NodeJS program and ngrok for temporally https webhook to listen it. LINE-bot-RecipientFetcher Run the program and using ngrok expose port to public $ node index.js $ ngrok http 3000 Go to \"Messaging API\" tab of your channel, fill up Webhook URL to https:///webhook If you want to let LINE bot send message to a yourself, use your real account to send a message to your LINE bot. Program will print out the userID in console. sample value: {\"type\":\"user\",\"userId\":\"U527xxxxxxxxxxxxxxxxxxxxxxxxxc0ee\"} If you want to let LINE bot send message to a group, do the following steps. Add your LINE bot into group Use your real account to send a message to group Program will print out the groupID in console, it will be Recipient ID, keep it safe. sample value: {\"type\":\"group\",\"groupId\":\"Ce51xxxxxxxxxxxxxxxxxxxxxxxxxx6ef\",\"userId\":\"U527xxxxxxxxxxxxxxxxxxxxxxxxxc0ee\"} ``` Example: Config Example Access token fhJ9vH2fsxxxxxxxxxxxxxxxxxxxxlFU= Recipient (groupID, userID or roomID) Ce51xxxxxxxxxxxxxxxxxxxxxxxxxx6ef LINE Notify LINE Notify LINE Notify API Document Example: Config Example Token AbCdEf12345 Mail The E-Mail transports uses the same email-configuration as the rest of LibreNMS. As a small reminder, here is its configuration directives including defaults: Emails will attach all graphs included with the @signedGraphTag directive. If the email format is set to html, they will be embedded. To disable attaching images, set email_attach_graphs to false. alerting/email lnms config:set email_html true lnms config:set email_attach_graphs false Example: Config Example Email me@example.com Matrix For using the Matrix transports, you have to create a room on the Matrix-server. The provided Auth_token belongs to an user, which is member of this room. The Message, sent to the matrix-room can be built from the variables defined in Template-Syntax but without the 'alert->' prefix. See API-Transport. The variable $msg is contains the result of the Alert template.The Matrix-Server URL is cutted before the beginning of the _matrix/client/r0/... API-part. Example: Config Example Matrix-Server URL https://matrix.example.com/ Room !ajPbbPalmVbNuQoBDK:example.com Auth_token: MDAyYmxvY2F0aW9uI...z1DCn6lz_uOhtW3XRICg Message: Alert: {{ $msg }} https://librenms.example.com Messagebird LibreNMS can send text messages through Messagebird Rest API transport. Config Example Api Key Api rest key given in the messagebird dashboard Originator E.164 formatted originator Recipient E.164 formatted recipient for multi recipents comma separated Character limit Range 1..480 (max 3 split messages) Messagebird Voice LibreNMS can send messages through Messagebird voice Rest API transport (text to speech). Config Example Api Key Api rest key given in the messagebird dashboard Originator E.164 formatted originator Recipient E.164 formatted recipient for multi recipents comma separated Language Select box for options Spoken voice Female or Male Repeat X times the message is repeated Microsoft Teams LibreNMS can send alerts to Microsoft Teams Incoming Webhooks which are then posted to a specific channel. Microsoft recommends using markdown formatting for connector cards. Administrators can opt to compose the MessageCard themselves using JSON to get the full functionality. Example: Config Example WebHook URL https://outlook.office365.com/webhook/123456789 Use JSON? x Nagios Compatible The nagios transport will feed a FIFO at the defined location with the same format that nagios would. This allows you to use other alerting systems with LibreNMS, for example Flapjack . Example: Config Example Nagios FIFO /path/to/my.fifo OpsGenie Using OpsGenie LibreNMS integration, LibreNMS forwards alerts to OpsGenie with detailed information. OpsGenie acts as a dispatcher for LibreNMS alerts, determines the right people to notify based on on-call schedules and notifies via email, text messages (SMS), phone calls and iOS & Android push notifications. Then escalates alerts until the alert is acknowledged or closed. Create a LibreNMS Integration from the integrations page once you signup. Then copy the API key from OpsGenie to LibreNMS. If you want to automatically ack and close alerts, leverage Marid integration. More detail with screenshots is available in OpsGenie LibreNMS Integration page . Example: Config Example WebHook URL https://url/path/to/webhook osTicket LibreNMS can send alerts to osTicket API which are then converted to osTicket tickets. Example: Config Example API URL http://osticket.example.com/api/http.php/tickets.json API Token 123456789 PagerDuty LibreNMS can make use of PagerDuty, this is done by utilizing an API key and Integraton Key. API Keys can be found under 'API Access' in the PagerDuty portal. Integration Keys can be found under 'Integration' for the particular Service you have created in the PagerDuty portal. Example: Config Example API Key randomsample Integration Key somerandomstring Philips Hue Want to spice up your noc life? LibreNMS will flash all lights connected to your philips hue bridge whenever an alert is triggered. To setup, go to the you http:// your-bridge-ip /debug/clip.html Update the \"URL:\" field to /api Paste this in the \"Message Body\" {\"devicetype\":\"librenms\"} Press the round button on your philips Hue Bridge Click on POST In the Command Response You should see output with your username. Copy this without the quotes More Info: Philips Hue Documentation Example: Config Example Host http://your-bridge-ip Hue User username Duration 1 Second PlaySMS PlaySMS is an open source SMS-Gateway that can be used via their HTTP API using a Username and WebService Token. Please consult PlaySMS's documentation regarding number formatting. PlaySMS Docs Here an example using 3 numbers, any amount of numbers is supported: Example: Config Example PlaySMS https://localhost/index.php User user1 Token MYFANCYACCESSTOKEN From My Name Mobiles +1234567892,+1234567890,+1234567891 Pushbullet Get your Access Token from your Pushbullet's settings page and set it in your transport: Example: Config Example Access Token MYFANCYACCESSTOKEN Pushover If you want to change the default notification sound for all notifications then you can add the following in Pushover Options: sound=falling You also have the possibility to change sound per severity: sound_critical=falling sound_warning=siren sound_ok=magic Enabling Pushover support is fairly easy, there are only two required parameters. Firstly you need to create a new Application (called LibreNMS, for example) in your account on the Pushover website ( https://pushover.net/apps ). Now copy your API Key and obtain your User Key from the newly created Application and setup the transport. Pushover Docs Example: Config Example Api Key APPLICATIONAPIKEYGOESHERE User Key USERKEYGOESHERE Pushover Options sound_critical=falling sound_warning=siren sound_ok=magic Rocket.chat The Rocket.chat transport will POST the alert message to your Rocket.chat Incoming WebHook using the attachments option. Simple html tags are stripped from the message. All options are optional, the only required value is for url, without this then no call to Rocket.chat will be made. Rocket.chat Docs Example: Config Example Webhook URL https://rocket.url/api/v1/chat.postMessage Rocket.chat Options channel=#Alerting username=myname icon_url=http://someurl/image.gif icon_emoji=:smirk: Sensu The Sensu transport will POST an Event to the Agent API upon an alert being generated. It will be categorised (ok, warning or critical), and if you configure the alert to send recovery notifications, Sensu will also clear the alert automatically. No configuration is required - as long as you are running the Sensu Agent on your poller with the HTTP socket enabled on tcp/3031, LibreNMS will start generating Sensu events as soon as you create the transport. Acknowledging alerts within LibreNMS is not directly supported, but an annotation ( acknowledged ) is set, so a mutator or silence, or even the handler could be written to look for it directly in the handler. There is also an annotation ( generated-by ) set, to allow you to treat LibreNMS events differently from agent events. The 'shortname' option is a simple way to reduce the length of device names in configs. It replaces the last 3 domain components with single letters (e.g. websrv08.dc4.eu.corp.example.net gets shortened to websrv08.dc4.eu.cen). Limitations Only a single namespace is supported Sensu will reject rules with special characters - the Transport will attempt to fix up rule names, but it's best to stick to letters, numbers and spaces The transport only deals in absolutes - it ignores the got worse/got better states The agent will buffer alerts, but LibreNMS will not - if your agent is offline, alerts will be dropped There is no backchannel between Sensu and LibreNMS - if you make changes in Sensu to LibreNMS alerts, they'll be lost on the next event (silences will work) Example: Config Example Sensu Endpoint http://localhost:3031 Sensu Namespace eu-west Check Prefix lnms Source Key hostname Slack The Slack transport will POST the alert message to your Slack Incoming WebHook using the attachments option, you are able to specify multiple webhooks along with the relevant options to go with it. Simple html tags are stripped from the message. All options are optional, the only required value is for url, without this then no call to Slack will be made. We currently support the following attachment options: author_name Slack docs Example: Config Example Webhook URL https://slack.com/url/somehook Slack Options author_name=Me SMSEagle SMSEagle is a hardware SMS Gateway that can be used via their HTTP API using a Username and password. Destination numbers are one per line, with no spaces. They can be in either local or international dialling format. SMSEagle Docs Example: Config Example SMSEagle Host ip.add.re.ss User smseagle_user Password smseagle_user_password Mobiles +3534567890 0834567891 SMSmode SMSmode is a SMS provider that can be configured by using the generic API Transport. You need a token you can find on your personnal space. SMSmode docs Example: Config Example Transport type Api API Method POST API URL http://api.smsmode.com/http/1.6/sendSMS.do Options accessToken= PUT_HERE_YOUR_TOKEN numero= PUT_HERE_DESTS_NUMBER_COMMA_SEPARATED message={{ $msg }} Splunk LibreNMS can send alerts to a Splunk instance and provide all device and alert details. Example output: Feb 21 15:21:52 nms hostname=\"localhost\", sysName=\"localhost\", sysDescr=\"\", sysContact=\"\", os=\"fortigate\", type=\"firewall\", ip=\"localhost\", hardware=\"FGT_50E\", version=\"v5.6.9\", serial=\"\", features=\"\", location=\"\", uptime=\"387\", uptime_short=\" 6m 27s\", uptime_long=\" 6 minutes 27 seconds\", description=\"\", notes=\"\", alert_notes=\"\", device_id=\"0\", rule_id=\"0\", id=\"0\", proc=\"\", status=\"1\", status_reason=\"\", ping_timestamp=\"\", ping_loss=\"0\", ping_min=\"25.6\", ping_max=\"26.8\", ping_avg=\"26.3\", title=\"localhost recovered from Device up/down \", elapsed=\"14m 54s\", uid=\"0\", alert_id=\"0\", severity=\"critical\", name=\"Device up/down\", timestamp=\"2020-02-21 15:21:33\", state=\"0\", device_device_id=\"0\", device_inserted=\"\", device_hostname=\"localhost\", device_sysName=\"localhost\", device_ip=\"localhost\", device_overwrite_ip=\"\", device_timeout=\"\", device_retries=\"\", device_snmp_disable=\"0\", device_bgpLocalAs=\"0\", device_sysObjectID=\"\", device_sysDescr=\"\", device_sysContact=\"\", device_version=\"v5.6.9\", device_hardware=\"FGT_50E\", device_features=\"build1673\", device_location_id=\"\", device_os=\"fortigate\", device_status=\"1\", device_status_reason=\"\", device_ignore=\"0\", device_disabled=\"0\", device_uptime=\"387\", device_agent_uptime=\"0\", device_last_polled=\"2020-02-21 15:21:33\", device_last_poll_attempted=\"\", device_last_polled_timetaken=\"7.9\", device_last_discovered_timetaken=\"11.77\", device_last_discovered=\"2020-02-21 13:16:42\", device_last_ping=\"2020-02-21 15:21:33\", device_last_ping_timetaken=\"26.3\", device_purpose=\"\", device_type=\"firewall\", device_serial=\"FGT50EXXX\", device_icon=\"images/os/fortinet.svg\", device_poller_group=\"0\", device_override_sysLocation=\"0\", device_notes=\"\", device_port_association_mode=\"1\", device_max_depth=\"0\", device_disable_notify=\"0\", device_location=\"\", device_vrf_lites=\"Array\", device_lat=\"\", device_lng=\"\", - sysObjectID => \"\"; ` Each alert will be sent as a separate message. Example: Config Example Host 127.0.0.1 UDP Port 514 Syslog You can have LibreNMS emit alerts as syslogs complying with RFC 3164. More information on RFC 3164 can be found here: https://tools.ietf.org/html/rfc3164 Example output: <26> Mar 22 00:59:03 librenms.host.net librenms[233]: [Critical] network.device.net: Port Down - port_id => 98939; ifDescr => xe-1/1/0; Each fault will be sent as a separate syslog. Example: Config Example Host 127.0.0.1 Port 514 Facility 3 Telegram Thank you to snis for these instructions. First you must create a telegram account and add BotFather to you list. To do this click on the following url: https://telegram.me/botfather Generate a new bot with the command \"/newbot\" BotFather is then asking for a username and a normal name. After that your bot is created and you get a HTTP token. (for more options for your bot type \"/help\") Add your bot to telegram with the following url: http://telegram.me/ to use app or https://web.telegram.org/ to use in web, and send some text to the bot. The BotFather should have responded with a token, copy your token code and go to the following page in chrome: https://api.telegram.org/bot/getUpdates (this could take a while so continue to refresh until you see something similar to below) You see a json code with the message you sent to the bot. Copy the Chat id. In this example that is \u201c-9787468\u201d within this example: \"message\":{\"message_id\":7,\"from\":\"id\":656556,\"first_name\":\"Joo\",\"last_name\":\"Doo\",\"username\":\"JohnDoo\"},\"chat\":{\"id\":-9787468,\"title\":\"Telegram Group\"},\"date\":1435216924,\"text\":\"Hi\"}}]} . Now create a new \"Telegram transport\" in LibreNMS (Global Settings -> Alerting Settings -> Telegram transport). Click on 'Add Telegram config' and put your chat id and token into the relevant box. If want to use a group to receive alerts, you need to pick the Chat ID of the group chat, and not of the Bot itself. Telegram Docs Example: Config Example Chat ID 34243432 Token 3ed32wwf235234 Format HTML or MARKDOWN Twilio SMS Twilio will send your alert via SMS. From your Twilio account you will need your account SID, account token and your Twilio SMS phone number that you would like to send the alerts from. Twilio's APIs are located at: https://www.twilio.com/docs/api?filter-product=sms Example: Config Example SID ACxxxxxxxxxxxxxxxxxxxxxxxxxxxx Token 7xxxx573acxxxbc2xxx308d6xxx652d32 Twilio SMS Number 8888778660 UKFast PSS UKFast PSS tickets can be raised from alerts using the UKFastPSS transport. This required an API key with PSS write permissions Example: Config Example API Key ABCDefgfg12 Author 5423 Priority Critical Secure true VictorOps VictorOps provide a webHook url to make integration extremely simple. To get the URL required login to your VictorOps account and go to: Settings -> Integrations -> REST Endpoint -> Enable Integration. The URL provided will have $routing_key at the end, you need to change this to something that is unique to the system sending the alerts such as librenms. I.e: https://alert.victorops.com/integrations/generic/20132414/alert/2f974ce1-08fc-4dg8-a4f4-9aee6cf35c98/librenms Example: Config Example Post URL https://alert.victorops.com/integrations/generic/20132414/alert/2f974ce1-08fc-4dg8-a4f4-9aee6cf35c98/librenms Kayako Classic LibreNMS can send alerts to Kayako Classic API which are then converted to tickets. To use this module, you need REST API feature enabled in Kayako Classic and configured email account at LibreNMS. To enable this, do this: AdminCP -> REST API -> Settings -> Enable API (Yes) Also you need to know the department id to provide tickets to appropriate department and a user email to provide, which is used as ticket author. To get department id: navigate to appropriate department name at the departments list page in Admin CP and watch the number at the end of url. Example: http://servicedesk.example.com/admin/Base/Department/Edit/17 . Department ID is 17 As a requirement, you have to know API Url, API Key and API Secret to connect to servicedesk Kayako REST API Docs Example: Config Example Kayako URL http://servicedesk.example.com/api/ Kayako API Key 8cc02f38-7465-4a0c-8730-bb3af122167b Kayako API Secret Y2NhZDIxNDMtNjVkMi0wYzE0LWExYTUtZGUwMjJiZDI0ZWEzMmRhOGNiYWMtNTU2YS0yODk0LTA1MTEtN2VhN2YzYzgzZjk5 Kayako Department 1 Signal CLI Use the Signal Mesenger for Alerts. Run the Signal CLI with the D-Bus option. GitHub Project Example: Config Example Path /opt/signal-cli/bin/signal-cli Recipient type Group Recipient dfgjsdkgljior4345== SMSFeedback SMSFeedback is a SAAS service, which can be used to deliver Alerts via API, using API url, Username & Password. They can be in international dialling format only. SMSFeedback Api Docs Example: Config Example User smsfeedback_user Password smsfeedback_password Mobiles 71234567890 Sender name CIA Zenduty Leveraging LibreNMS<>Zenduty Integration, users can send new LibreNMS alerts to the right team and notify them based on on-call schedules via email, SMS, Phone Calls, Slack, Microsoft Teams and mobile push notifications. Zenduty provides engineers with detailed context around the LibreNMS alert along with playbooks and a complete incident command framework to triage, remediate and resolve incidents with speed. Create a LibreNMS Integration from inside Zenduty , then copy the Webhook URL from Zenduty to LibreNMS. For a detailed guide with screenshots, refer to the LibreNMS documentation at Zenduty . Example: Config Example WebHook URL https://www.zenduty.com/api/integration/librenms/integration-key/","title":"Transports"},{"location":"Alerting/Transports/#transports","text":"Transports are located within LibreNMS/Alert/Transport/ and can be configured within the WebUI under Alerts -> Alert Transports. Contacts will be gathered automatically and passed to the configured transports. By default the Contacts will be only gathered when the alert triggers and will ignore future changes in contacts for the incident. If you want contacts to be re-gathered before each dispatch, please set 'Updates to contact email addresses not honored' to Off in the WebUI. The contacts will always include the SysContact defined in the Device's SNMP configuration and also every LibreNMS user that has at least read -permissions on the entity that is to be alerted. At the moment LibreNMS only supports Port or Device permissions. You can exclude the SysContact by toggling 'Issue alerts to sysContact'. To include users that have Global-Read , Administrator or Normal-User permissions it is required to toggle the options: Issue alerts to admins. Issue alerts to read only users Issue alerts to normal users.","title":"Transports"},{"location":"Alerting/Transports/#using-a-proxy","text":"Proxy Configuration","title":"Using a Proxy"},{"location":"Alerting/Transports/#using-a-amqp-based-transport","text":"You need to install an additional php module : bcmath","title":"Using a AMQP based Transport"},{"location":"Alerting/Transports/#alerta","text":"The alerta monitoring system is a tool used to consolidate and de-duplicate alerts from multiple sources for quick \u2018at-a-glance\u2019 visualisation. With just one system you can monitor alerts from many other monitoring tools on a single screen. Example: Config Example API Endpoint http://alerta.example.com/api/alert Environment Production Apy key api key with write permission Alert state critical Recover state cleared","title":"Alerta"},{"location":"Alerting/Transports/#alertmanager","text":"Alertmanager is an alert handling software, initially developed for alert processing sent by Prometheus. It has built-in functionality for deduplicating, grouping and routing alerts based on configurable criteria. LibreNMS uses alert grouping by alert rule, which can produce an array of alerts of similar content for an array of hosts, whereas Alertmanager can group them by alert meta, ideally producing one single notice in case an issue occurs. It is possible to configure as many label values as required in Alertmanager Options section. Every label and its value should be entered as a new line. Labels can be a fixed string or a dynamic variable from the alert. To set a dynamic variable your label must start with extra_ then complete with the name of your label (only characters, figures and underscore are allowed here). The value must be the name of the variable you want to get (you can see all the variables in Alerts->Notifications by clicking on the Details icon of your alert when it is pending). If the variable's name does not match with an existing value the label's value will be the string you provided just as it was a fixed string. Multiple Alertmanager URLs (comma separated) are supported. Each URL will be tried and the search will stop at the first success. Basic HTTP authentication with a username and a password is supported. If you let those value blank, no authentication will be used. Alertmanager Docs Example: Config Example Alertmanager URL(s) http://alertmanager1.example.com,http://alertmanager2.example.com Alertmanager Username myUsername Alertmanager Password myPassword Alertmanager Options: source=librenms customlabel=value extra_dynamic_value=variable_name","title":"Alertmanager"},{"location":"Alerting/Transports/#api","text":"The API transport allows to reach any service provider using POST, PUT or GET URLs (Like SMS provider, etc). It can be used in multiple ways: The same text built from the Alert template is available in the variable $msg , which can then be sent as an option to the API. Be carefull that HTTP GET requests are usually limited in length. The API-Option fields can be directly built from the variables defined in Template-Syntax but without the 'alert->' prefix. For instance, $alert->uptime is available as $uptime in the API transport The API-Headers allows you to add the headers that the api endpoint requires. The API-body allow sending data in the format required by the API endpoint. A few variables commonly used : Variable Description {{ $hostname }} Hostname {{ $sysName }} SysName {{ $sysDescr }} SysDescr {{ $os }} OS of device (librenms defined) {{ $type }} Type of device (librenms defined) {{ $ip }} IP Address {{ $hardware }} Hardware {{ $version }} Version {{ $uptime }} Uptime in seconds {{ $uptime_short }} Uptime in human-readable format {{ $timestamp }} Timestamp of alert {{ $description }} Description of device {{ $title }} Title (as built from the Alert Template) {{ $msg }} Body text (as built from the Alert Template) Example: The example below will use the API named sms-api of my.example.com and send the title of the alert to the provided number using the provided service key. Refer to your service documentation to configure it properly. Config Example API Method GET API URL http://my.example.com/sms-api API Options rcpt=0123456789 key=0987654321abcdef msg=(LNMS) {{ $title }} API Username myUsername API Password myPassword The example below will use the API named wall-display of my.example.com and send the title and text of the alert to a screen in the Network Operation Center. Config Example API Method POST API URL http://my.example.com/wall-display API Options title={{ $title }} msg={{ $msg }} The example below will use the API named component of my.example.com with id 1, body as json status value and headers send token authentication and content type required. Config Example API Method PUT API URL http://my.example.com/comonent/1 API Headers X-Token=HASH Content-Type=application/json API Body { \"status\": 2 }","title":"API"},{"location":"Alerting/Transports/#aspsms","text":"aspSMS is a SMS provider that can be configured by using the generic API Transport. You need a token you can find on your personnal space. aspSMS docs Example: Config Example Transport type Api API Method POST API URL https://soap.aspsms.com/aspsmsx.asmx/SimpleTextSMS Options UserKey=USERKEY Password=APIPASSWORD Recipient=RECIPIENT Originator=ORIGINATOR MessageText={{ $msg }}","title":"aspSMS"},{"location":"Alerting/Transports/#browser-push","text":"Browser push notifications can send a notification to the user's device even when the browser is not open. This requires HTTPS, the PHP GMP extension, Push API support, and permissions on each device to send alerts. Simply configure an alert transport and allow notification permission on the device(s) you wish to receive alerts on. You may disable alerts on a browser on the user preferences page.","title":"Browser Push"},{"location":"Alerting/Transports/#canopsis","text":"Canopsis is a hypervision tool. LibreNMS can send alerts to Canopsis which are then converted to canopsis events. Canopsis Docs Example: Config Example Hostname www.xxx.yyy.zzz Port Number 5672 User admin Password my_password Vhost canopsis","title":"Canopsis"},{"location":"Alerting/Transports/#cisco-spark-aka-webex-teams","text":"Cisco Spark (now known as Webex Teams). LibreNMS can send alerts to a Cisco Spark room. To make this possible you need to have a RoomID and a token. You can also choose to send alerts using Markdown syntax. Enabling this option provides for more richly formatted alerts, but be sure to adjust your alert template to account for the Markdown syntax. For more information about Cisco Spark RoomID and token, take a look here : Getting started Rooms Example: Config Example API Token ASd23r23edewda RoomID 34243243251 Use Markdown? x","title":"Cisco Spark (aka Webex Teams)"},{"location":"Alerting/Transports/#clickatell","text":"Clickatell provides a REST-API requiring an Authorization-Token and at least one Cellphone number. Clickatell Docs Here an example using 3 numbers, any amount of numbers is supported: Example: Config Example Token dsaWd3rewdwea Mobile Numbers +1234567890,+1234567891,+1234567892","title":"Clickatell"},{"location":"Alerting/Transports/#discord","text":"The Discord transport will POST the alert message to your Discord Incoming WebHook. Simple html tags are stripped from the message. The only required value is for url, without this no call to Discord will be made. The Options field supports the JSON/Form Params listed in the Discord Docs below. Discord Docs Example: Config Example Discord URL https://discordapp.com/api/webhooks/4515489001665127664/82-sf4385ysuhfn34u2fhfsdePGLrg8K7cP9wl553Fg6OlZuuxJGaa1d54fe Options username=myname","title":"Discord"},{"location":"Alerting/Transports/#elasticsearch","text":"You can have LibreNMS send alerts to an elasticsearch database. Each fault will be sent as a separate document. Example: Config Example Host 127.0.0.1 Port 9200 Index Pattern \\l\\i\\b\\r\\e\\n\\m\\s-Y.m.d","title":"Elasticsearch"},{"location":"Alerting/Transports/#gitlab","text":"LibreNMS will create issues for warning and critical level alerts however only title and description are set. Uses Personal access tokens to authenticate with GitLab and will store the token in cleartext. Example: Config Example Host http://gitlab.host.tld Project ID 1 Personal Access Token AbCdEf12345","title":"GitLab"},{"location":"Alerting/Transports/#grafana-oncall","text":"Send alerts to Grafana Oncall using a Formatted Webhook Example: Config Example Webhook URL https://a-prod-us-central-0.grafana.net/integrations/v1/formatted_webhook/m12xmIjOcgwH74UF8CN4dk0Dh/","title":"Grafana Oncall"},{"location":"Alerting/Transports/#hipchat","text":"See the HipChat API Documentation for rooms/message for details on acceptable values. You may notice that the link points at the \"deprecated\" v1 API. This is because the v2 API is still in beta. Example: Config Example API URL https://api.hipchat.com/v1/rooms/message?auth_token=109jawregoaihj Room ID 7654321 From Name LibreNMS Options color=red At present the following options are supported: color . Note: The default message format for HipChat messages is HTML. It is recommended that you specify the text message format to prevent unexpected results, such as HipChat attempting to interpret angled brackets ( < and > ).","title":"HipChat"},{"location":"Alerting/Transports/#irc","text":"The IRC transports only works together with the LibreNMS IRC-Bot. Configuration of the LibreNMS IRC-Bot is described here . Example: Config Example IRC enabled","title":"IRC"},{"location":"Alerting/Transports/#jira","text":"You can have LibreNMS create issues on a Jira instance for critical and warning alerts using either the Jira REST API or webhooks. Custom fields allow you to add any required fields beyond summary and description fields in case mandatory fields are required by your Jira project/issue type configuration. Custom fields are defined in JSON format but ustom fields allow you to add any required fields beyond summary and description fields in case mandatory fields are required by your Jira project/issue type configuration. Custom fields are defined in JSON format. Currently http authentication is used to access Jira and Jira username and password will be stored as cleartext in the LibreNMS database.","title":"JIRA"},{"location":"Alerting/Transports/#rest-api","text":"The config fields that need to set for Jira REST API are: Jira Open URL, Jira username, Jira password, Project key, and issue type. Note: REST API is that it is only able to open new tickets.","title":"REST API"},{"location":"Alerting/Transports/#webhooks","text":"The config fields that need to set for webhooks are: Jira Open URL, Jira Close URL, Jira username, Jira password and webhook ID. Note: Webhooks allow more control over how alerts are handled in Jira. With webhooks, recovery messages can be sent to a different URL than alerts. Additionally, a custom conditional logic can be built using the webhook payload and ID to automatically close an open ticket if predefined conditions are met. Jira Issue Types Jira Webhooks Example: Config Example Project Key JIRAPROJECTKEY Issue Type Myissuetype Open URL https://myjira.mysite.com / https://webhook-open-url Close URL https://webhook-close-url Jira Username myjirauser Jira Password myjirapass Enable webhook ON/OFF Webhook ID alert_id Custom Fileds {\"components\":[{\"id\":\"00001\"}], \"source\": \"LibrenNMS\"}","title":"Webhooks"},{"location":"Alerting/Transports/#jira-service-management","text":"Using Jira Service Management LibreNMS integration, LibreNMS forwards alerts to Jira Service Management with detailed information. Jira Service Management acts as a dispatcher for LibreNMS alerts, determines the right people to notify based on on-call schedules and notifies via email, text messages (SMS), phone calls and iOS & Android push notifications. Then escalates alerts until the alert is acknowledged or closed. :warning: If the feature isn\u2019t available on your site, keep checking Jira Service Management for updates. Example: Config Example WebHook URL https://url/path/to/webhook","title":"Jira Service Management"},{"location":"Alerting/Transports/#line-messaging-api","text":"LINE Messaging API Docs Here is the step for setup a LINE bot and using it in LibreNMS. Use your real LINE account register in developer protal . Add a new channel, choose Messaging API and continue fill up the forms, note that Channel name cannot edit later. Go to \"Messaging API\" tab of your channel, here listing some important value. Bot basic ID and QR code is your LINE bot's ID and QR code. Channel access token (long-lived) , will use it in LibreNMS, keep it safe. Use your real Line account add your LINE bot as a friend. Recipient ID can be groupID , userID or roomID , it will be used in LibreNMS to send message to a group or a user. Use the following NodeJS program and ngrok for temporally https webhook to listen it. LINE-bot-RecipientFetcher Run the program and using ngrok expose port to public $ node index.js $ ngrok http 3000 Go to \"Messaging API\" tab of your channel, fill up Webhook URL to https:///webhook If you want to let LINE bot send message to a yourself, use your real account to send a message to your LINE bot. Program will print out the userID in console. sample value: {\"type\":\"user\",\"userId\":\"U527xxxxxxxxxxxxxxxxxxxxxxxxxc0ee\"} If you want to let LINE bot send message to a group, do the following steps. Add your LINE bot into group Use your real account to send a message to group Program will print out the groupID in console, it will be Recipient ID, keep it safe. sample value: {\"type\":\"group\",\"groupId\":\"Ce51xxxxxxxxxxxxxxxxxxxxxxxxxx6ef\",\"userId\":\"U527xxxxxxxxxxxxxxxxxxxxxxxxxc0ee\"} ``` Example: Config Example Access token fhJ9vH2fsxxxxxxxxxxxxxxxxxxxxlFU= Recipient (groupID, userID or roomID) Ce51xxxxxxxxxxxxxxxxxxxxxxxxxx6ef","title":"LINE Messaging API"},{"location":"Alerting/Transports/#line-notify","text":"LINE Notify LINE Notify API Document Example: Config Example Token AbCdEf12345","title":"LINE Notify"},{"location":"Alerting/Transports/#mail","text":"The E-Mail transports uses the same email-configuration as the rest of LibreNMS. As a small reminder, here is its configuration directives including defaults: Emails will attach all graphs included with the @signedGraphTag directive. If the email format is set to html, they will be embedded. To disable attaching images, set email_attach_graphs to false. alerting/email lnms config:set email_html true lnms config:set email_attach_graphs false Example: Config Example Email me@example.com","title":"Mail"},{"location":"Alerting/Transports/#matrix","text":"For using the Matrix transports, you have to create a room on the Matrix-server. The provided Auth_token belongs to an user, which is member of this room. The Message, sent to the matrix-room can be built from the variables defined in Template-Syntax but without the 'alert->' prefix. See API-Transport. The variable $msg is contains the result of the Alert template.The Matrix-Server URL is cutted before the beginning of the _matrix/client/r0/... API-part. Example: Config Example Matrix-Server URL https://matrix.example.com/ Room !ajPbbPalmVbNuQoBDK:example.com Auth_token: MDAyYmxvY2F0aW9uI...z1DCn6lz_uOhtW3XRICg Message: Alert: {{ $msg }} https://librenms.example.com","title":"Matrix"},{"location":"Alerting/Transports/#messagebird","text":"LibreNMS can send text messages through Messagebird Rest API transport. Config Example Api Key Api rest key given in the messagebird dashboard Originator E.164 formatted originator Recipient E.164 formatted recipient for multi recipents comma separated Character limit Range 1..480 (max 3 split messages)","title":"Messagebird"},{"location":"Alerting/Transports/#messagebird-voice","text":"LibreNMS can send messages through Messagebird voice Rest API transport (text to speech). Config Example Api Key Api rest key given in the messagebird dashboard Originator E.164 formatted originator Recipient E.164 formatted recipient for multi recipents comma separated Language Select box for options Spoken voice Female or Male Repeat X times the message is repeated","title":"Messagebird Voice"},{"location":"Alerting/Transports/#microsoft-teams","text":"LibreNMS can send alerts to Microsoft Teams Incoming Webhooks which are then posted to a specific channel. Microsoft recommends using markdown formatting for connector cards. Administrators can opt to compose the MessageCard themselves using JSON to get the full functionality. Example: Config Example WebHook URL https://outlook.office365.com/webhook/123456789 Use JSON? x","title":"Microsoft Teams"},{"location":"Alerting/Transports/#nagios-compatible","text":"The nagios transport will feed a FIFO at the defined location with the same format that nagios would. This allows you to use other alerting systems with LibreNMS, for example Flapjack . Example: Config Example Nagios FIFO /path/to/my.fifo","title":"Nagios Compatible"},{"location":"Alerting/Transports/#opsgenie","text":"Using OpsGenie LibreNMS integration, LibreNMS forwards alerts to OpsGenie with detailed information. OpsGenie acts as a dispatcher for LibreNMS alerts, determines the right people to notify based on on-call schedules and notifies via email, text messages (SMS), phone calls and iOS & Android push notifications. Then escalates alerts until the alert is acknowledged or closed. Create a LibreNMS Integration from the integrations page once you signup. Then copy the API key from OpsGenie to LibreNMS. If you want to automatically ack and close alerts, leverage Marid integration. More detail with screenshots is available in OpsGenie LibreNMS Integration page . Example: Config Example WebHook URL https://url/path/to/webhook","title":"OpsGenie"},{"location":"Alerting/Transports/#osticket","text":"LibreNMS can send alerts to osTicket API which are then converted to osTicket tickets. Example: Config Example API URL http://osticket.example.com/api/http.php/tickets.json API Token 123456789","title":"osTicket"},{"location":"Alerting/Transports/#pagerduty","text":"LibreNMS can make use of PagerDuty, this is done by utilizing an API key and Integraton Key. API Keys can be found under 'API Access' in the PagerDuty portal. Integration Keys can be found under 'Integration' for the particular Service you have created in the PagerDuty portal. Example: Config Example API Key randomsample Integration Key somerandomstring","title":"PagerDuty"},{"location":"Alerting/Transports/#philips-hue","text":"Want to spice up your noc life? LibreNMS will flash all lights connected to your philips hue bridge whenever an alert is triggered. To setup, go to the you http:// your-bridge-ip /debug/clip.html Update the \"URL:\" field to /api Paste this in the \"Message Body\" {\"devicetype\":\"librenms\"} Press the round button on your philips Hue Bridge Click on POST In the Command Response You should see output with your username. Copy this without the quotes More Info: Philips Hue Documentation Example: Config Example Host http://your-bridge-ip Hue User username Duration 1 Second","title":"Philips Hue"},{"location":"Alerting/Transports/#playsms","text":"PlaySMS is an open source SMS-Gateway that can be used via their HTTP API using a Username and WebService Token. Please consult PlaySMS's documentation regarding number formatting. PlaySMS Docs Here an example using 3 numbers, any amount of numbers is supported: Example: Config Example PlaySMS https://localhost/index.php User user1 Token MYFANCYACCESSTOKEN From My Name Mobiles +1234567892,+1234567890,+1234567891","title":"PlaySMS"},{"location":"Alerting/Transports/#pushbullet","text":"Get your Access Token from your Pushbullet's settings page and set it in your transport: Example: Config Example Access Token MYFANCYACCESSTOKEN","title":"Pushbullet"},{"location":"Alerting/Transports/#pushover","text":"If you want to change the default notification sound for all notifications then you can add the following in Pushover Options: sound=falling You also have the possibility to change sound per severity: sound_critical=falling sound_warning=siren sound_ok=magic Enabling Pushover support is fairly easy, there are only two required parameters. Firstly you need to create a new Application (called LibreNMS, for example) in your account on the Pushover website ( https://pushover.net/apps ). Now copy your API Key and obtain your User Key from the newly created Application and setup the transport. Pushover Docs Example: Config Example Api Key APPLICATIONAPIKEYGOESHERE User Key USERKEYGOESHERE Pushover Options sound_critical=falling sound_warning=siren sound_ok=magic","title":"Pushover"},{"location":"Alerting/Transports/#rocketchat","text":"The Rocket.chat transport will POST the alert message to your Rocket.chat Incoming WebHook using the attachments option. Simple html tags are stripped from the message. All options are optional, the only required value is for url, without this then no call to Rocket.chat will be made. Rocket.chat Docs Example: Config Example Webhook URL https://rocket.url/api/v1/chat.postMessage Rocket.chat Options channel=#Alerting username=myname icon_url=http://someurl/image.gif icon_emoji=:smirk:","title":"Rocket.chat"},{"location":"Alerting/Transports/#sensu","text":"The Sensu transport will POST an Event to the Agent API upon an alert being generated. It will be categorised (ok, warning or critical), and if you configure the alert to send recovery notifications, Sensu will also clear the alert automatically. No configuration is required - as long as you are running the Sensu Agent on your poller with the HTTP socket enabled on tcp/3031, LibreNMS will start generating Sensu events as soon as you create the transport. Acknowledging alerts within LibreNMS is not directly supported, but an annotation ( acknowledged ) is set, so a mutator or silence, or even the handler could be written to look for it directly in the handler. There is also an annotation ( generated-by ) set, to allow you to treat LibreNMS events differently from agent events. The 'shortname' option is a simple way to reduce the length of device names in configs. It replaces the last 3 domain components with single letters (e.g. websrv08.dc4.eu.corp.example.net gets shortened to websrv08.dc4.eu.cen).","title":"Sensu"},{"location":"Alerting/Transports/#limitations","text":"Only a single namespace is supported Sensu will reject rules with special characters - the Transport will attempt to fix up rule names, but it's best to stick to letters, numbers and spaces The transport only deals in absolutes - it ignores the got worse/got better states The agent will buffer alerts, but LibreNMS will not - if your agent is offline, alerts will be dropped There is no backchannel between Sensu and LibreNMS - if you make changes in Sensu to LibreNMS alerts, they'll be lost on the next event (silences will work) Example: Config Example Sensu Endpoint http://localhost:3031 Sensu Namespace eu-west Check Prefix lnms Source Key hostname","title":"Limitations"},{"location":"Alerting/Transports/#slack","text":"The Slack transport will POST the alert message to your Slack Incoming WebHook using the attachments option, you are able to specify multiple webhooks along with the relevant options to go with it. Simple html tags are stripped from the message. All options are optional, the only required value is for url, without this then no call to Slack will be made. We currently support the following attachment options: author_name Slack docs Example: Config Example Webhook URL https://slack.com/url/somehook Slack Options author_name=Me","title":"Slack"},{"location":"Alerting/Transports/#smseagle","text":"SMSEagle is a hardware SMS Gateway that can be used via their HTTP API using a Username and password. Destination numbers are one per line, with no spaces. They can be in either local or international dialling format. SMSEagle Docs Example: Config Example SMSEagle Host ip.add.re.ss User smseagle_user Password smseagle_user_password Mobiles +3534567890 0834567891","title":"SMSEagle"},{"location":"Alerting/Transports/#smsmode","text":"SMSmode is a SMS provider that can be configured by using the generic API Transport. You need a token you can find on your personnal space. SMSmode docs Example: Config Example Transport type Api API Method POST API URL http://api.smsmode.com/http/1.6/sendSMS.do Options accessToken= PUT_HERE_YOUR_TOKEN numero= PUT_HERE_DESTS_NUMBER_COMMA_SEPARATED message={{ $msg }}","title":"SMSmode"},{"location":"Alerting/Transports/#splunk","text":"LibreNMS can send alerts to a Splunk instance and provide all device and alert details. Example output: Feb 21 15:21:52 nms hostname=\"localhost\", sysName=\"localhost\", sysDescr=\"\", sysContact=\"\", os=\"fortigate\", type=\"firewall\", ip=\"localhost\", hardware=\"FGT_50E\", version=\"v5.6.9\", serial=\"\", features=\"\", location=\"\", uptime=\"387\", uptime_short=\" 6m 27s\", uptime_long=\" 6 minutes 27 seconds\", description=\"\", notes=\"\", alert_notes=\"\", device_id=\"0\", rule_id=\"0\", id=\"0\", proc=\"\", status=\"1\", status_reason=\"\", ping_timestamp=\"\", ping_loss=\"0\", ping_min=\"25.6\", ping_max=\"26.8\", ping_avg=\"26.3\", title=\"localhost recovered from Device up/down \", elapsed=\"14m 54s\", uid=\"0\", alert_id=\"0\", severity=\"critical\", name=\"Device up/down\", timestamp=\"2020-02-21 15:21:33\", state=\"0\", device_device_id=\"0\", device_inserted=\"\", device_hostname=\"localhost\", device_sysName=\"localhost\", device_ip=\"localhost\", device_overwrite_ip=\"\", device_timeout=\"\", device_retries=\"\", device_snmp_disable=\"0\", device_bgpLocalAs=\"0\", device_sysObjectID=\"\", device_sysDescr=\"\", device_sysContact=\"\", device_version=\"v5.6.9\", device_hardware=\"FGT_50E\", device_features=\"build1673\", device_location_id=\"\", device_os=\"fortigate\", device_status=\"1\", device_status_reason=\"\", device_ignore=\"0\", device_disabled=\"0\", device_uptime=\"387\", device_agent_uptime=\"0\", device_last_polled=\"2020-02-21 15:21:33\", device_last_poll_attempted=\"\", device_last_polled_timetaken=\"7.9\", device_last_discovered_timetaken=\"11.77\", device_last_discovered=\"2020-02-21 13:16:42\", device_last_ping=\"2020-02-21 15:21:33\", device_last_ping_timetaken=\"26.3\", device_purpose=\"\", device_type=\"firewall\", device_serial=\"FGT50EXXX\", device_icon=\"images/os/fortinet.svg\", device_poller_group=\"0\", device_override_sysLocation=\"0\", device_notes=\"\", device_port_association_mode=\"1\", device_max_depth=\"0\", device_disable_notify=\"0\", device_location=\"\", device_vrf_lites=\"Array\", device_lat=\"\", device_lng=\"\", - sysObjectID => \"\"; ` Each alert will be sent as a separate message. Example: Config Example Host 127.0.0.1 UDP Port 514","title":"Splunk"},{"location":"Alerting/Transports/#syslog","text":"You can have LibreNMS emit alerts as syslogs complying with RFC 3164. More information on RFC 3164 can be found here: https://tools.ietf.org/html/rfc3164 Example output: <26> Mar 22 00:59:03 librenms.host.net librenms[233]: [Critical] network.device.net: Port Down - port_id => 98939; ifDescr => xe-1/1/0; Each fault will be sent as a separate syslog. Example: Config Example Host 127.0.0.1 Port 514 Facility 3","title":"Syslog"},{"location":"Alerting/Transports/#telegram","text":"Thank you to snis for these instructions. First you must create a telegram account and add BotFather to you list. To do this click on the following url: https://telegram.me/botfather Generate a new bot with the command \"/newbot\" BotFather is then asking for a username and a normal name. After that your bot is created and you get a HTTP token. (for more options for your bot type \"/help\") Add your bot to telegram with the following url: http://telegram.me/ to use app or https://web.telegram.org/ to use in web, and send some text to the bot. The BotFather should have responded with a token, copy your token code and go to the following page in chrome: https://api.telegram.org/bot/getUpdates (this could take a while so continue to refresh until you see something similar to below) You see a json code with the message you sent to the bot. Copy the Chat id. In this example that is \u201c-9787468\u201d within this example: \"message\":{\"message_id\":7,\"from\":\"id\":656556,\"first_name\":\"Joo\",\"last_name\":\"Doo\",\"username\":\"JohnDoo\"},\"chat\":{\"id\":-9787468,\"title\":\"Telegram Group\"},\"date\":1435216924,\"text\":\"Hi\"}}]} . Now create a new \"Telegram transport\" in LibreNMS (Global Settings -> Alerting Settings -> Telegram transport). Click on 'Add Telegram config' and put your chat id and token into the relevant box. If want to use a group to receive alerts, you need to pick the Chat ID of the group chat, and not of the Bot itself. Telegram Docs Example: Config Example Chat ID 34243432 Token 3ed32wwf235234 Format HTML or MARKDOWN","title":"Telegram"},{"location":"Alerting/Transports/#twilio-sms","text":"Twilio will send your alert via SMS. From your Twilio account you will need your account SID, account token and your Twilio SMS phone number that you would like to send the alerts from. Twilio's APIs are located at: https://www.twilio.com/docs/api?filter-product=sms Example: Config Example SID ACxxxxxxxxxxxxxxxxxxxxxxxxxxxx Token 7xxxx573acxxxbc2xxx308d6xxx652d32 Twilio SMS Number 8888778660","title":"Twilio SMS"},{"location":"Alerting/Transports/#ukfast-pss","text":"UKFast PSS tickets can be raised from alerts using the UKFastPSS transport. This required an API key with PSS write permissions Example: Config Example API Key ABCDefgfg12 Author 5423 Priority Critical Secure true","title":"UKFast PSS"},{"location":"Alerting/Transports/#victorops","text":"VictorOps provide a webHook url to make integration extremely simple. To get the URL required login to your VictorOps account and go to: Settings -> Integrations -> REST Endpoint -> Enable Integration. The URL provided will have $routing_key at the end, you need to change this to something that is unique to the system sending the alerts such as librenms. I.e: https://alert.victorops.com/integrations/generic/20132414/alert/2f974ce1-08fc-4dg8-a4f4-9aee6cf35c98/librenms Example: Config Example Post URL https://alert.victorops.com/integrations/generic/20132414/alert/2f974ce1-08fc-4dg8-a4f4-9aee6cf35c98/librenms","title":"VictorOps"},{"location":"Alerting/Transports/#kayako-classic","text":"LibreNMS can send alerts to Kayako Classic API which are then converted to tickets. To use this module, you need REST API feature enabled in Kayako Classic and configured email account at LibreNMS. To enable this, do this: AdminCP -> REST API -> Settings -> Enable API (Yes) Also you need to know the department id to provide tickets to appropriate department and a user email to provide, which is used as ticket author. To get department id: navigate to appropriate department name at the departments list page in Admin CP and watch the number at the end of url. Example: http://servicedesk.example.com/admin/Base/Department/Edit/17 . Department ID is 17 As a requirement, you have to know API Url, API Key and API Secret to connect to servicedesk Kayako REST API Docs Example: Config Example Kayako URL http://servicedesk.example.com/api/ Kayako API Key 8cc02f38-7465-4a0c-8730-bb3af122167b Kayako API Secret Y2NhZDIxNDMtNjVkMi0wYzE0LWExYTUtZGUwMjJiZDI0ZWEzMmRhOGNiYWMtNTU2YS0yODk0LTA1MTEtN2VhN2YzYzgzZjk5 Kayako Department 1","title":"Kayako Classic"},{"location":"Alerting/Transports/#signal-cli","text":"Use the Signal Mesenger for Alerts. Run the Signal CLI with the D-Bus option. GitHub Project Example: Config Example Path /opt/signal-cli/bin/signal-cli Recipient type Group Recipient dfgjsdkgljior4345==","title":"Signal CLI"},{"location":"Alerting/Transports/#smsfeedback","text":"SMSFeedback is a SAAS service, which can be used to deliver Alerts via API, using API url, Username & Password. They can be in international dialling format only. SMSFeedback Api Docs Example: Config Example User smsfeedback_user Password smsfeedback_password Mobiles 71234567890 Sender name CIA","title":"SMSFeedback"},{"location":"Alerting/Transports/#zenduty","text":"Leveraging LibreNMS<>Zenduty Integration, users can send new LibreNMS alerts to the right team and notify them based on on-call schedules via email, SMS, Phone Calls, Slack, Microsoft Teams and mobile push notifications. Zenduty provides engineers with detailed context around the LibreNMS alert along with playbooks and a complete incident command framework to triage, remediate and resolve incidents with speed. Create a LibreNMS Integration from inside Zenduty , then copy the Webhook URL from Zenduty to LibreNMS. For a detailed guide with screenshots, refer to the LibreNMS documentation at Zenduty . Example: Config Example WebHook URL https://www.zenduty.com/api/integration/librenms/integration-key/","title":"Zenduty"},{"location":"Developing/Application-Notes/","text":"Notes On Application Development LibreNMS JSON SNMP Extends The polling function json_app_get makes it easy to poll complex data using SNMP extends and JSON. The following exceptions are provided by it. It takes three parameters, in order in the list below. Integer :: Device ID to fetch it for. String :: The extend name. For example, if 'zfs' is passed it will be converted to 'nsExtendOutputFull.3.122.102.115'. Integer :: Minimum expected version of the JSON return. The required keys for the returned JSON are as below. version :: The version of the snmp extend script. Should be numeric and at least 1. error :: Error code from the snmp extend script. Should be > 0 (0 will be ignored and negatives are reserved) errorString :: Text to describe the error. data :: An key with an array with the data to be used. The supported exceptions are as below. JsonAppPollingFailedException :: Empty return from SNMP. JsonAppParsingFailedException :: Could not parse the JSON JsonAppBlankJsonException :: Blank JSON. JsonAppMissingKeysException :: Missing required keys. JsonAppWrongVersionException :: Older version than supported. JsonAppExtendErroredException :: Polling and parsing was good, but the returned data has an error set. This may be checked via $e->getParsedJson() and then checking the keys error and errorString. The error value can be accessed via $e->getCode(). The output can be accessed via $->getOutput() Only returned JsonAppParsingFailedException. The parsed JSON can be access via $e->getParsedJson(). An example below from includes/polling/applications/zfs.inc.php ... try { $zfs = json_app_get ( $device , $name , 1 )[ 'data' ]; } catch ( JsonAppMissingKeysException $e ) { //old version with out the data key $zfs = $e -> getParsedJson (); } catch ( JsonAppException $e ) { echo PHP_EOL . $name . ':' . $e -> getCode () . ':' . $e -> getMessage () . PHP_EOL ; update_application ( $app , $e -> getCode () . ':' . $e -> getMessage (), []); return ; } Compression Also worth noting that json_app_get supports compressed data via base64 encoded gzip. If base64 encoding is detected on the the SNMP return, it will be gunzipped and then parsed. https://github.com/librenms/librenms-agent/blob/master/utils/librenms_return_optimizer may be used to optimize JSON returns. Application Data Storage The $app model is supplied for each application poller and graph. You may access and update the $app->data field to store arrays of data the Application model. When you call update_application() the $app model will be saved along with any changes to the data field. // set the varaible data to $foo $app->data = [ 'item_A' => 123, 'item_B' => 4.5, 'type' => 'foo', 'other_items' => [ 'a', 'b', 'c' ], ]; // save the change $app->save(); // var_dump the contents of the variable var_dump($app->data);","title":"Applications"},{"location":"Developing/Application-Notes/#notes-on-application-development","text":"","title":"Notes On Application Development"},{"location":"Developing/Application-Notes/#librenms-json-snmp-extends","text":"The polling function json_app_get makes it easy to poll complex data using SNMP extends and JSON. The following exceptions are provided by it. It takes three parameters, in order in the list below. Integer :: Device ID to fetch it for. String :: The extend name. For example, if 'zfs' is passed it will be converted to 'nsExtendOutputFull.3.122.102.115'. Integer :: Minimum expected version of the JSON return. The required keys for the returned JSON are as below. version :: The version of the snmp extend script. Should be numeric and at least 1. error :: Error code from the snmp extend script. Should be > 0 (0 will be ignored and negatives are reserved) errorString :: Text to describe the error. data :: An key with an array with the data to be used. The supported exceptions are as below. JsonAppPollingFailedException :: Empty return from SNMP. JsonAppParsingFailedException :: Could not parse the JSON JsonAppBlankJsonException :: Blank JSON. JsonAppMissingKeysException :: Missing required keys. JsonAppWrongVersionException :: Older version than supported. JsonAppExtendErroredException :: Polling and parsing was good, but the returned data has an error set. This may be checked via $e->getParsedJson() and then checking the keys error and errorString. The error value can be accessed via $e->getCode(). The output can be accessed via $->getOutput() Only returned JsonAppParsingFailedException. The parsed JSON can be access via $e->getParsedJson(). An example below from includes/polling/applications/zfs.inc.php ... try { $zfs = json_app_get ( $device , $name , 1 )[ 'data' ]; } catch ( JsonAppMissingKeysException $e ) { //old version with out the data key $zfs = $e -> getParsedJson (); } catch ( JsonAppException $e ) { echo PHP_EOL . $name . ':' . $e -> getCode () . ':' . $e -> getMessage () . PHP_EOL ; update_application ( $app , $e -> getCode () . ':' . $e -> getMessage (), []); return ; }","title":"LibreNMS JSON SNMP Extends"},{"location":"Developing/Application-Notes/#compression","text":"Also worth noting that json_app_get supports compressed data via base64 encoded gzip. If base64 encoding is detected on the the SNMP return, it will be gunzipped and then parsed. https://github.com/librenms/librenms-agent/blob/master/utils/librenms_return_optimizer may be used to optimize JSON returns.","title":"Compression"},{"location":"Developing/Application-Notes/#application-data-storage","text":"The $app model is supplied for each application poller and graph. You may access and update the $app->data field to store arrays of data the Application model. When you call update_application() the $app model will be saved along with any changes to the data field. // set the varaible data to $foo $app->data = [ 'item_A' => 123, 'item_B' => 4.5, 'type' => 'foo', 'other_items' => [ 'a', 'b', 'c' ], ]; // save the change $app->save(); // var_dump the contents of the variable var_dump($app->data);","title":"Application Data Storage"},{"location":"Developing/Code-Structure/","text":"Code structure This document will try and provide a good overview of how the code is structured within LibreNMS. We will go through the main directories and provide information on how and when they are used. LibreNMS now uses Laravel for much of it's frontend (webui) and database code. Much of the Laravel documentation applies: https://laravel.com/docs/structure Directories from the (filtered) structure tree below are some of the directories that will be most interesting during development: . \u251c\u2500 app \u251c\u2500 database \u2502 \u2514\u2500 migrations \u251c\u2500 doc \u251c\u2500 html \u2502 \u251c\u2500 css \u2502 \u2502 \u2514\u2500 custom \u2502 \u2514\u2500 js \u251c\u2500 includes \u2502 \u251c\u2500 definitions \u2502 \u251c\u2500 discovery \u2502 \u251c\u2500 html \u2502 \u2502 \u251c\u2500 forms \u2502 \u2502 \u251c\u2500 graphs \u2502 \u2502 \u251c\u2500 pages \u2502 \u2502 \u2514\u2500 reports \u2502 \u2514\u2500 polling \u251c\u2500 LibreNMS \u251c\u2500 logs \u251c\u2500 mibs \u2514\u2500 rrd doc/ This is the location of all the documentation for LibreNMS, this is in GitHub markdown format and can be viewed online app/ Most Laravel and Eloquent classes should be under this directory. LibreNMS/ Classes that don't belong to the Laravel application belong in this directory, with a directory structure that matches the namespace. One class per file. See PSR-0 for details. html/ All legacy web accessible files are located here. New pages should follow the Laravel conventions. html/api_v0.php This is the API routing file which directs users to the correct API function based on the API endpoint call. html/index.php This is the main file which all links within LibreNMS are parsed through. It loads the majority of the relevant includes needed for the control panel to function. CSS and JS files are also loaded here. html/css/ All used CSS files are located here. html/css/custom/ This is a directory you can put custom css files into that won't interfere with auto updates html/js/ All used JS files are located here. includes/ This directory is quite big and contains all the files to make the cli and polling / discovery to work. This code is not currently accessible from Laravel code (intentionally). includes/discovery/, includes/polling/ All the discovery and polling code. The format is usually quite similar between discovery and polling. Both are made up of modules and the files within the relevant directories will match that module. So for instance if you want to update the os detection for a device, you would look in includes/discovery/os/ for a file named after the operating system such as linux: includes/discovery/linux.inc.php . Within here you would update or add support for newer OS'. This is the same for polling as well. includes/html/ This is where the majority of the website core files are located. These tend to be files that contain functions or often used code segments that can be included where needed rather than duplicating code. includes/html/forms/ This directory contains all of the files that are dynamically included from an ajax call to ajax/form. includes/html/api_functions.inc.php All of the functions and calls for the API are located here. includes/html/functions.inc.php This contains the majority of functions used throughout the standard web ui. includes/html/graphs/ This directory contains global and OS specific graph definitions. includes/html/reports/ In here is a list of of files that generate PDF reports available to the user. These are dynamically called in from html/pdf.php based on the report the user requests. includes/html/table/ This directory contains all of the ajax calls when generating the table of data. Most have been converted over so if you are planning to add a new table of data then you will do so here for all of the back end data calls. includes/html/pages/ This directory contains the URL structure when browsing the Web UI. So for example /devices/ is actually a call to includes/html/pages/devices.inc.php , /device/tab=ports/ is includes/html/pages/device/ports.inc.php . logs/ Contains the main librenms.log file by default, but can also contain your web server's logs, poller logs, and other items. mibs/ Here is where all of the mibs are located. Generally standard mibs should be in the root directory and specific vendor mibs should be in their own subdirectory. rrd/ Simple enough, this is where all of the rrd files are created. They are stored in directory based on the device hostname. database/migrations Contains all the database migrations. See Laravel docs for additional info: https://laravel.com/docs/migrations In general to create a new table you should run: php artisan make:model ModelName -m -c -r","title":"Code Structure"},{"location":"Developing/Code-Structure/#code-structure","text":"This document will try and provide a good overview of how the code is structured within LibreNMS. We will go through the main directories and provide information on how and when they are used. LibreNMS now uses Laravel for much of it's frontend (webui) and database code. Much of the Laravel documentation applies: https://laravel.com/docs/structure Directories from the (filtered) structure tree below are some of the directories that will be most interesting during development: . \u251c\u2500 app \u251c\u2500 database \u2502 \u2514\u2500 migrations \u251c\u2500 doc \u251c\u2500 html \u2502 \u251c\u2500 css \u2502 \u2502 \u2514\u2500 custom \u2502 \u2514\u2500 js \u251c\u2500 includes \u2502 \u251c\u2500 definitions \u2502 \u251c\u2500 discovery \u2502 \u251c\u2500 html \u2502 \u2502 \u251c\u2500 forms \u2502 \u2502 \u251c\u2500 graphs \u2502 \u2502 \u251c\u2500 pages \u2502 \u2502 \u2514\u2500 reports \u2502 \u2514\u2500 polling \u251c\u2500 LibreNMS \u251c\u2500 logs \u251c\u2500 mibs \u2514\u2500 rrd","title":"Code structure"},{"location":"Developing/Code-Structure/#doc","text":"This is the location of all the documentation for LibreNMS, this is in GitHub markdown format and can be viewed online","title":"doc/"},{"location":"Developing/Code-Structure/#app","text":"Most Laravel and Eloquent classes should be under this directory.","title":"app/"},{"location":"Developing/Code-Structure/#librenms","text":"Classes that don't belong to the Laravel application belong in this directory, with a directory structure that matches the namespace. One class per file. See PSR-0 for details.","title":"LibreNMS/"},{"location":"Developing/Code-Structure/#html","text":"All legacy web accessible files are located here. New pages should follow the Laravel conventions.","title":"html/"},{"location":"Developing/Code-Structure/#htmlapi_v0php","text":"This is the API routing file which directs users to the correct API function based on the API endpoint call.","title":"html/api_v0.php"},{"location":"Developing/Code-Structure/#htmlindexphp","text":"This is the main file which all links within LibreNMS are parsed through. It loads the majority of the relevant includes needed for the control panel to function. CSS and JS files are also loaded here.","title":"html/index.php"},{"location":"Developing/Code-Structure/#htmlcss","text":"All used CSS files are located here.","title":"html/css/"},{"location":"Developing/Code-Structure/#htmlcsscustom","text":"This is a directory you can put custom css files into that won't interfere with auto updates","title":"html/css/custom/"},{"location":"Developing/Code-Structure/#htmljs","text":"All used JS files are located here.","title":"html/js/"},{"location":"Developing/Code-Structure/#includes","text":"This directory is quite big and contains all the files to make the cli and polling / discovery to work. This code is not currently accessible from Laravel code (intentionally).","title":"includes/"},{"location":"Developing/Code-Structure/#includesdiscovery-includespolling","text":"All the discovery and polling code. The format is usually quite similar between discovery and polling. Both are made up of modules and the files within the relevant directories will match that module. So for instance if you want to update the os detection for a device, you would look in includes/discovery/os/ for a file named after the operating system such as linux: includes/discovery/linux.inc.php . Within here you would update or add support for newer OS'. This is the same for polling as well.","title":"includes/discovery/, includes/polling/"},{"location":"Developing/Code-Structure/#includeshtml","text":"This is where the majority of the website core files are located. These tend to be files that contain functions or often used code segments that can be included where needed rather than duplicating code.","title":"includes/html/"},{"location":"Developing/Code-Structure/#includeshtmlforms","text":"This directory contains all of the files that are dynamically included from an ajax call to ajax/form.","title":"includes/html/forms/"},{"location":"Developing/Code-Structure/#includeshtmlapi_functionsincphp","text":"All of the functions and calls for the API are located here.","title":"includes/html/api_functions.inc.php"},{"location":"Developing/Code-Structure/#includeshtmlfunctionsincphp","text":"This contains the majority of functions used throughout the standard web ui.","title":"includes/html/functions.inc.php"},{"location":"Developing/Code-Structure/#includeshtmlgraphs","text":"This directory contains global and OS specific graph definitions.","title":"includes/html/graphs/"},{"location":"Developing/Code-Structure/#includeshtmlreports","text":"In here is a list of of files that generate PDF reports available to the user. These are dynamically called in from html/pdf.php based on the report the user requests.","title":"includes/html/reports/"},{"location":"Developing/Code-Structure/#includeshtmltable","text":"This directory contains all of the ajax calls when generating the table of data. Most have been converted over so if you are planning to add a new table of data then you will do so here for all of the back end data calls.","title":"includes/html/table/"},{"location":"Developing/Code-Structure/#includeshtmlpages","text":"This directory contains the URL structure when browsing the Web UI. So for example /devices/ is actually a call to includes/html/pages/devices.inc.php , /device/tab=ports/ is includes/html/pages/device/ports.inc.php .","title":"includes/html/pages/"},{"location":"Developing/Code-Structure/#logs","text":"Contains the main librenms.log file by default, but can also contain your web server's logs, poller logs, and other items.","title":"logs/"},{"location":"Developing/Code-Structure/#mibs","text":"Here is where all of the mibs are located. Generally standard mibs should be in the root directory and specific vendor mibs should be in their own subdirectory.","title":"mibs/"},{"location":"Developing/Code-Structure/#rrd","text":"Simple enough, this is where all of the rrd files are created. They are stored in directory based on the device hostname.","title":"rrd/"},{"location":"Developing/Code-Structure/#databasemigrations","text":"Contains all the database migrations. See Laravel docs for additional info: https://laravel.com/docs/migrations In general to create a new table you should run: php artisan make:model ModelName -m -c -r","title":"database/migrations"},{"location":"Developing/Creating-Documentation/","text":"Creating Documentation One of the goals of the LibreNMS project is to enable users to get all of the help they need from our documentation. The documentation uses the markdown markup language and is generated with mkdocs . To edit or create markdown you only need a text editor, but it is recommended to build your docs before submitting, in order to check them visually. The section on this page has instructions for this step. Writing docs When you are adding a new feature or extension, we need to have full documentation to go along with it. It's quite simple to do this: Find the relevant directory to store your new document in, General, Support and Extensions are the most likely choices. Think of a descriptive name that's not too long, it should match what they may be looking for or describes the feature. Add the new document into the nav section of mkdocs.yml if it needs to appear in the table of contents Ensure the first line contains: source: path/to/file.md - don't include the initial doc/ . In the body of the document, be descriptive but keep things simple. Some tips: If the document could cover different distros like CentOS and Ubuntu please try and include the information for them all. If that's not possible then at least put a placeholder in asking for contributions. Ensure you use the correct formatting for commands and code blocks by wrapping one liners in backticks or blocks in ```. Put content into sub-headings where possible to organise the content. If you rename a file, please add a redirect for the old file in mkdocs.yml like so: - redirects : redirect_maps : 'old/page.md' : 'new/page.md' Please ensure you add the document to the relevant section within pages of mkdocs.yml so that it's in the correct menu and is built. Forgetting this step will result in your document never seeing the light of day :) Formatting docs Our docs are based on Markdown using mkdocs which adheres to markdown specs and nothing more, because of that we also import a couple of extra libraries: pymdownx.tasklist pymdownx.tilde This means you can use: ~~strikethrough~~ to perform strikethrough - [X] List items Url's can be made [like this](https://www.librenms.org) like this Code can be placed in `` for single line or ``` for multiline. # Can be used for main headings which translates to a tag, increasing the # 's will increase the hX tags. ### Can be used for sub-headings which will appear in the TOC to the left. Settings should be prefixed with !!! setting \"\" Markdown CheatSheet Link Building docs This is achieved with mkdocs , a python package. Install the required packages. pip install mkdocs mkdocs-exclude mkdocs-material mkdocs-macros-plugin mkdocs-minify-plugin mkdocs-redirects If you encounter permissions issues, these might be reoslved by using the user option, with whatever user you are building as, e.g. -u librenms A configuration file for building LibreNMS docs is already included in the distribution: /opt/librenms/mkdocs.yml . The various configuration directives are documented here . Build from the librenms base directory: cd /opt/librenms . Building is simple: mkdocs build This will output all the documentation in html format to /opt/librenms/out (this folder will be ignored from any commits). Viewing docs mkdocs includes it's own light-weight webserver for this purpose. Viewing is as simple as running the following command: $ mkdocs serve INFO - Building documentation... <..> INFO - Documentation built in 12.54 seconds <..> INFO - Serving on http://127.0.0.1:8000 <..> INFO - Start watching changes Now you will find the complete set of LibreNMS documentation by opening your browser to localhost:8000 . Note it is not necessary to build before viewing as the serve command will do this for you. Also the server will update the documents it is serving whenever changes to the markdown are made, such as in another terminal. Viewing docs from another machine By default the server will only listen for connections from the local machine. If you are building on a different machine you can use the following directive to listen on all interfaces: mkdocs serve --dev-addr=0.0.0.0:8000 WARNING: this is not a secure webserver, do this at your own risk, with appropriate host security and do not leave the server running.","title":"Creating Documentation"},{"location":"Developing/Creating-Documentation/#creating-documentation","text":"One of the goals of the LibreNMS project is to enable users to get all of the help they need from our documentation. The documentation uses the markdown markup language and is generated with mkdocs . To edit or create markdown you only need a text editor, but it is recommended to build your docs before submitting, in order to check them visually. The section on this page has instructions for this step.","title":"Creating Documentation"},{"location":"Developing/Creating-Documentation/#writing-docs","text":"When you are adding a new feature or extension, we need to have full documentation to go along with it. It's quite simple to do this: Find the relevant directory to store your new document in, General, Support and Extensions are the most likely choices. Think of a descriptive name that's not too long, it should match what they may be looking for or describes the feature. Add the new document into the nav section of mkdocs.yml if it needs to appear in the table of contents Ensure the first line contains: source: path/to/file.md - don't include the initial doc/ . In the body of the document, be descriptive but keep things simple. Some tips: If the document could cover different distros like CentOS and Ubuntu please try and include the information for them all. If that's not possible then at least put a placeholder in asking for contributions. Ensure you use the correct formatting for commands and code blocks by wrapping one liners in backticks or blocks in ```. Put content into sub-headings where possible to organise the content. If you rename a file, please add a redirect for the old file in mkdocs.yml like so: - redirects : redirect_maps : 'old/page.md' : 'new/page.md' Please ensure you add the document to the relevant section within pages of mkdocs.yml so that it's in the correct menu and is built. Forgetting this step will result in your document never seeing the light of day :)","title":"Writing docs"},{"location":"Developing/Creating-Documentation/#formatting-docs","text":"Our docs are based on Markdown using mkdocs which adheres to markdown specs and nothing more, because of that we also import a couple of extra libraries: pymdownx.tasklist pymdownx.tilde This means you can use: ~~strikethrough~~ to perform strikethrough - [X] List items Url's can be made [like this](https://www.librenms.org) like this Code can be placed in `` for single line or ``` for multiline. # Can be used for main headings which translates to a tag, increasing the # 's will increase the hX tags. ### Can be used for sub-headings which will appear in the TOC to the left. Settings should be prefixed with !!! setting \"\" Markdown CheatSheet Link","title":"Formatting docs"},{"location":"Developing/Creating-Documentation/#building-docs","text":"This is achieved with mkdocs , a python package. Install the required packages. pip install mkdocs mkdocs-exclude mkdocs-material mkdocs-macros-plugin mkdocs-minify-plugin mkdocs-redirects If you encounter permissions issues, these might be reoslved by using the user option, with whatever user you are building as, e.g. -u librenms A configuration file for building LibreNMS docs is already included in the distribution: /opt/librenms/mkdocs.yml . The various configuration directives are documented here . Build from the librenms base directory: cd /opt/librenms . Building is simple: mkdocs build This will output all the documentation in html format to /opt/librenms/out (this folder will be ignored from any commits).","title":"Building docs"},{"location":"Developing/Creating-Documentation/#viewing-docs","text":"mkdocs includes it's own light-weight webserver for this purpose. Viewing is as simple as running the following command: $ mkdocs serve INFO - Building documentation... <..> INFO - Documentation built in 12.54 seconds <..> INFO - Serving on http://127.0.0.1:8000 <..> INFO - Start watching changes Now you will find the complete set of LibreNMS documentation by opening your browser to localhost:8000 . Note it is not necessary to build before viewing as the serve command will do this for you. Also the server will update the documents it is serving whenever changes to the markdown are made, such as in another terminal.","title":"Viewing docs"},{"location":"Developing/Creating-Documentation/#viewing-docs-from-another-machine","text":"By default the server will only listen for connections from the local machine. If you are building on a different machine you can use the following directive to listen on all interfaces: mkdocs serve --dev-addr=0.0.0.0:8000 WARNING: this is not a secure webserver, do this at your own risk, with appropriate host security and do not leave the server running.","title":"Viewing docs from another machine"},{"location":"Developing/Creating-Release/","text":"Creating a release GitHub You can create a new release on GitHub . Enter the tag version that month, i.e for September 2016 you would enter 201609 . Enter a title, we usually use August 2016 Release Enter a placeholder for the body, we will edit this later. Create changelog For this, we assume you are using the master branch to create the release against. We now generate the changelog using the GitHub API itself so it shouldn't matter what state your local branch is in so long as it has the code to generate the changelog itself. Using the GitHub API means we can use the labels associated with merged pull requests to categorise the changelog. We also then record who made the pull request to thank them in the changelog itself. You will be asked for a GitHub personal access token. You can generate this here . No permissions should be needed so just give it a name and click Generate Token . You can then export the token as an environment variable GH_TOKEN or place it in your .env file. The basic command to run is by using artisan . Here you pass new tag (1.41) and previous tag (1.40). For further help run php artisan release:tag --help . This will generate a changelog up to the latest master branch, if you want it to be done against something else then pass the latest pull request number with --pr $PR_NUMBER . php artisan release:tag 1 .41 1 .40 Now commit and push the change that has been made to doc/General/Changelog.md . Once the pull request has been merged in for the Changelog, you can create a new release on GitHub . Create two threads on the community site: A changelog thread example An info thread example Tweet it Facebook it Google Plus it LinkedIn it","title":"Creating Release"},{"location":"Developing/Creating-Release/#creating-a-release","text":"","title":"Creating a release"},{"location":"Developing/Creating-Release/#github","text":"You can create a new release on GitHub . Enter the tag version that month, i.e for September 2016 you would enter 201609 . Enter a title, we usually use August 2016 Release Enter a placeholder for the body, we will edit this later.","title":"GitHub"},{"location":"Developing/Creating-Release/#create-changelog","text":"For this, we assume you are using the master branch to create the release against. We now generate the changelog using the GitHub API itself so it shouldn't matter what state your local branch is in so long as it has the code to generate the changelog itself. Using the GitHub API means we can use the labels associated with merged pull requests to categorise the changelog. We also then record who made the pull request to thank them in the changelog itself. You will be asked for a GitHub personal access token. You can generate this here . No permissions should be needed so just give it a name and click Generate Token . You can then export the token as an environment variable GH_TOKEN or place it in your .env file. The basic command to run is by using artisan . Here you pass new tag (1.41) and previous tag (1.40). For further help run php artisan release:tag --help . This will generate a changelog up to the latest master branch, if you want it to be done against something else then pass the latest pull request number with --pr $PR_NUMBER . php artisan release:tag 1 .41 1 .40 Now commit and push the change that has been made to doc/General/Changelog.md . Once the pull request has been merged in for the Changelog, you can create a new release on GitHub . Create two threads on the community site: A changelog thread example An info thread example Tweet it Facebook it Google Plus it LinkedIn it","title":"Create changelog"},{"location":"Developing/Dynamic-Config/","text":"Adding new config settings Adding support for users to update a new config option via the WebUI is now a lot easier for general options. This document shows you how to add a new config option and even section to the WebUI. Config settings are defined in misc/config_definitions.json You should give a little thought to the name of your config setting. For example: a good setting for snmp community, would be snmp.community . The dot notation is path and when the config is hydrated, it is converted to a nested array. If the user is overriding the option in config.php it would use the format $config['snmp']['community'] Translation The config definition system inherently supports translation. You must add the English names in the resoures/lang/en/settings.php file (and other languages if you can). To update the javascript translation files, run: ./lnms translation:generate Definition Format For snmp.community, this is the definition: \"snmp.community\" : { \"group\" : \"poller\" , \"section\" : \"snmp\" , \"order\" : 2 , \"type\" : \"array\" , \"default\" : [ \"public\" ] } Fields All fields are optional. To show in the web ui, group and section are required, order is recommended. type : Defines the type, there are a few predefined types and custom types can be defined and implemented in a vue.js component default : the default value for this setting options : the options for the select type. An object with {\"value1\": \"display string\", \"value2\": \"display string\"} validate : Defines more complex validation than the default simple type check. Uses Laravel validation syntax. group : The web ui tab this is under section : A panel grouping settings in the web ui order : The order to display this setting within the section Predefined Types string : A string integer : A number boolean : A simple toggle switch array : A list of values that can be added, removed, and re-ordered. select : A dropdown box with predefined options. Requires the option field. email : Will validate the input is the correct format for an email password : Will mask the value of the input (but does not keep it fully private) Custom Types You may set the type field to a custom type and define a Vue.js component to display it to the user. The Vue.js component should be named as \"SettingType\" where type is the custom type entered with the first letter capitalized. Vue.js components exist in the resources/js/components directory. Here is an empty component named SettingType (make sure to rename it). It pulls in BaseSetting mixin for basic setting code to reuse. You should review the BaseSetting component. Using Vue.js is beyond the scope of this document. Documentation can be found at vuejs.org .","title":"Dynamic Config"},{"location":"Developing/Dynamic-Config/#adding-new-config-settings","text":"Adding support for users to update a new config option via the WebUI is now a lot easier for general options. This document shows you how to add a new config option and even section to the WebUI. Config settings are defined in misc/config_definitions.json You should give a little thought to the name of your config setting. For example: a good setting for snmp community, would be snmp.community . The dot notation is path and when the config is hydrated, it is converted to a nested array. If the user is overriding the option in config.php it would use the format $config['snmp']['community']","title":"Adding new config settings"},{"location":"Developing/Dynamic-Config/#translation","text":"The config definition system inherently supports translation. You must add the English names in the resoures/lang/en/settings.php file (and other languages if you can). To update the javascript translation files, run: ./lnms translation:generate","title":"Translation"},{"location":"Developing/Dynamic-Config/#definition-format","text":"For snmp.community, this is the definition: \"snmp.community\" : { \"group\" : \"poller\" , \"section\" : \"snmp\" , \"order\" : 2 , \"type\" : \"array\" , \"default\" : [ \"public\" ] }","title":"Definition Format"},{"location":"Developing/Dynamic-Config/#fields","text":"All fields are optional. To show in the web ui, group and section are required, order is recommended. type : Defines the type, there are a few predefined types and custom types can be defined and implemented in a vue.js component default : the default value for this setting options : the options for the select type. An object with {\"value1\": \"display string\", \"value2\": \"display string\"} validate : Defines more complex validation than the default simple type check. Uses Laravel validation syntax. group : The web ui tab this is under section : A panel grouping settings in the web ui order : The order to display this setting within the section","title":"Fields"},{"location":"Developing/Dynamic-Config/#predefined-types","text":"string : A string integer : A number boolean : A simple toggle switch array : A list of values that can be added, removed, and re-ordered. select : A dropdown box with predefined options. Requires the option field. email : Will validate the input is the correct format for an email password : Will mask the value of the input (but does not keep it fully private)","title":"Predefined Types"},{"location":"Developing/Dynamic-Config/#custom-types","text":"You may set the type field to a custom type and define a Vue.js component to display it to the user. The Vue.js component should be named as \"SettingType\" where type is the custom type entered with the first letter capitalized. Vue.js components exist in the resources/js/components directory. Here is an empty component named SettingType (make sure to rename it). It pulls in BaseSetting mixin for basic setting code to reuse. You should review the BaseSetting component. Using Vue.js is beyond the scope of this document. Documentation can be found at vuejs.org .","title":"Custom Types"},{"location":"Developing/Getting-Started/","text":"Get ready to contribute to LibreNMS This document is intended to help you get your local environment set up to contribute code to the LibreNMS project. Setting up a development environment When starting to develop, it may be tempting to just make changes on your production server, but that will make things harder for you. Taking a little time to set up somewhere to work on code changes can really help. Possible options: A Linux computer, VM, or container Another directory on your LibreNMS server Windows Subsystem for Linux Set up your development git clone Follow the documentation on using git Install development dependencies ./scripts/composer_wrapper.php install Set variables in .env , including database settings. Which could be a local or remote MySQL server including your production DB. APP_ENV=local APP_DEBUG=true ... Start a development webserver ./lnms serve Access the Web UI at http://localhost:8000 Automated testing LibreNMS uses continuous integration to test code changes to help reduce bugs. This also helps guarantee the changes you contribute won't be broken in the future. You can find out more in our Validating Code Documentation The default database connection for automated testing is testing . To override the database parameters for unit tests, configure your .env file accordingly. The defaults (from config/database.php ) are: DB_TEST_DRIVER=\"mysql\" # PDO driver DB_TEST_HOST=\"localhost\" # hostname or IP address DB_TEST_PORT=\"\" # port DB_TEST_DATABASE=\"librenms_phpunit_78hunjuybybh\" # database DB_TEST_USERNAME=\"root\" # username DB_TEST_PASSWORD=\"\" # password DB_TEST_SOCKET=\"\" # unix socket path Polling debug output You can see detailed info by running your polling code in debug mode by adding a -d flag. ./discovery.php -d -h HOSTNAME lnms device:poll HOSTNAME -vv Inspecting variables Sometimes you want to find out what a variable contains (such as the data return from an snmpwalk). You can dump one or more variables and halt execution with the dd() function. dd ( $variable1 , $variable2 ); Inspecting web pages Installing the development dependencies and setting APP_DEBUG enables the Laravel Debugbar This will allow you to inspect page generation and errors right in your web browser. Better code completion in IDEs and editors You can generate some files to improve code completion. (These file are not updated automatically, so you may need to re-run these command periodically) ./lnms ide-helper:generate ./lnms ide-helper:models -N Emulating devices You can capture and emulate devices using Snmpsim . LibreNMS has a set of scripts to make it easier to work with snmprec files. LibreNMS Snmpsim helpers Laravel documentation You can find a lot of how LibreNMS works by following the Laravel Documentation","title":"Getting Started"},{"location":"Developing/Getting-Started/#get-ready-to-contribute-to-librenms","text":"This document is intended to help you get your local environment set up to contribute code to the LibreNMS project.","title":"Get ready to contribute to LibreNMS"},{"location":"Developing/Getting-Started/#setting-up-a-development-environment","text":"When starting to develop, it may be tempting to just make changes on your production server, but that will make things harder for you. Taking a little time to set up somewhere to work on code changes can really help. Possible options: A Linux computer, VM, or container Another directory on your LibreNMS server Windows Subsystem for Linux","title":"Setting up a development environment"},{"location":"Developing/Getting-Started/#set-up-your-development-git-clone","text":"Follow the documentation on using git Install development dependencies ./scripts/composer_wrapper.php install Set variables in .env , including database settings. Which could be a local or remote MySQL server including your production DB. APP_ENV=local APP_DEBUG=true ... Start a development webserver ./lnms serve Access the Web UI at http://localhost:8000","title":"Set up your development git clone"},{"location":"Developing/Getting-Started/#automated-testing","text":"LibreNMS uses continuous integration to test code changes to help reduce bugs. This also helps guarantee the changes you contribute won't be broken in the future. You can find out more in our Validating Code Documentation The default database connection for automated testing is testing . To override the database parameters for unit tests, configure your .env file accordingly. The defaults (from config/database.php ) are: DB_TEST_DRIVER=\"mysql\" # PDO driver DB_TEST_HOST=\"localhost\" # hostname or IP address DB_TEST_PORT=\"\" # port DB_TEST_DATABASE=\"librenms_phpunit_78hunjuybybh\" # database DB_TEST_USERNAME=\"root\" # username DB_TEST_PASSWORD=\"\" # password DB_TEST_SOCKET=\"\" # unix socket path","title":"Automated testing"},{"location":"Developing/Getting-Started/#polling-debug-output","text":"You can see detailed info by running your polling code in debug mode by adding a -d flag. ./discovery.php -d -h HOSTNAME lnms device:poll HOSTNAME -vv","title":"Polling debug output"},{"location":"Developing/Getting-Started/#inspecting-variables","text":"Sometimes you want to find out what a variable contains (such as the data return from an snmpwalk). You can dump one or more variables and halt execution with the dd() function. dd ( $variable1 , $variable2 );","title":"Inspecting variables"},{"location":"Developing/Getting-Started/#inspecting-web-pages","text":"Installing the development dependencies and setting APP_DEBUG enables the Laravel Debugbar This will allow you to inspect page generation and errors right in your web browser.","title":"Inspecting web pages"},{"location":"Developing/Getting-Started/#better-code-completion-in-ides-and-editors","text":"You can generate some files to improve code completion. (These file are not updated automatically, so you may need to re-run these command periodically) ./lnms ide-helper:generate ./lnms ide-helper:models -N","title":"Better code completion in IDEs and editors"},{"location":"Developing/Getting-Started/#emulating-devices","text":"You can capture and emulate devices using Snmpsim . LibreNMS has a set of scripts to make it easier to work with snmprec files. LibreNMS Snmpsim helpers","title":"Emulating devices"},{"location":"Developing/Getting-Started/#laravel-documentation","text":"You can find a lot of how LibreNMS works by following the Laravel Documentation","title":"Laravel documentation"},{"location":"Developing/Merging-Pull-Requests/","text":"Merging Pull Requests GitHub We will now build the monthly change log from our GitHub commits. When merging a commit, please ensure you: Click the Merge pull request button Give the merge a descriptive but short title For the commit message prepend it with one of the following tags for the pull request to appear in the changelog: devices: or newdevice: For new device support. feature: or feat: To indicate this is a new or updated feature webui: or web: To indicate this is an update to the WebUI fix: or bugfix: To show this is a bug fix. refactoring: or refactor: When the changes are refactoring a large portion of code You can reference an issue number with #xyz , i.e #1234 Use the Confirm squash and merge button to merge. Example commits Feature feature: Added new availability map #4401 New device newdevice: Added support for Cisco ASA #4402","title":"Merging Pull Requests"},{"location":"Developing/Merging-Pull-Requests/#merging-pull-requests","text":"","title":"Merging Pull Requests"},{"location":"Developing/Merging-Pull-Requests/#github","text":"We will now build the monthly change log from our GitHub commits. When merging a commit, please ensure you: Click the Merge pull request button Give the merge a descriptive but short title For the commit message prepend it with one of the following tags for the pull request to appear in the changelog: devices: or newdevice: For new device support. feature: or feat: To indicate this is a new or updated feature webui: or web: To indicate this is an update to the WebUI fix: or bugfix: To show this is a bug fix. refactoring: or refactor: When the changes are refactoring a large portion of code You can reference an issue number with #xyz , i.e #1234 Use the Confirm squash and merge button to merge.","title":"GitHub"},{"location":"Developing/Merging-Pull-Requests/#example-commits","text":"","title":"Example commits"},{"location":"Developing/Merging-Pull-Requests/#feature","text":"feature: Added new availability map #4401","title":"Feature"},{"location":"Developing/Merging-Pull-Requests/#new-device","text":"newdevice: Added support for Cisco ASA #4402","title":"New device"},{"location":"Developing/SNMP-Traps/","text":"Creating snmp trap handlers You must have a working snmptrapd. See SNMP TRAP HANDLER Make sure the MIB is loaded from the trap you are adding. Edit /etc/systemd/system/snmptrapd.service.d/mibs.conf to add it then restart snmptrapd. MIBDIRS option is not recursive, so you need to specify each directory individually. Create a new class in LibreNMS\\Snmptrap\\Handlers that implements the LibreNMS\\Interfaces\\SnmptrapHandler interface. For example: php /** * ColdBoot.php * * Handles the SNMPv2-MIB::coldStart trap * * 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 3 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 PURPOSE.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, see . * * @package LibreNMS * @link https://www.librenms.org */ namespace LibreNMS\\Snmptrap\\Handlers ; use App\\Models\\Device ; use LibreNMS\\Enum\\Severity ; use LibreNMS\\Interfaces\\SnmptrapHandler ; use LibreNMS\\Snmptrap\\Trap ; class ColdBoot implements SnmptrapHandler { /** * Handle snmptrap. * Data is pre-parsed and delivered as a Trap. * * @param Device $device * @param Trap $trap * @return void */ public function handle ( Device $device , Trap $trap ) { $trap -> log ( 'SNMP Trap: Device ' . $device -> displayName () . ' cold booted' , $device -> device_id , 'reboot' , Severity :: Warning ); } } where number on the end means color of the eventlog: Severity::Ok = green Severity::Info = cyan Severity::Notice = blue Severity::Warning = yellow Severity::Error = red Register the mapping in the config/snmptraps.php file. Make sure to use the full trap OID and correct class. 'SNMPv2-MIB::coldStart' => \\LibreNMS\\Snmptrap\\Handlers\\ColdBoot :: class , The handle function inside your new class will receive a LibreNMS/Snmptrap/Trap object containing the parsed trap. It is common to update the database and create event log entries within the handle function. Getting information from the Trap Source information $trap -> getDevice (); // gets Device model for the device associated with this trap $trap -> ip ; // gets source IP of this trap $trap -> getTrapOid (); // returns the string you registered your class with Retrieving data from the Trap $trap -> getOidData ( 'IF-MIB::ifDescr.114' ); getOidData() requires the full name including any additional index. You can use these functions to search the OID keys. $trap -> findOid ( 'ifDescr' ); // returns the first oid key that contains the string $trap -> findOids ( 'ifDescr' ); // returns all oid keys containing the string Advanced If the above isn't adequate, you can get the entire trap text: $trap -> raw ; Tests Submitting new traps requires them to be fully tested. You can find many examples in the tests/Feature/SnmpTraps/ directory. Here is a basic example of a test that trap handler only creates a log message. If your trap modifies the database, you should also test that it does so. php namespace LibreNMS\\Tests\\Feature\\SnmpTraps ; class ColdStratTest extends SnmpTrapTestCase { public function testColdStart () : void { $this -> assertTrapLogsMessage ( rawTrap : <<< 'TRAP' {{ hostname }} UDP : [{{ ip }}] : 44298 -> [ 192.168 . 5.5 ] : 162 DISMAN - EVENT - MIB :: sysUpTimeInstance 0 : 0 : 1 : 12.7 SNMPv2 - MIB :: snmpTrapOID . 0 SNMPv2 - MIB :: coldStart TRAP , log : 'SNMP Trap: Device {{ hostname }} cold booted' , // The log message sent failureMessage : 'Failed to handle SNMPv2-MIB::coldStart' , // an informative message to let user know what failed args : [ 4 , 'reboot' ], // the additional arguments to the log method ); } }","title":"SNMP Traps"},{"location":"Developing/SNMP-Traps/#creating-snmp-trap-handlers","text":"You must have a working snmptrapd. See SNMP TRAP HANDLER Make sure the MIB is loaded from the trap you are adding. Edit /etc/systemd/system/snmptrapd.service.d/mibs.conf to add it then restart snmptrapd. MIBDIRS option is not recursive, so you need to specify each directory individually. Create a new class in LibreNMS\\Snmptrap\\Handlers that implements the LibreNMS\\Interfaces\\SnmptrapHandler interface. For example: php /** * ColdBoot.php * * Handles the SNMPv2-MIB::coldStart trap * * 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 3 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 PURPOSE.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, see . * * @package LibreNMS * @link https://www.librenms.org */ namespace LibreNMS\\Snmptrap\\Handlers ; use App\\Models\\Device ; use LibreNMS\\Enum\\Severity ; use LibreNMS\\Interfaces\\SnmptrapHandler ; use LibreNMS\\Snmptrap\\Trap ; class ColdBoot implements SnmptrapHandler { /** * Handle snmptrap. * Data is pre-parsed and delivered as a Trap. * * @param Device $device * @param Trap $trap * @return void */ public function handle ( Device $device , Trap $trap ) { $trap -> log ( 'SNMP Trap: Device ' . $device -> displayName () . ' cold booted' , $device -> device_id , 'reboot' , Severity :: Warning ); } } where number on the end means color of the eventlog: Severity::Ok = green Severity::Info = cyan Severity::Notice = blue Severity::Warning = yellow Severity::Error = red Register the mapping in the config/snmptraps.php file. Make sure to use the full trap OID and correct class. 'SNMPv2-MIB::coldStart' => \\LibreNMS\\Snmptrap\\Handlers\\ColdBoot :: class , The handle function inside your new class will receive a LibreNMS/Snmptrap/Trap object containing the parsed trap. It is common to update the database and create event log entries within the handle function.","title":"Creating snmp trap handlers"},{"location":"Developing/SNMP-Traps/#getting-information-from-the-trap","text":"","title":"Getting information from the Trap"},{"location":"Developing/SNMP-Traps/#source-information","text":"$trap -> getDevice (); // gets Device model for the device associated with this trap $trap -> ip ; // gets source IP of this trap $trap -> getTrapOid (); // returns the string you registered your class with","title":"Source information"},{"location":"Developing/SNMP-Traps/#retrieving-data-from-the-trap","text":"$trap -> getOidData ( 'IF-MIB::ifDescr.114' ); getOidData() requires the full name including any additional index. You can use these functions to search the OID keys. $trap -> findOid ( 'ifDescr' ); // returns the first oid key that contains the string $trap -> findOids ( 'ifDescr' ); // returns all oid keys containing the string","title":"Retrieving data from the Trap"},{"location":"Developing/SNMP-Traps/#advanced","text":"If the above isn't adequate, you can get the entire trap text: $trap -> raw ;","title":"Advanced"},{"location":"Developing/SNMP-Traps/#tests","text":"Submitting new traps requires them to be fully tested. You can find many examples in the tests/Feature/SnmpTraps/ directory. Here is a basic example of a test that trap handler only creates a log message. If your trap modifies the database, you should also test that it does so. php namespace LibreNMS\\Tests\\Feature\\SnmpTraps ; class ColdStratTest extends SnmpTrapTestCase { public function testColdStart () : void { $this -> assertTrapLogsMessage ( rawTrap : <<< 'TRAP' {{ hostname }} UDP : [{{ ip }}] : 44298 -> [ 192.168 . 5.5 ] : 162 DISMAN - EVENT - MIB :: sysUpTimeInstance 0 : 0 : 1 : 12.7 SNMPv2 - MIB :: snmpTrapOID . 0 SNMPv2 - MIB :: coldStart TRAP , log : 'SNMP Trap: Device {{ hostname }} cold booted' , // The log message sent failureMessage : 'Failed to handle SNMPv2-MIB::coldStart' , // an informative message to let user know what failed args : [ 4 , 'reboot' ], // the additional arguments to the log method ); } }","title":"Tests"},{"location":"Developing/Sensor-State-Support/","text":"Sensor State Support Introduction In this section we are briefly going to walk through, what it takes to write sensor state support. We will also briefly get around the concepts of the current sensor state monitoring. Logic For sensor state monitoring, we have 4 DB tables we need to concentrate about. sensors state_indexes state_translations sensors_to_state_indexes We will just briefly tie a comment to each one of them. Sensors Each time a sensor needs to be polled, the system needs to know which sensor is it that it need to poll, at what oid is this sensor located and what class the sensor is etc. This information is fetched from the sensors table. state_indexes Is where we keep track of which state sensors we monitor. state_translations Is where we map the possible returned state sensor values to a generic LibreNMS value, in order to make displaying and alerting more generic. We also map these values to the actual state sensor(state_index) where these values are actually returned from. The LibreNMS generic states are derived from Nagios: 0 = OK 1 = Warning 2 = Critical 3 = Unknown sensors_to_state_indexes Is as you might have guessed, where the sensor_id is mapped to a state_index_id. Example For YAML based state discovery: mib : NETBOTZV2-MIB modules : sensors : state : data : - oid : dryContactSensorTable value : dryContactSensorValue num_oid : '.1.3.6.1.4.1.5528.100.4.2.1.1.2.{{ $index }}' descr : dryContactSensorLabel group : Contact Sensors index : 'dryContactSensor.{{ $index }}' state_name : dryContactSensor states : - { value : -1 , generic : 3 , graph : 0 , descr : 'null' } - { value : 0 , generic : 0 , graph : 0 , descr : open } - { value : 1 , generic : 2 , graph : 0 , descr : closed } - oid : doorSwitchSensorTable value : doorSwitchSensorValue num_oid : '.1.3.6.1.4.1.5528.100.4.2.2.1.2.{{ $index }}' descr : doorSwitchSensorLabel group : Switch Sensors index : 'doorSwitchSensor.{{ $index }}' state_name : doorSwitchSensor states : - { value : -1 , generic : 3 , graph : 0 , descr : 'null' } - { value : 0 , generic : 0 , graph : 0 , descr : open } - { value : 1 , generic : 2 , graph : 0 , descr : closed } - oid : cameraMotionSensorTable value : cameraMotionSensorValue num_oid : '.1.3.6.1.4.1.5528.100.4.2.3.1.2.{{ $index }}' descr : cameraMotionSensorLabel group : Camera Motion Sensors index : 'cameraMotionSensor.{{ $index }}' state_name : cameraMotionSensor states : - { value : -1 , generic : 3 , graph : 0 , descr : 'null' } - { value : 0 , generic : 0 , graph : 0 , descr : noMotion } - { value : 1 , generic : 2 , graph : 0 , descr : motionDetected } - oid : otherStateSensorTable value : otherStateSensorErrorStatus num_oid : '.1.3.6.1.4.1.5528.100.4.2.10.1.3.{{ $index }}' descr : otherStateSensorLabel index : '{{ $index }}' state_name : otherStateSensorErrorStatus states : - { value : 0 , generic : 0 , graph : 0 , descr : normal } - { value : 1 , generic : 1 , graph : 0 , descr : info } - { value : 2 , generic : 1 , graph : 0 , descr : warning } - { value : 3 , generic : 2 , graph : 0 , descr : error } - { value : 4 , generic : 2 , graph : 0 , descr : critical } - { value : 5 , generic : 2 , graph : 0 , descr : failure } Advanced Example For advanced state discovery: This example will be based on a Cisco power supply sensor and is all it takes to have sensor state support for Cisco power supplies in Cisco switches. The file should be located in /includes/discovery/sensors/state/cisco.inc.php. php $oids = snmpwalk_group ( $device , 'ciscoEnvMonSupplyStatusTable' , 'CISCO-ENVMON-MIB' ); if ( ! empty ( $oids )) { //Create State Index $state_name = 'ciscoEnvMonSupplyState' ; $states = [ [ 'value' => 1 , 'generic' => 0 , 'graph' => 0 , 'descr' => 'normal' ], [ 'value' => 2 , 'generic' => 1 , 'graph' => 0 , 'descr' => 'warning' ], [ 'value' => 3 , 'generic' => 2 , 'graph' => 0 , 'descr' => 'critical' ], [ 'value' => 4 , 'generic' => 3 , 'graph' => 0 , 'descr' => 'shutdown' ], [ 'value' => 5 , 'generic' => 3 , 'graph' => 0 , 'descr' => 'notPresent' ], [ 'value' => 6 , 'generic' => 2 , 'graph' => 0 , 'descr' => 'notFunctioning' ], ]; create_state_index ( $state_name , $states ); $num_oid = '.1.3.6.1.4.1.9.9.13.1.5.1.3.' ; foreach ( $oids as $index => $entry ) { //Discover Sensors discover_sensor ( $valid [ 'sensor' ], 'state' , $device , $num_oid . $index , $index , $state_name , $entry [ 'ciscoEnvMonSupplyStatusDescr' ], '1' , '1' , null , null , null , null , $entry [ 'ciscoEnvMonSupplyState' ], 'snmp' , $index ); //Create Sensor To State Index create_sensor_to_state_index ( $device , $state_name , $index ); } }","title":"Sensor State Support"},{"location":"Developing/Sensor-State-Support/#sensor-state-support","text":"","title":"Sensor State Support"},{"location":"Developing/Sensor-State-Support/#introduction","text":"In this section we are briefly going to walk through, what it takes to write sensor state support. We will also briefly get around the concepts of the current sensor state monitoring.","title":"Introduction"},{"location":"Developing/Sensor-State-Support/#logic","text":"For sensor state monitoring, we have 4 DB tables we need to concentrate about. sensors state_indexes state_translations sensors_to_state_indexes We will just briefly tie a comment to each one of them.","title":"Logic"},{"location":"Developing/Sensor-State-Support/#sensors","text":"Each time a sensor needs to be polled, the system needs to know which sensor is it that it need to poll, at what oid is this sensor located and what class the sensor is etc. This information is fetched from the sensors table.","title":"Sensors"},{"location":"Developing/Sensor-State-Support/#state_indexes","text":"Is where we keep track of which state sensors we monitor.","title":"state_indexes"},{"location":"Developing/Sensor-State-Support/#state_translations","text":"Is where we map the possible returned state sensor values to a generic LibreNMS value, in order to make displaying and alerting more generic. We also map these values to the actual state sensor(state_index) where these values are actually returned from. The LibreNMS generic states are derived from Nagios: 0 = OK 1 = Warning 2 = Critical 3 = Unknown","title":"state_translations"},{"location":"Developing/Sensor-State-Support/#sensors_to_state_indexes","text":"Is as you might have guessed, where the sensor_id is mapped to a state_index_id.","title":"sensors_to_state_indexes"},{"location":"Developing/Sensor-State-Support/#example","text":"For YAML based state discovery: mib : NETBOTZV2-MIB modules : sensors : state : data : - oid : dryContactSensorTable value : dryContactSensorValue num_oid : '.1.3.6.1.4.1.5528.100.4.2.1.1.2.{{ $index }}' descr : dryContactSensorLabel group : Contact Sensors index : 'dryContactSensor.{{ $index }}' state_name : dryContactSensor states : - { value : -1 , generic : 3 , graph : 0 , descr : 'null' } - { value : 0 , generic : 0 , graph : 0 , descr : open } - { value : 1 , generic : 2 , graph : 0 , descr : closed } - oid : doorSwitchSensorTable value : doorSwitchSensorValue num_oid : '.1.3.6.1.4.1.5528.100.4.2.2.1.2.{{ $index }}' descr : doorSwitchSensorLabel group : Switch Sensors index : 'doorSwitchSensor.{{ $index }}' state_name : doorSwitchSensor states : - { value : -1 , generic : 3 , graph : 0 , descr : 'null' } - { value : 0 , generic : 0 , graph : 0 , descr : open } - { value : 1 , generic : 2 , graph : 0 , descr : closed } - oid : cameraMotionSensorTable value : cameraMotionSensorValue num_oid : '.1.3.6.1.4.1.5528.100.4.2.3.1.2.{{ $index }}' descr : cameraMotionSensorLabel group : Camera Motion Sensors index : 'cameraMotionSensor.{{ $index }}' state_name : cameraMotionSensor states : - { value : -1 , generic : 3 , graph : 0 , descr : 'null' } - { value : 0 , generic : 0 , graph : 0 , descr : noMotion } - { value : 1 , generic : 2 , graph : 0 , descr : motionDetected } - oid : otherStateSensorTable value : otherStateSensorErrorStatus num_oid : '.1.3.6.1.4.1.5528.100.4.2.10.1.3.{{ $index }}' descr : otherStateSensorLabel index : '{{ $index }}' state_name : otherStateSensorErrorStatus states : - { value : 0 , generic : 0 , graph : 0 , descr : normal } - { value : 1 , generic : 1 , graph : 0 , descr : info } - { value : 2 , generic : 1 , graph : 0 , descr : warning } - { value : 3 , generic : 2 , graph : 0 , descr : error } - { value : 4 , generic : 2 , graph : 0 , descr : critical } - { value : 5 , generic : 2 , graph : 0 , descr : failure }","title":"Example"},{"location":"Developing/Sensor-State-Support/#advanced-example","text":"For advanced state discovery: This example will be based on a Cisco power supply sensor and is all it takes to have sensor state support for Cisco power supplies in Cisco switches. The file should be located in /includes/discovery/sensors/state/cisco.inc.php. php $oids = snmpwalk_group ( $device , 'ciscoEnvMonSupplyStatusTable' , 'CISCO-ENVMON-MIB' ); if ( ! empty ( $oids )) { //Create State Index $state_name = 'ciscoEnvMonSupplyState' ; $states = [ [ 'value' => 1 , 'generic' => 0 , 'graph' => 0 , 'descr' => 'normal' ], [ 'value' => 2 , 'generic' => 1 , 'graph' => 0 , 'descr' => 'warning' ], [ 'value' => 3 , 'generic' => 2 , 'graph' => 0 , 'descr' => 'critical' ], [ 'value' => 4 , 'generic' => 3 , 'graph' => 0 , 'descr' => 'shutdown' ], [ 'value' => 5 , 'generic' => 3 , 'graph' => 0 , 'descr' => 'notPresent' ], [ 'value' => 6 , 'generic' => 2 , 'graph' => 0 , 'descr' => 'notFunctioning' ], ]; create_state_index ( $state_name , $states ); $num_oid = '.1.3.6.1.4.1.9.9.13.1.5.1.3.' ; foreach ( $oids as $index => $entry ) { //Discover Sensors discover_sensor ( $valid [ 'sensor' ], 'state' , $device , $num_oid . $index , $index , $state_name , $entry [ 'ciscoEnvMonSupplyStatusDescr' ], '1' , '1' , null , null , null , null , $entry [ 'ciscoEnvMonSupplyState' ], 'snmp' , $index ); //Create Sensor To State Index create_sensor_to_state_index ( $device , $state_name , $index ); } }","title":"Advanced Example"},{"location":"Developing/Support-New-OS/","text":"This document is broken down into the relevant sections depending on what support you are adding. During all of these examples we will be using the OS of pulse as the example OS we will add. Adding the initial detection. Adding Memory and CPU information. Adding Health / Sensor information. Adding Wireless Sensor information. Adding custom graphs. Adding Unit tests (required). Optional Settings We currently have a script in pre-beta stages that can help speed up the process of deploying a new OS. It has support for add sensors in a basic form (except state sensors). In this example, we will add a new OS called test-os using the device ID 101 that has already been added. It will be of the type network and belongs to the vendor, Cisco: ./scripts/new-os.php -h 101 -o test-os -t network -v cisco The process will then step you through the process with some more questions. Please be warned, this is currently pre-beta and may cause some issues. Please let us know of any on Discord .","title":"Intro"},{"location":"Developing/Using-Git/","text":"Git can have a bit of a steep learning curve, stick with it as it is worth learning the basics 2 at least. If you want to help develop LibreNMS and haven't really used Git before then this quick primer will help you get started. Some assumptions: Work is being done on a Linux box. LibreNMS is to be installed in /opt/librenms You have git installed. You have a GitHub Account . You are using ssh to connect to GitHub (If not, replace git@github.com:/yourusername/librenms.git with https://github.com/yourusername/librenms.git . Replace yourusername with your GitHub username. Fork LibreNMS repo You do this directly within GitHub , click the 'Fork' button near the top right. If you are associated with multiple organisations within GitHub then you might need to select which account you want to push the fork to. Prepare your git environment These are the defaults that are recommended. git config branch.autosetupmerge true git config --global user.name \"John Doe\" git config --global user.email johndoe@example.com Clone the repo Ok so now that you have forked the repo, you now need to clone it to your local install where you can then make the changes you need and submit them back. cd /opt/ git clone git@github.com:/yourusername/librenms.git Add Upstream repo To be able to pull in changes from the master LibreNMS repo you need to have it setup on your system. git remote add upstream https://github.com/librenms/librenms.git Now you have two configured remotes: origin: This is your repository, you can push and pull changes here. upstream: This is the main LibreNMS repository and you can only pull changes. Workflow guide As you become more familiar you may find a better workflow that fits your needs, until then this should be a safe workflow for you to follow. Before you start work on a new branch / feature. Make sure you are up to date. cd /opt/librenms git checkout master git pull upstream master git push origin master At this stage it's worth pointing out that we have some standard checks that are performed when you submit a pull request, you can run these checks yourself to be sure no issues are present in your pull request. Now, create a new branch to do you work on. It's important that you do this as you are then able to work on more than one feature at a time and submit them as pull requests individually. If you did all your work in the master branch then it gets a bit messy! You need to give your branch a name. If an issue is open (or closed on GitHub) then you can use that, in this example if the issue number is 123 then we will use issue-123. If a post exists on the community forum then you can use the post id like community-123. You're also welcome to use any arbitrary name for your branch but try and make it relevant to what the branch is. git checkout -b issue-123 Now, code away. Make the changes you need, test, change and test again :) When you are ready to submit the updates as a pull request then commit away. git add path/to/new/files/or/folders git commit -a -m 'Added feature to do X, Y and Z' git push origin issue-123 If you need to rebase against master then you can do this with: git pull upstream master git push origin issue-123 If after do this you get some merge conflicts then you need to resolve these before carrying on. Please try to squash all commits into one, this isn't essential as we can do this when we merge but it would be helpful to do this before you submit your pull request. Now you will be ready to submit a pull request from within GitHub. To do this, go to your GitHub page for the LibreNMS repo. Now select the branch you have just been working on (issue-123) from the drop down to the left and then click 'Pull Request'. Fill in the details to describe the work you have done and click 'Create pull request'. Thanks for your first pull request :) Ok, that should get you started on the contributing path. If you have any other questions then stop by our Discord Server Hints and tips Undo last commit git reset --soft 'HEAD^' Remove specific commit git revert Restore deleted file git checkout $(git rev-list -n 1 HEAD -- \"$file\")^ -- \"$file\" Merge last two commits git rebase --interactive HEAD~2 In the text file that opens, change the last commit to squash from pick then save an exit. For more tips take a look at Oh shit, git!","title":"Using Git"},{"location":"Developing/Using-Git/#fork-librenms-repo","text":"You do this directly within GitHub , click the 'Fork' button near the top right. If you are associated with multiple organisations within GitHub then you might need to select which account you want to push the fork to.","title":"Fork LibreNMS repo"},{"location":"Developing/Using-Git/#prepare-your-git-environment","text":"These are the defaults that are recommended. git config branch.autosetupmerge true git config --global user.name \"John Doe\" git config --global user.email johndoe@example.com","title":"Prepare your git environment"},{"location":"Developing/Using-Git/#clone-the-repo","text":"Ok so now that you have forked the repo, you now need to clone it to your local install where you can then make the changes you need and submit them back. cd /opt/ git clone git@github.com:/yourusername/librenms.git","title":"Clone the repo"},{"location":"Developing/Using-Git/#add-upstream-repo","text":"To be able to pull in changes from the master LibreNMS repo you need to have it setup on your system. git remote add upstream https://github.com/librenms/librenms.git Now you have two configured remotes: origin: This is your repository, you can push and pull changes here. upstream: This is the main LibreNMS repository and you can only pull changes.","title":"Add Upstream repo"},{"location":"Developing/Using-Git/#workflow-guide","text":"As you become more familiar you may find a better workflow that fits your needs, until then this should be a safe workflow for you to follow. Before you start work on a new branch / feature. Make sure you are up to date. cd /opt/librenms git checkout master git pull upstream master git push origin master At this stage it's worth pointing out that we have some standard checks that are performed when you submit a pull request, you can run these checks yourself to be sure no issues are present in your pull request. Now, create a new branch to do you work on. It's important that you do this as you are then able to work on more than one feature at a time and submit them as pull requests individually. If you did all your work in the master branch then it gets a bit messy! You need to give your branch a name. If an issue is open (or closed on GitHub) then you can use that, in this example if the issue number is 123 then we will use issue-123. If a post exists on the community forum then you can use the post id like community-123. You're also welcome to use any arbitrary name for your branch but try and make it relevant to what the branch is. git checkout -b issue-123 Now, code away. Make the changes you need, test, change and test again :) When you are ready to submit the updates as a pull request then commit away. git add path/to/new/files/or/folders git commit -a -m 'Added feature to do X, Y and Z' git push origin issue-123 If you need to rebase against master then you can do this with: git pull upstream master git push origin issue-123 If after do this you get some merge conflicts then you need to resolve these before carrying on. Please try to squash all commits into one, this isn't essential as we can do this when we merge but it would be helpful to do this before you submit your pull request. Now you will be ready to submit a pull request from within GitHub. To do this, go to your GitHub page for the LibreNMS repo. Now select the branch you have just been working on (issue-123) from the drop down to the left and then click 'Pull Request'. Fill in the details to describe the work you have done and click 'Create pull request'. Thanks for your first pull request :) Ok, that should get you started on the contributing path. If you have any other questions then stop by our Discord Server","title":"Workflow guide"},{"location":"Developing/Using-Git/#hints-and-tips","text":"Undo last commit git reset --soft 'HEAD^' Remove specific commit git revert Restore deleted file git checkout $(git rev-list -n 1 HEAD -- \"$file\")^ -- \"$file\" Merge last two commits git rebase --interactive HEAD~2 In the text file that opens, change the last commit to squash from pick then save an exit. For more tips take a look at Oh shit, git!","title":"Hints and tips"},{"location":"Developing/Validating-Code/","text":"Validating Code As part of the pull request process with GitHub we run some automated build tests to ensure that the code is error free, standards compliant and our test suite builds successfully. Rather than submit a pull request and wait for the results, you can run these checks yourself to ensure a more seamless merge. All of these commands should be run from within the librenms directory and can be run as the librenms user unless otherwise noted. Install composer (you can skip this if composer is already installed). curl -sS https://getcomposer.org/installer | php Composer will now be installed into /opt/librenms/composer.phar. Now install the dependencies we require: ./composer.phar install Once composer is installed you can now run the code validation script: ./lnms dev:check If you see Tests ok, submit away :) then all is well. If you see other output then it should contain what you need to resolve the issues and re-test. Git Hooks Git has a hook system which you can use to trigger checks at various stages. Utilising the ./lnms dev:check you can make this part of your commit process. Add ./lnms dev:check to your .git/hooks/pre-commit : echo \"/opt/librenms/lnms dev:check\" >> /opt/librenms/.git/hooks/pre-commit chmod +x /opt/librenms/.git/hooks/pre-commit","title":"Validating Code"},{"location":"Developing/Validating-Code/#validating-code","text":"As part of the pull request process with GitHub we run some automated build tests to ensure that the code is error free, standards compliant and our test suite builds successfully. Rather than submit a pull request and wait for the results, you can run these checks yourself to ensure a more seamless merge. All of these commands should be run from within the librenms directory and can be run as the librenms user unless otherwise noted. Install composer (you can skip this if composer is already installed). curl -sS https://getcomposer.org/installer | php Composer will now be installed into /opt/librenms/composer.phar. Now install the dependencies we require: ./composer.phar install Once composer is installed you can now run the code validation script: ./lnms dev:check If you see Tests ok, submit away :) then all is well. If you see other output then it should contain what you need to resolve the issues and re-test.","title":"Validating Code"},{"location":"Developing/Validating-Code/#git-hooks","text":"Git has a hook system which you can use to trigger checks at various stages. Utilising the ./lnms dev:check you can make this part of your commit process. Add ./lnms dev:check to your .git/hooks/pre-commit : echo \"/opt/librenms/lnms dev:check\" >> /opt/librenms/.git/hooks/pre-commit chmod +x /opt/librenms/.git/hooks/pre-commit","title":"Git Hooks"},{"location":"Developing/os/Custom-Graphs/","text":"First we define our graphs in includes/definitions.inc.php to share our work and contribute in the development of LibreNMS. :-) (or place in config.php if you don't plan to contribute) // Pulse Secure Graphs $config [ 'graph_types' ][ 'device' ][ 'pulse_sessions' ] = [ 'section' => 'firewall' , 'order' => 0 , 'descr' => 'Active Sessions' ]; $config [ 'graph_types' ][ 'device' ][ 'pulse_users' ] = [ 'section' => 'firewall' , 'order' => 0 , 'descr' => 'Active Users' ]; Polling OS OS polling is not necessarily where custom polling should be done, please speak to one of the core devs in Discord for guidance. Let's update our example file to add additional polling: includes/polling/os/pulse.inc.php We declare two specific graphs for users and sessions numbers. Theses two graphs will be displayed on the firewall section of the graphs tab as it was written in the definition include file. php use LibreNMS\\RRD\\RrdDefinition ; $users = snmp_get ( $device , 'iveConcurrentUsers.0' , '-OQv' , 'PULSESECURE-PSG-MIB' ); if ( is_numeric ( $users )) { $rrd_def = RrdDefinition :: make () -> addDataset ( 'users' , 'GAUGE' , 0 ); $fields = array ( 'users' => $users , ); $tags = compact ( 'rrd_def' ); data_update ( $device , 'pulse_users' , $tags , $fields ); $os -> enableGraph ( 'pulse_users' ); } $sessions = snmp_get ( $device , 'iveConcurrentUsers.0' , '-OQv' , 'PULSESECURE-PSG-MIB' ); if ( is_numeric ( $sessions )) { $rrd_def = RrdDefinition :: make () -> addDataset ( 'sessions' , 'GAUGE' , 0 ); $fields = array ( 'sessions' => $sessions , ); $tags = compact ( 'rrd_def' ); data_update ( $device , 'pulse_sessions' , $tags , $fields ); $os -> enableGraph ( 'pulse_sessions' ); } Displaying The specific graphs are not displayed automatically so we need to write the following PHP code: Pulse Sessions includes/html/graphs/device/pulse_sessions.inc.php php $rrd_filename = Rrd :: name ( $device [ 'hostname' ], 'pulse_sessions' ); require 'includes/html/graphs/common.inc.php' ; $ds = 'sessions' ; $colour_area = '9999cc' ; $colour_line = '0000cc' ; $colour_area_max = '9999cc' ; $graph_max = 1 ; $unit_text = 'Sessions' ; require 'includes/graphs/generic_simplex.inc.php' ; Pulse Users includes/html/graphs/device/pulse_users.inc.php php $rrd_filename = Rrd :: name ( $device [ 'hostname' ], 'pulse_users' ); require 'includes/html/graphs/common.inc.php' ; $ds = 'users' ; $colour_area = '9999cc' ; $colour_line = '0000cc' ; $colour_area_max = '9999cc' ; $graph_max = 1 ; $unit_text = 'Users' ; require 'includes/html/graphs/generic_simplex.inc.php' ; That should be it, after data has started to be collected graphs should appear in the WebUI.","title":"Custom Graphs"},{"location":"Developing/os/Custom-Graphs/#polling-os","text":"OS polling is not necessarily where custom polling should be done, please speak to one of the core devs in Discord for guidance. Let's update our example file to add additional polling: includes/polling/os/pulse.inc.php We declare two specific graphs for users and sessions numbers. Theses two graphs will be displayed on the firewall section of the graphs tab as it was written in the definition include file. php use LibreNMS\\RRD\\RrdDefinition ; $users = snmp_get ( $device , 'iveConcurrentUsers.0' , '-OQv' , 'PULSESECURE-PSG-MIB' ); if ( is_numeric ( $users )) { $rrd_def = RrdDefinition :: make () -> addDataset ( 'users' , 'GAUGE' , 0 ); $fields = array ( 'users' => $users , ); $tags = compact ( 'rrd_def' ); data_update ( $device , 'pulse_users' , $tags , $fields ); $os -> enableGraph ( 'pulse_users' ); } $sessions = snmp_get ( $device , 'iveConcurrentUsers.0' , '-OQv' , 'PULSESECURE-PSG-MIB' ); if ( is_numeric ( $sessions )) { $rrd_def = RrdDefinition :: make () -> addDataset ( 'sessions' , 'GAUGE' , 0 ); $fields = array ( 'sessions' => $sessions , ); $tags = compact ( 'rrd_def' ); data_update ( $device , 'pulse_sessions' , $tags , $fields ); $os -> enableGraph ( 'pulse_sessions' ); }","title":"Polling OS"},{"location":"Developing/os/Custom-Graphs/#displaying","text":"The specific graphs are not displayed automatically so we need to write the following PHP code: Pulse Sessions includes/html/graphs/device/pulse_sessions.inc.php php $rrd_filename = Rrd :: name ( $device [ 'hostname' ], 'pulse_sessions' ); require 'includes/html/graphs/common.inc.php' ; $ds = 'sessions' ; $colour_area = '9999cc' ; $colour_line = '0000cc' ; $colour_area_max = '9999cc' ; $graph_max = 1 ; $unit_text = 'Sessions' ; require 'includes/graphs/generic_simplex.inc.php' ; Pulse Users includes/html/graphs/device/pulse_users.inc.php php $rrd_filename = Rrd :: name ( $device [ 'hostname' ], 'pulse_users' ); require 'includes/html/graphs/common.inc.php' ; $ds = 'users' ; $colour_area = '9999cc' ; $colour_line = '0000cc' ; $colour_area_max = '9999cc' ; $graph_max = 1 ; $unit_text = 'Users' ; require 'includes/html/graphs/generic_simplex.inc.php' ; That should be it, after data has started to be collected graphs should appear in the WebUI.","title":"Displaying"},{"location":"Developing/os/Health-Information/","text":"Sensors This document will guide you through adding health / sensor information for your new device. Currently, we have support for the following health metrics along with the values we expect to see the data in: Class Measurement airflow cfm ber ratio charge % chromatic_dispersion ps/nm cooling W count # current A dbm dBm delay s eer eer fanspeed rpm frequency Hz humidity % load % loss % power W power_consumed kWh power_factor ratio pressure kPa quality_factor dB runtime Min signal dBm snr SNR state # temperature C tv_signal dBmV bitrate bps voltage V waterflow l/m percent % Simple health discovery We have support for defining health / sensor discovery using YAML files so that you don't need to know how to write PHP. Please note that DISPLAY-HINTS are disabled so ensure you use the correct divisor / multiplier if applicable. All yaml files are located in includes/definitions/discovery/$os.yaml . Defining the information here is not always possible and is heavily reliant on vendors being sensible with the MIBs they generate. Only snmp walks are supported, and you must provide a sane table that can be traversed and contains all the data you need. We will use netbotz as an example here. includes/definitions/discovery/netbotz.yaml mib : NETBOTZV2-MIB modules : sensors : airflow : options : skip_value_lt : 0 data : - oid : airFlowSensorTable value : airFlowSensorValue divisor : 10 num_oid : '.1.3.6.1.4.1.5528.100.4.1.5.1.2.{{ $index }}' descr : '{{ $airFlowSensorLabel }}' index : 'airFlowSensorValue.{{ $index }}' At the top you can define one or more mibs to be used in the lookup of data: mib: NETBOTZV2-MIB For use of multiple MIB files separate them with a colon: mib: NETBOTZV2-MIB:SECOND-MIB For data: you have the following options: The only sensor we have defined here is airflow. The available options are as follows: oid (required): This is the name of the table you want to snmp walk for data. value (optional): This is the key within the table that contains the value. If not provided will use oid num_oid (required for PullRequests): If not provided, this parameter should be computed automatically by discovery process. This parameter is still required to submit a pull request. This is the numerical OID that contains value . This should usually include {{ $index }} . In case the index is a string, {{ $index_string }} can be used instead. divisor (optional): This is the divisor to use against the returned value . multiplier (optional): This is the multiplier to use against the returned value . low_limit (optional): This is the critical low threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. low_warn_limit (optional): This is the warning low threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. warn_limit (optional): This is the warning high threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. high_limit (optional): This is the critical high threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. descr (required): The visible label for this sensor. It can be a key with in the table or a static string, optionally using {{ index }} . group (optional): Groups sensors together under in the webui, displaying this text. Not specifying this will put the sensors in the default group. index (optional): This is the index value we use to uniquely identify this sensor. {{ $index }} will be replaced by the index from the snmp walk. skip_values (optional): This is an array of values we should skip over (see note below). skip_value_lt (optional): If sensor value is less than this, skip the discovery. skip_value_gt (optional): If sensor value is greater than this, skip the discovery. entPhysicalIndex (optional): If the sensor belongs to a physical entity then you can specify the index here. entPhysicalIndex_measured (optional): If the sensor belongs to a physical entity then you can specify the entity type here. user_func (optional): You can provide a function name for the sensors value to be processed through (i.e. Convert fahrenheit to celsius use fahrenheit_to_celsius ) snmp_flags (optional): this sets the flags to be sent to snmpwalk, it overrides flags set on the sensor type and os. The default is '-OQUb' . A common issue is dealing with string indexes, setting '-OQUsbe' will change them to numeric oids. Setting ['-OQUsbe', '-Pu'] will also allow _ in oid names. You can find more in the Man Page rrd_type (optional): You can change the type of the RRD file that will be created to store the data. By default, type GAUGE is used. More details can be found here: https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html For options: you have the following available: divisor : This is the divisor to use against the returned value . multiplier : This is the multiplier to use against the returned value . skip_values : This is an array of values we should skip over (see note below). skip_value_lt : If sensor value is less than this, skip the discovery. skip_value_gt : If sensor value is greater than this, skip the discovery. Multiple variables can be used in the sensor's definition. The syntax is {{ $variable }} . Any oid in the current table can be used, as well as pre_cached data. The index ($index) and the sub_indexes (in case the oid is indexed multiple times) are also available: if $index=\"1.20\", then $subindex0=\"1\" and $subindex1=\"20\". When referencing an oid in another table the full index will be used to match the other table. If this is undesirable, you may use a single sub index by appending the sub index after a colon to the variable name. Example {{ $ifName:2 }} skip_values can also compare items within the OID table against values. The index of the sensor is used to retrieve the value from the OID, unless a target index is appended to the OID. Additionally, you may check fields from the device. Comparisons behave on a logical OR basis when chained, so only one of them needs to be matched for that particular sensor to be skipped during discovery. An example of this is below: skip_values : - oid : sensUnit op : '!=' value : 4 - oid : sensConfig.0 op : '!=' value : 1 - device : hardware op : 'contains' value : 'rev2' op can be any of the following operators : =, !=, ==, !==, <=, >=, <, >, starts, ends, contains, regex, in_array, not_starts, not_ends, not_contains, not_regex, not_in_array, exists Example: skip_values : - oid : sensorName op : 'not_in_array' value : [ 'sensor1' , 'sensor2' ] skip_values : - oid : sensorOptionalOID op : 'exists' value : false temperature : data : - oid : hwOpticalModuleInfoTable value : hwEntityOpticalTemperature descr : '{{ $entPhysicalName }}' index : '{{ $index }}' skip_values : - oid : hwEntityOpticalMode op : '=' value : '1' If you aren't able to use yaml to perform the sensor discovery, you will most likely need to use Advanced health discovery. Advanced health discovery If you can't use the yaml files as above, then you will need to create the discovery code in php. If it is possible to create via yaml, php discovery will likely be rejected due to the much higher chance of later problems, so it is highly suggested to use yaml. The directory structure for sensor information is includes/discovery/sensors/$class/$os.inc.php . The format of all the sensors follows the same code format which is to collect sensor information via SNMP and then call the discover_sensor() function; except state sensors which requires additional code. Sensor information is commonly found in an ENTITY mib supplied by device's vendor in the form of a table. Other mib tables may be used as well. Sensor information is first collected by includes/discovery/sensors/pre_cache/$os.inc.php . This program will pull in data from mib tables into a $pre_cache array that can then be used in includes/discovery/sensors/$class/$os.inc.php to extract specific values which are then passed to discover_sensor() . discover_sensor() Accepts the following arguments: &$valid = This is always $valid['sensor'], do not pass any other values. $class = Required. This is the sensor class from the table above (i.e humidity). $device = Required. This is the $device array. $oid = Required. This must be the numerical OID for where the data can be found, i.e .1.2.3.4.5.6.7.0 $index = Required. This must be unique for this sensor class, device and type. Typically it's the index from the table being walked, or it could be the name of the OID if it's a single value. $type = Required. This should be the OS name, i.e. pulse. $descr = Required. This is a descriptive value for the sensor. Some devices will provide names to use. $divisor = Defaults to 1. This is used to divide the returned value. $multiplier = Defaults to 1. This is used to multiply the returned value. $low_limit = Defaults to null. Sets the low threshold limit for the sensor, used in alerting to report out range sensors. $low_warn_limit = Defaults to null. Sets the low warning limit for the sensor, used in alerting to report near out of range sensors. $warn_limit = Defaults to null. Sets the high warning limit for the sensor, used in alerting to report near out of range sensors. $high_limit = Defaults to null. Sets the high limit for the sensor, used in alerting to report out range sensors. $current = Defaults to null. Can be used to set the current value on discovery. Poller will update this on the next poll cycle anyway. $poller_type = Defaults to snmp. Things like the unix-agent can set different values but for the most part this should be left as snmp. $entPhysicalIndex = Defaults to null. Sets the entPhysicalIndex to be used to look up further hardware if available. $entPhysicalIndex_measured = Defaults to null. Sets the type of entPhysicalIndex used, i.e ports. $user_func = Defaults to null. You can provide a function name for the sensors value to be processed through (i.e. Convert fahrenheit to celsius use fahrenheit_to_celsius ) $group = Defaults to null. Groups sensors together under in the webui, displaying this text. $rrd_type = Default to 'GAUGE'. Allows to change the type of the RRD file created for this sensor. More details can be found here in the RRD documentation: https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html For the majority of devices, this is all that's required to add support for a sensor. Polling is done based on the data gathered using discover_sensor() . If custom polling is needed then the file format is similar to discovery: includes/polling/sensors/$class/$os.inc.php . Whilst it's possible to perform additional snmp queries within polling this should be avoided where possible. The value for the OID is already available as $sensor_value . Graphing is performed automatically for sensors, no custom graphing is required or supported. Adding a new sensor class You will need to add code for your new sensor class in the following existing files: app/Models/Sensor.php : add a free icon from Font Awesome in the $icons array. doc/Developing/os/Health-Information.md : documentation for every sensor class is mandatory. includes/discovery/sensors.inc.php : add the sensor class to the $run_sensors array. includes/discovery/functions.inc.php : optional - if sensible low_limit and high_limit values are guessable when a SNMP-retrievable threshold is not available, add a case for the sensor class to the sensor_limit() and/or sensor_low_limit() functions. LibreNMS/Util/ObjectCache.php : optional - choose menu grouping for the sensor class. includes/html/pages/device/health.inc.php : add a dbFetchCell(), $datas[], and $type_text[] entry for the sensor class. includes/html/pages/device/overview.inc.php : add require 'overview/sensors/$class.inc.php' in the desired order for the device overview page. includes/html/pages/health.inc.php : add a $type_text[] entry for the sensor class. lang/en/sensors.php : add human-readable names and units for the sensor class in English, feel free to do so for other languages as well. Create and populate new files for the sensor class in the following places: includes/discovery/sensors/$class/ : create the folder where advanced php-based discovery files are stored. Not used for yaml discovery. ======= includes/html/pages/device/health.inc.php : add a dbFetchCell(), $datas[], and $type_text[] entry for the sensor class. includes/html/pages/device/overview.inc.php : add require 'overview/sensors/$class.inc.php' in the desired order for the device overview page. includes/html/pages/health.inc.php : add a $type_text[] entry for the sensor class. lang/en/sensors.php : add human-readable names and units for the sensor class in English, feel free to do so for other languages as well. Create and populate new files for the sensor class in the following places: includes/discovery/sensors/$class/ : create the folder where advanced php-based discovery files are stored. Not used for yaml discovery. includes/html/graphs/device/$class.inc.php : define unit names used in RRDtool graphs. includes/html/graphs/sensor/$class.inc.php : define various parameters for RRDtool graphs. includes/html/pages/device/health/$class.inc.php includes/html/pages/device/overview/sensors/$class.inc.php includes/html/pages/health/$class.inc.php Advanced health sensor example This example shows how to build sensors using the advanced method. In this example we will be collecting optical power level (dBm) from Adva FSP150CC family MetroE devices. This example will assume an understanding of SNMP and MIBs. First we setup includes/discovery/sensors/pre_cache/adva_fsp150.inc as shown below. The first line walks the cmEntityObject table to get information about the chassis and line cards. From this information we extract the model type which will identify which tables in the CM-Facility-Mib the ports are populated in. The program then reads the appropriate table into the $pre_cache array adva_fsp150_ports . This array will have OID indexies for each port, which we will use later to identify our sensor OIDs. $pre_cache['adva_fsp150'] = snmpwalk_cache_multi_oid($device, 'cmEntityObjects', [], 'CM-ENTITY-MIB', null, '-OQUbs'); $neType = $pre_cache['adva_fsp150'][1]['neType']; if ($neType == 'ccxg116pro') { $pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetTrafficPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs'); } else { $pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetNetPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs'); $pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetAccPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs'); } Next we are going to build our sensor discovery code. These are optical readings, so the file will be created as the dBm sensor type in includes/discover/sensors/dbm/adva_fsp150.inc.php . Below is a snippet of the code: foreach ($pre_cache['adva_fsp150_ports'] as $index => $entry) { if ($entry['cmEthernetTrafficPortMediaType'] == 'fiber') { //Discover received power level $oidRx = '.1.3.6.1.4.1.2544.1.12.5.1.21.1.34.' . $index . '.3'; $oidTx = '.1.3.6.1.4.1.2544.1.12.5.1.21.1.33.' . $index . '.3'; $currentRx = snmp_get($device, $oidRx, '-Oqv', 'CM-PERFORMANCE-MIB', '/opt/librenms/mibs/adva'); $currentTx = snmp_get($device, $oidTx, '-Oqv', 'CM-PERFORMANCE-MIB', '/opt/librenms/mibs/adva'); if ($currentRx != 0 || $currentTx != 0) { $entPhysicalIndex = $entry['cmEthernetTrafficPortIfIndex']; $entPhysicalIndex_measured = 'ports'; $descrRx = dbFetchCell('SELECT `ifName` FROM `ports` WHERE `ifIndex`= ? AND `device_id` = ?', [$entry['cmEthernetTrafficPortIfIndex'], $device['device_id']]) . ' Rx Power'; discover_sensor( $valid['sensor'], 'dbm', $device, $oidRx, 'cmEthernetTrafficPortStatsOPR.' . $index, 'adva_fsp150', $descrRx, $divisor, $multiplier, null, null, null, null, $currentRx, 'snmp', $entPhysicalIndex, $entPhysicalIndex_measured ); $descrTx = dbFetchCell('SELECT `ifName` FROM `ports` WHERE `ifIndex`= ? AND `device_id` = ?', [$entry['cmEthernetTrafficPortIfIndex'], $device['device_id']]) . ' Tx Power'; discover_sensor( $valid['sensor'], 'dbm', $device, $oidTx, 'cmEthernetTrafficPortStatsOPT.' . $index, 'adva_fsp150', $descrTx, $divisor, $multiplier, null, null, null, null, $currentTx, 'snmp', $entPhysicalIndex, $entPhysicalIndex_measured ); } } } First the program will loop through each port's index value. In the case of Advas, the ports are names Ethernet 1-1-1-1, 1-1-1-2, etc, and they are indexed as oid.1.1.1.1, oid.1.1.1.2, etc in the mib. Next the program checks which table the port exists in and that the connector type is 'fiber'. There are other port tables in the full code that were ommitted from the example for brevity. Copper media won't have optical readings, so if the media type isn't fiber we skip discovery for that port. The next two lines build the OIDs for getting the optical receive and transmit values using the $index for the port. Using the OIDs the program gets the current receive and transmit values ($currentRx and $currentTx repectively) to verify the values are not 0. Not all SFPs collect digital optical monitoring (DOM) data, in the case of Adva the value of both transmit and recieve will be 0 if DOM is not available. While 0 is a valid value for optical power, its extremely unlikely that both will be 0 if DOM is present. If DOM is not available, then the program stops discovery for that port. Note that while this is the case with Adva, other vendors may differ in how they handle optics that do not supply DOM. Please check your vendor's mibs. Next the program assigns the values of $entPhysicalIndex and $entPhysicalIndex_measured. In this case $entPhysicalIndex is set to the value of the cmEthernetTrafficPortIfIndex so that it is associated with port. This will also allow the sensor graphs to show up on the associated port's page in the GUI in addition to the Health page. Following that the program uses a database call to get the description of the port which will be used as the title for the graph in the GUI. Lastly the program calls discover_sensor() and passes the information collected in the previous steps. The null values are for low, low warning, high, and high warning values, which are not collected in the Adva's MIB. You can manually run discovery to verify the code works by running ./discovery.php -h $device_id -m sensors . You can use -v to see what calls are being used during discovery and -d to see debug output. In the output under #### Load disco module sensors #### you can see a list of sensors types. If there is a + a sensor is added, if there is a - one was deleted, and a . means no change. If there is nothing next to the sensor type then the sensor was not discovered. There is is also information about changes to the database and RRD files at the bottom. [librenms@nms-test ~]$ ./discovery.php -h 2 -m sensors LibreNMS Discovery 164.113.194.250 2 adva_fsp150 #### Load disco module core #### >> Runtime for discovery module 'core': 0.0240 seconds with 66536 bytes >> SNMP: [2/0.06s] MySQL: [3/0.00s] RRD: [0/0.00s] #### Unload disco module core #### #### Load disco module sensors #### Pre-cache adva_fsp150: ENTITY-SENSOR: Caching OIDs: entPhysicalDescr entPhysicalName entPhySensorType entPhySensorScale entPhySensorPrecision entPhySensorValue entPhySensorOperStatus Airflow: Current: . Charge: Dbm: Adva FSP-150 dBm.. Fanspeed: Frequency: Humidity: Load: Power: Power_consumed: Power_factor: Runtime: Signal: State: Count: Temperature: .. Tv_signal: Bitrate: Voltage: . Snr: Pressure: Cooling: Delay: Quality_factor: Chromatic_dispersion: Ber: Eer: Waterflow: Percent: >> Runtime for discovery module 'sensors': 3.9340 seconds with 190024 bytes >> SNMP: [16/3.89s] MySQL: [36/0.03s] RRD: [0/0.00s] #### Unload disco module sensors #### Discovered in 5.521 seconds SNMP [18/3.96s]: Get[8/0.81s] Getnext[0/0.00s] Walk[10/3.15s] MySQL [41/0.03s]: Cell[10/0.01s] Row[-4/-0.00s] Rows[31/0.02s] Column[0/0.00s] Update[2/0.00s] Insert[2/0.00s] Delete[0/0.00s] RRD [0/0.00s]: Update[0/0.00s] Create [0/0.00s] Other[0/0.00s]","title":"Health Information"},{"location":"Developing/os/Health-Information/#sensors","text":"This document will guide you through adding health / sensor information for your new device. Currently, we have support for the following health metrics along with the values we expect to see the data in: Class Measurement airflow cfm ber ratio charge % chromatic_dispersion ps/nm cooling W count # current A dbm dBm delay s eer eer fanspeed rpm frequency Hz humidity % load % loss % power W power_consumed kWh power_factor ratio pressure kPa quality_factor dB runtime Min signal dBm snr SNR state # temperature C tv_signal dBmV bitrate bps voltage V waterflow l/m percent %","title":"Sensors"},{"location":"Developing/os/Health-Information/#simple-health-discovery","text":"We have support for defining health / sensor discovery using YAML files so that you don't need to know how to write PHP. Please note that DISPLAY-HINTS are disabled so ensure you use the correct divisor / multiplier if applicable. All yaml files are located in includes/definitions/discovery/$os.yaml . Defining the information here is not always possible and is heavily reliant on vendors being sensible with the MIBs they generate. Only snmp walks are supported, and you must provide a sane table that can be traversed and contains all the data you need. We will use netbotz as an example here. includes/definitions/discovery/netbotz.yaml mib : NETBOTZV2-MIB modules : sensors : airflow : options : skip_value_lt : 0 data : - oid : airFlowSensorTable value : airFlowSensorValue divisor : 10 num_oid : '.1.3.6.1.4.1.5528.100.4.1.5.1.2.{{ $index }}' descr : '{{ $airFlowSensorLabel }}' index : 'airFlowSensorValue.{{ $index }}' At the top you can define one or more mibs to be used in the lookup of data: mib: NETBOTZV2-MIB For use of multiple MIB files separate them with a colon: mib: NETBOTZV2-MIB:SECOND-MIB For data: you have the following options: The only sensor we have defined here is airflow. The available options are as follows: oid (required): This is the name of the table you want to snmp walk for data. value (optional): This is the key within the table that contains the value. If not provided will use oid num_oid (required for PullRequests): If not provided, this parameter should be computed automatically by discovery process. This parameter is still required to submit a pull request. This is the numerical OID that contains value . This should usually include {{ $index }} . In case the index is a string, {{ $index_string }} can be used instead. divisor (optional): This is the divisor to use against the returned value . multiplier (optional): This is the multiplier to use against the returned value . low_limit (optional): This is the critical low threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. low_warn_limit (optional): This is the warning low threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. warn_limit (optional): This is the warning high threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. high_limit (optional): This is the critical high threshold that value should be (used in alerting). If an OID is specified then divisor / multiplier are used. descr (required): The visible label for this sensor. It can be a key with in the table or a static string, optionally using {{ index }} . group (optional): Groups sensors together under in the webui, displaying this text. Not specifying this will put the sensors in the default group. index (optional): This is the index value we use to uniquely identify this sensor. {{ $index }} will be replaced by the index from the snmp walk. skip_values (optional): This is an array of values we should skip over (see note below). skip_value_lt (optional): If sensor value is less than this, skip the discovery. skip_value_gt (optional): If sensor value is greater than this, skip the discovery. entPhysicalIndex (optional): If the sensor belongs to a physical entity then you can specify the index here. entPhysicalIndex_measured (optional): If the sensor belongs to a physical entity then you can specify the entity type here. user_func (optional): You can provide a function name for the sensors value to be processed through (i.e. Convert fahrenheit to celsius use fahrenheit_to_celsius ) snmp_flags (optional): this sets the flags to be sent to snmpwalk, it overrides flags set on the sensor type and os. The default is '-OQUb' . A common issue is dealing with string indexes, setting '-OQUsbe' will change them to numeric oids. Setting ['-OQUsbe', '-Pu'] will also allow _ in oid names. You can find more in the Man Page rrd_type (optional): You can change the type of the RRD file that will be created to store the data. By default, type GAUGE is used. More details can be found here: https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html For options: you have the following available: divisor : This is the divisor to use against the returned value . multiplier : This is the multiplier to use against the returned value . skip_values : This is an array of values we should skip over (see note below). skip_value_lt : If sensor value is less than this, skip the discovery. skip_value_gt : If sensor value is greater than this, skip the discovery. Multiple variables can be used in the sensor's definition. The syntax is {{ $variable }} . Any oid in the current table can be used, as well as pre_cached data. The index ($index) and the sub_indexes (in case the oid is indexed multiple times) are also available: if $index=\"1.20\", then $subindex0=\"1\" and $subindex1=\"20\". When referencing an oid in another table the full index will be used to match the other table. If this is undesirable, you may use a single sub index by appending the sub index after a colon to the variable name. Example {{ $ifName:2 }} skip_values can also compare items within the OID table against values. The index of the sensor is used to retrieve the value from the OID, unless a target index is appended to the OID. Additionally, you may check fields from the device. Comparisons behave on a logical OR basis when chained, so only one of them needs to be matched for that particular sensor to be skipped during discovery. An example of this is below: skip_values : - oid : sensUnit op : '!=' value : 4 - oid : sensConfig.0 op : '!=' value : 1 - device : hardware op : 'contains' value : 'rev2' op can be any of the following operators : =, !=, ==, !==, <=, >=, <, >, starts, ends, contains, regex, in_array, not_starts, not_ends, not_contains, not_regex, not_in_array, exists Example: skip_values : - oid : sensorName op : 'not_in_array' value : [ 'sensor1' , 'sensor2' ] skip_values : - oid : sensorOptionalOID op : 'exists' value : false temperature : data : - oid : hwOpticalModuleInfoTable value : hwEntityOpticalTemperature descr : '{{ $entPhysicalName }}' index : '{{ $index }}' skip_values : - oid : hwEntityOpticalMode op : '=' value : '1' If you aren't able to use yaml to perform the sensor discovery, you will most likely need to use Advanced health discovery.","title":"Simple health discovery"},{"location":"Developing/os/Health-Information/#advanced-health-discovery","text":"If you can't use the yaml files as above, then you will need to create the discovery code in php. If it is possible to create via yaml, php discovery will likely be rejected due to the much higher chance of later problems, so it is highly suggested to use yaml. The directory structure for sensor information is includes/discovery/sensors/$class/$os.inc.php . The format of all the sensors follows the same code format which is to collect sensor information via SNMP and then call the discover_sensor() function; except state sensors which requires additional code. Sensor information is commonly found in an ENTITY mib supplied by device's vendor in the form of a table. Other mib tables may be used as well. Sensor information is first collected by includes/discovery/sensors/pre_cache/$os.inc.php . This program will pull in data from mib tables into a $pre_cache array that can then be used in includes/discovery/sensors/$class/$os.inc.php to extract specific values which are then passed to discover_sensor() . discover_sensor() Accepts the following arguments: &$valid = This is always $valid['sensor'], do not pass any other values. $class = Required. This is the sensor class from the table above (i.e humidity). $device = Required. This is the $device array. $oid = Required. This must be the numerical OID for where the data can be found, i.e .1.2.3.4.5.6.7.0 $index = Required. This must be unique for this sensor class, device and type. Typically it's the index from the table being walked, or it could be the name of the OID if it's a single value. $type = Required. This should be the OS name, i.e. pulse. $descr = Required. This is a descriptive value for the sensor. Some devices will provide names to use. $divisor = Defaults to 1. This is used to divide the returned value. $multiplier = Defaults to 1. This is used to multiply the returned value. $low_limit = Defaults to null. Sets the low threshold limit for the sensor, used in alerting to report out range sensors. $low_warn_limit = Defaults to null. Sets the low warning limit for the sensor, used in alerting to report near out of range sensors. $warn_limit = Defaults to null. Sets the high warning limit for the sensor, used in alerting to report near out of range sensors. $high_limit = Defaults to null. Sets the high limit for the sensor, used in alerting to report out range sensors. $current = Defaults to null. Can be used to set the current value on discovery. Poller will update this on the next poll cycle anyway. $poller_type = Defaults to snmp. Things like the unix-agent can set different values but for the most part this should be left as snmp. $entPhysicalIndex = Defaults to null. Sets the entPhysicalIndex to be used to look up further hardware if available. $entPhysicalIndex_measured = Defaults to null. Sets the type of entPhysicalIndex used, i.e ports. $user_func = Defaults to null. You can provide a function name for the sensors value to be processed through (i.e. Convert fahrenheit to celsius use fahrenheit_to_celsius ) $group = Defaults to null. Groups sensors together under in the webui, displaying this text. $rrd_type = Default to 'GAUGE'. Allows to change the type of the RRD file created for this sensor. More details can be found here in the RRD documentation: https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html For the majority of devices, this is all that's required to add support for a sensor. Polling is done based on the data gathered using discover_sensor() . If custom polling is needed then the file format is similar to discovery: includes/polling/sensors/$class/$os.inc.php . Whilst it's possible to perform additional snmp queries within polling this should be avoided where possible. The value for the OID is already available as $sensor_value . Graphing is performed automatically for sensors, no custom graphing is required or supported.","title":"Advanced health discovery"},{"location":"Developing/os/Health-Information/#adding-a-new-sensor-class","text":"You will need to add code for your new sensor class in the following existing files: app/Models/Sensor.php : add a free icon from Font Awesome in the $icons array. doc/Developing/os/Health-Information.md : documentation for every sensor class is mandatory. includes/discovery/sensors.inc.php : add the sensor class to the $run_sensors array. includes/discovery/functions.inc.php : optional - if sensible low_limit and high_limit values are guessable when a SNMP-retrievable threshold is not available, add a case for the sensor class to the sensor_limit() and/or sensor_low_limit() functions. LibreNMS/Util/ObjectCache.php : optional - choose menu grouping for the sensor class. includes/html/pages/device/health.inc.php : add a dbFetchCell(), $datas[], and $type_text[] entry for the sensor class. includes/html/pages/device/overview.inc.php : add require 'overview/sensors/$class.inc.php' in the desired order for the device overview page. includes/html/pages/health.inc.php : add a $type_text[] entry for the sensor class. lang/en/sensors.php : add human-readable names and units for the sensor class in English, feel free to do so for other languages as well. Create and populate new files for the sensor class in the following places: includes/discovery/sensors/$class/ : create the folder where advanced php-based discovery files are stored. Not used for yaml discovery. ======= includes/html/pages/device/health.inc.php : add a dbFetchCell(), $datas[], and $type_text[] entry for the sensor class. includes/html/pages/device/overview.inc.php : add require 'overview/sensors/$class.inc.php' in the desired order for the device overview page. includes/html/pages/health.inc.php : add a $type_text[] entry for the sensor class. lang/en/sensors.php : add human-readable names and units for the sensor class in English, feel free to do so for other languages as well. Create and populate new files for the sensor class in the following places: includes/discovery/sensors/$class/ : create the folder where advanced php-based discovery files are stored. Not used for yaml discovery. includes/html/graphs/device/$class.inc.php : define unit names used in RRDtool graphs. includes/html/graphs/sensor/$class.inc.php : define various parameters for RRDtool graphs. includes/html/pages/device/health/$class.inc.php includes/html/pages/device/overview/sensors/$class.inc.php includes/html/pages/health/$class.inc.php","title":"Adding a new sensor class"},{"location":"Developing/os/Health-Information/#advanced-health-sensor-example","text":"This example shows how to build sensors using the advanced method. In this example we will be collecting optical power level (dBm) from Adva FSP150CC family MetroE devices. This example will assume an understanding of SNMP and MIBs. First we setup includes/discovery/sensors/pre_cache/adva_fsp150.inc as shown below. The first line walks the cmEntityObject table to get information about the chassis and line cards. From this information we extract the model type which will identify which tables in the CM-Facility-Mib the ports are populated in. The program then reads the appropriate table into the $pre_cache array adva_fsp150_ports . This array will have OID indexies for each port, which we will use later to identify our sensor OIDs. $pre_cache['adva_fsp150'] = snmpwalk_cache_multi_oid($device, 'cmEntityObjects', [], 'CM-ENTITY-MIB', null, '-OQUbs'); $neType = $pre_cache['adva_fsp150'][1]['neType']; if ($neType == 'ccxg116pro') { $pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetTrafficPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs'); } else { $pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetNetPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs'); $pre_cache['adva_fsp150_ports'] = snmpwalk_cache_multi_oid($device, 'cmEthernetAccPortTable', $pre_cache['adva_fsp150_ports'], 'CM-FACILITY-MIB', null, '-OQUbs'); } Next we are going to build our sensor discovery code. These are optical readings, so the file will be created as the dBm sensor type in includes/discover/sensors/dbm/adva_fsp150.inc.php . Below is a snippet of the code: foreach ($pre_cache['adva_fsp150_ports'] as $index => $entry) { if ($entry['cmEthernetTrafficPortMediaType'] == 'fiber') { //Discover received power level $oidRx = '.1.3.6.1.4.1.2544.1.12.5.1.21.1.34.' . $index . '.3'; $oidTx = '.1.3.6.1.4.1.2544.1.12.5.1.21.1.33.' . $index . '.3'; $currentRx = snmp_get($device, $oidRx, '-Oqv', 'CM-PERFORMANCE-MIB', '/opt/librenms/mibs/adva'); $currentTx = snmp_get($device, $oidTx, '-Oqv', 'CM-PERFORMANCE-MIB', '/opt/librenms/mibs/adva'); if ($currentRx != 0 || $currentTx != 0) { $entPhysicalIndex = $entry['cmEthernetTrafficPortIfIndex']; $entPhysicalIndex_measured = 'ports'; $descrRx = dbFetchCell('SELECT `ifName` FROM `ports` WHERE `ifIndex`= ? AND `device_id` = ?', [$entry['cmEthernetTrafficPortIfIndex'], $device['device_id']]) . ' Rx Power'; discover_sensor( $valid['sensor'], 'dbm', $device, $oidRx, 'cmEthernetTrafficPortStatsOPR.' . $index, 'adva_fsp150', $descrRx, $divisor, $multiplier, null, null, null, null, $currentRx, 'snmp', $entPhysicalIndex, $entPhysicalIndex_measured ); $descrTx = dbFetchCell('SELECT `ifName` FROM `ports` WHERE `ifIndex`= ? AND `device_id` = ?', [$entry['cmEthernetTrafficPortIfIndex'], $device['device_id']]) . ' Tx Power'; discover_sensor( $valid['sensor'], 'dbm', $device, $oidTx, 'cmEthernetTrafficPortStatsOPT.' . $index, 'adva_fsp150', $descrTx, $divisor, $multiplier, null, null, null, null, $currentTx, 'snmp', $entPhysicalIndex, $entPhysicalIndex_measured ); } } } First the program will loop through each port's index value. In the case of Advas, the ports are names Ethernet 1-1-1-1, 1-1-1-2, etc, and they are indexed as oid.1.1.1.1, oid.1.1.1.2, etc in the mib. Next the program checks which table the port exists in and that the connector type is 'fiber'. There are other port tables in the full code that were ommitted from the example for brevity. Copper media won't have optical readings, so if the media type isn't fiber we skip discovery for that port. The next two lines build the OIDs for getting the optical receive and transmit values using the $index for the port. Using the OIDs the program gets the current receive and transmit values ($currentRx and $currentTx repectively) to verify the values are not 0. Not all SFPs collect digital optical monitoring (DOM) data, in the case of Adva the value of both transmit and recieve will be 0 if DOM is not available. While 0 is a valid value for optical power, its extremely unlikely that both will be 0 if DOM is present. If DOM is not available, then the program stops discovery for that port. Note that while this is the case with Adva, other vendors may differ in how they handle optics that do not supply DOM. Please check your vendor's mibs. Next the program assigns the values of $entPhysicalIndex and $entPhysicalIndex_measured. In this case $entPhysicalIndex is set to the value of the cmEthernetTrafficPortIfIndex so that it is associated with port. This will also allow the sensor graphs to show up on the associated port's page in the GUI in addition to the Health page. Following that the program uses a database call to get the description of the port which will be used as the title for the graph in the GUI. Lastly the program calls discover_sensor() and passes the information collected in the previous steps. The null values are for low, low warning, high, and high warning values, which are not collected in the Adva's MIB. You can manually run discovery to verify the code works by running ./discovery.php -h $device_id -m sensors . You can use -v to see what calls are being used during discovery and -d to see debug output. In the output under #### Load disco module sensors #### you can see a list of sensors types. If there is a + a sensor is added, if there is a - one was deleted, and a . means no change. If there is nothing next to the sensor type then the sensor was not discovered. There is is also information about changes to the database and RRD files at the bottom. [librenms@nms-test ~]$ ./discovery.php -h 2 -m sensors LibreNMS Discovery 164.113.194.250 2 adva_fsp150 #### Load disco module core #### >> Runtime for discovery module 'core': 0.0240 seconds with 66536 bytes >> SNMP: [2/0.06s] MySQL: [3/0.00s] RRD: [0/0.00s] #### Unload disco module core #### #### Load disco module sensors #### Pre-cache adva_fsp150: ENTITY-SENSOR: Caching OIDs: entPhysicalDescr entPhysicalName entPhySensorType entPhySensorScale entPhySensorPrecision entPhySensorValue entPhySensorOperStatus Airflow: Current: . Charge: Dbm: Adva FSP-150 dBm.. Fanspeed: Frequency: Humidity: Load: Power: Power_consumed: Power_factor: Runtime: Signal: State: Count: Temperature: .. Tv_signal: Bitrate: Voltage: . Snr: Pressure: Cooling: Delay: Quality_factor: Chromatic_dispersion: Ber: Eer: Waterflow: Percent: >> Runtime for discovery module 'sensors': 3.9340 seconds with 190024 bytes >> SNMP: [16/3.89s] MySQL: [36/0.03s] RRD: [0/0.00s] #### Unload disco module sensors #### Discovered in 5.521 seconds SNMP [18/3.96s]: Get[8/0.81s] Getnext[0/0.00s] Walk[10/3.15s] MySQL [41/0.03s]: Cell[10/0.01s] Row[-4/-0.00s] Rows[31/0.02s] Column[0/0.00s] Update[2/0.00s] Insert[2/0.00s] Delete[0/0.00s] RRD [0/0.00s]: Update[0/0.00s] Create [0/0.00s] Other[0/0.00s]","title":"Advanced health sensor example"},{"location":"Developing/os/Initial-Detection/","text":"This document will provide the information you should need to add basic detection for a new OS. Discovery OS discovery is how LibreNMS detects which OS should be used for a device. Generally detection should use sysObjectID or sysDescr, but you can also snmpget an oid and check for a value. snmpget is discouraged because it slows down all os detections, not just the added os. To begin, create the new OS file which should be called includes/definitions/pulse.yaml . Here is a working example: os : pulse text : 'Pulse Secure' type : firewall icon : pulse over : - { graph : device_bits , text : 'Device Traffic' } - { graph : device_processor , text : 'CPU Usage' } - { graph : device_mempool , text : 'Memory Usage' } discovery : - sysObjectID : - .1.3.6.1.4.1.12532. over : This is a list of the graphs which will be shown within the device header bar (mini graphs top right). discovery : Here we are detecting this new OS using sysObjectID, this is the preferred method for detection. Other options are available: sysObjectID The preferred operator. Checks if the sysObjectID starts with one of the strings under this item sysDescr Use this in addition to sysObjectID if required. Check that the sysDescr contains one of the strings under this item sysObjectID_regex Please avoid use of this. Checks if the sysObjectID matches one of the regex statements under this item sysDescr_regex Please avoid use of this. Checks if the sysDescr matches one of the regex statements under this item snmpget Do not use this unless none of the other methods work. Fetch an oid and compare it against a value. discovery : - snmpget : - oid : - op : <[\"=\",\"!=\",\"==\",\"!==\",\"<=\",\">=\",\"<\",\">\",\"starts\",\"ends\",\"contains\",\"regex\",\"not_starts\",\"not_ends\",\"not_contains\",\"not_regex\",\"in_array\",\"not_in_array\",\"exists\"]> - value : <'string' | boolean> _except You can add this to any of the above to exclude that element. As an example: discovery : - sysObjectID : - .1.3.6.1.4.1.12532. sysDescr_except : - 'Not some pulse' group : You can group certain OS' together by using group, for instance ios, nx-os, iosxr are all within a group called cisco. bad_ifXEntry : This is a list of models for which to tell LibreNMS that the device doesn't support ifXEntry and to ignore it: bad_ifXEntry : - cisco1941 - cisco886Va - cisco2811 mib_dir : You can use this to specify an additional directory to look in for MIBs. An array is not accepted, only one directory may be specified. mib_dir : juniper poller_modules : This is a list of poller modules to either enable (1) or disable (0). Check misc/config_definitions.json to see which modules are enabled/disabled by default. poller_modules : cisco-ace-serverfarms : false cisco-ace-loadbalancer : false discovery_modules : This is the list of discovery modules to either enable (1) or disable (0). Check misc/config_definitions.json to see which modules are enabled/disabled by default. discovery_modules : cisco-cef : true slas : true cisco-mac-accounting : false Discovery Logic YAML is converted to an array in PHP. Consider the following YAML: discovery : - sysObjectID : foo - sysDescr : [ snafu , exodar ] sysObjectID : bar This is how the discovery array would look in PHP: [ [ \"sysObjectID\" => \"foo\" , ], [ \"sysDescr\" => [ \"snafu\" , \"exodar\" , ], \"sysObjectID\" => \"bar\" , ] ] The logic for the discovery is as follows: One of the first level items must match ALL of the second level items must match (sysObjectID, sysDescr) One of the third level items (foo, [snafu,exodar], bar) must match So, considering the example: sysObjectID: foo, sysDescr: ANYTHING matches sysObjectID: bar, sysDescr: ANYTHING does not match sysObjectID: bar, sysDescr: exodar matches sysObjectID: bar, sysDescr: snafu matches OS discovery OS discovery collects additional standardized data about the OS. These are specified in the discovery yaml includes/definitions/discovery/.yaml or LibreNMS/OS/.php if more complex collection is required. version The version of the OS running on the device. hardware The hardware version for the device. For example: 'WS-C3560X-24T-S' features Features for the device, for example a list of enabled software features. serial The main serial number of the device. Yaml based OS discovery sysDescr_regex apply a regex or list of regexes to the sysDescr to extract named groups, this data has the lowest precedence specify an oid or list of oids to attempt to pull the data from, the first non-empty response will be used _regex parse the value out of the returned oid data, must use a named group _template combine multiple oid results together to create a final string value. The result is trimmed. _replace An array of replacements ['search regex', 'replace'] or regex to remove hardware_mib MIB used to translate sysObjectID to get hardware. hardware_regex can process the result. modules : os : sysDescr_regex : '/(?MSM\\S+) .* Serial number (?\\S+) - Firmware version (?\\S+)/' features : UPS-MIB::upsIdentAttachedDevices.0 hardware : - ENTITY-MIB::entPhysicalName.1 - ENTITY-MIB::entPhysicalHardwareRev.1 hardware_template : '{{ ENTITY-MIB::entPhysicalName.1 }} {{ ENTITY-MIB::entPhysicalHardwareRev.1 }}' serial : ENTITY-MIB::entPhysicalSerialNum.1 version : ENTITY-MIB::entPhysicalSoftwareRev.1 version_regex : '/V(?.*)/' PHP based OS discovery public function discoverOS ( \\App\\Models\\Device $device ) : void { $info = snmp_getnext_multi ( $this -> getDeviceArray (), [ 'enclosureModel' , 'enclosureSerialNum' , 'entPhysicalFirmwareRev' ], '-OQUs' , 'NAS-MIB:ENTITY-MIB' ); $device -> version = $info [ 'entPhysicalFirmwareRev' ]; $device -> hardware = $info [ 'enclosureModel' ]; $device -> serial = $info [ 'enclosureSerialNum' ]; } MIBs If the device has MIBs available and you use it in the detection then you can add these in. It is highly recommended that you add mibs to a vendor specific directory. For instance HP mibs are in mibs/hp . Please ensure that these directories are specified in the yaml detection file, see mib_dir above. Icon and Logo It is highly recommended to use SVG images where possible, these scale and provide a nice visual image for users with HiDPI screens. If you can't find SVG images then please use png. Create an SVG image of the icon and logo. Legacy PNG bitmaps are also supported but look bad on HiDPI. A vector image should not contain padding. The file should not be larger than 20 Kb. Simplify paths to reduce large files. Use plain SVG without gzip compression. The SVG root element must not contain length and width attributes, only viewBox. Icon Save the icon SVG to html/images/os/$os.svg . Icons should look good when viewed at 32x32 px. Square icons are preferred to full logos with text. Remove small ornaments that are almost not visible when displayed with 32px width (e.g. \u00ae or \u2122). Logo Save the logo SVG to html/images/logos/$os.svg . Logos can be any dimension, but often are wide and contain the company name. If a logo is not present, the icon will be used. Hints Hints for Inkscape : You can open a PDF or EPS to extract the logo. Ungroup elements to isolate the logo. Use Path -> Simplify to simplify paths of large files. Use File -> Document Properties\u2026 -> Resize page to content\u2026 to remove padding. Use File -> Clean up document to remove unused gradients, patterns, or markers. Use File -> Save As -> Plain SVG to save the final image. By optimizing the SVG you can shrink the file size in some cases to less than 20 %. SVG Optimizer does a great job. There is also an online version . The final check Discovery ./discovery.php -d -h HOSTNAME Polling lnms device:poll HOSTNAME At this step we should see all the values retrieved in LibreNMS. Note: If you have made a number of changes to either the OS's Discovery files, it's possible earlier edits have been cached. As such, if you do not get expected behaviour when completing the final check above, try removing the cache file first: rm -f cache/os_defs.cache","title":"Initial Detection"},{"location":"Developing/os/Initial-Detection/#discovery","text":"OS discovery is how LibreNMS detects which OS should be used for a device. Generally detection should use sysObjectID or sysDescr, but you can also snmpget an oid and check for a value. snmpget is discouraged because it slows down all os detections, not just the added os. To begin, create the new OS file which should be called includes/definitions/pulse.yaml . Here is a working example: os : pulse text : 'Pulse Secure' type : firewall icon : pulse over : - { graph : device_bits , text : 'Device Traffic' } - { graph : device_processor , text : 'CPU Usage' } - { graph : device_mempool , text : 'Memory Usage' } discovery : - sysObjectID : - .1.3.6.1.4.1.12532. over : This is a list of the graphs which will be shown within the device header bar (mini graphs top right). discovery : Here we are detecting this new OS using sysObjectID, this is the preferred method for detection. Other options are available: sysObjectID The preferred operator. Checks if the sysObjectID starts with one of the strings under this item sysDescr Use this in addition to sysObjectID if required. Check that the sysDescr contains one of the strings under this item sysObjectID_regex Please avoid use of this. Checks if the sysObjectID matches one of the regex statements under this item sysDescr_regex Please avoid use of this. Checks if the sysDescr matches one of the regex statements under this item snmpget Do not use this unless none of the other methods work. Fetch an oid and compare it against a value. discovery : - snmpget : - oid : - op : <[\"=\",\"!=\",\"==\",\"!==\",\"<=\",\">=\",\"<\",\">\",\"starts\",\"ends\",\"contains\",\"regex\",\"not_starts\",\"not_ends\",\"not_contains\",\"not_regex\",\"in_array\",\"not_in_array\",\"exists\"]> - value : <'string' | boolean> _except You can add this to any of the above to exclude that element. As an example: discovery : - sysObjectID : - .1.3.6.1.4.1.12532. sysDescr_except : - 'Not some pulse' group : You can group certain OS' together by using group, for instance ios, nx-os, iosxr are all within a group called cisco. bad_ifXEntry : This is a list of models for which to tell LibreNMS that the device doesn't support ifXEntry and to ignore it: bad_ifXEntry : - cisco1941 - cisco886Va - cisco2811 mib_dir : You can use this to specify an additional directory to look in for MIBs. An array is not accepted, only one directory may be specified. mib_dir : juniper poller_modules : This is a list of poller modules to either enable (1) or disable (0). Check misc/config_definitions.json to see which modules are enabled/disabled by default. poller_modules : cisco-ace-serverfarms : false cisco-ace-loadbalancer : false discovery_modules : This is the list of discovery modules to either enable (1) or disable (0). Check misc/config_definitions.json to see which modules are enabled/disabled by default. discovery_modules : cisco-cef : true slas : true cisco-mac-accounting : false","title":"Discovery"},{"location":"Developing/os/Initial-Detection/#discovery-logic","text":"YAML is converted to an array in PHP. Consider the following YAML: discovery : - sysObjectID : foo - sysDescr : [ snafu , exodar ] sysObjectID : bar This is how the discovery array would look in PHP: [ [ \"sysObjectID\" => \"foo\" , ], [ \"sysDescr\" => [ \"snafu\" , \"exodar\" , ], \"sysObjectID\" => \"bar\" , ] ] The logic for the discovery is as follows: One of the first level items must match ALL of the second level items must match (sysObjectID, sysDescr) One of the third level items (foo, [snafu,exodar], bar) must match So, considering the example: sysObjectID: foo, sysDescr: ANYTHING matches sysObjectID: bar, sysDescr: ANYTHING does not match sysObjectID: bar, sysDescr: exodar matches sysObjectID: bar, sysDescr: snafu matches","title":"Discovery Logic"},{"location":"Developing/os/Initial-Detection/#os-discovery","text":"OS discovery collects additional standardized data about the OS. These are specified in the discovery yaml includes/definitions/discovery/.yaml or LibreNMS/OS/.php if more complex collection is required. version The version of the OS running on the device. hardware The hardware version for the device. For example: 'WS-C3560X-24T-S' features Features for the device, for example a list of enabled software features. serial The main serial number of the device.","title":"OS discovery"},{"location":"Developing/os/Initial-Detection/#yaml-based-os-discovery","text":"sysDescr_regex apply a regex or list of regexes to the sysDescr to extract named groups, this data has the lowest precedence specify an oid or list of oids to attempt to pull the data from, the first non-empty response will be used _regex parse the value out of the returned oid data, must use a named group _template combine multiple oid results together to create a final string value. The result is trimmed. _replace An array of replacements ['search regex', 'replace'] or regex to remove hardware_mib MIB used to translate sysObjectID to get hardware. hardware_regex can process the result. modules : os : sysDescr_regex : '/(?MSM\\S+) .* Serial number (?\\S+) - Firmware version (?\\S+)/' features : UPS-MIB::upsIdentAttachedDevices.0 hardware : - ENTITY-MIB::entPhysicalName.1 - ENTITY-MIB::entPhysicalHardwareRev.1 hardware_template : '{{ ENTITY-MIB::entPhysicalName.1 }} {{ ENTITY-MIB::entPhysicalHardwareRev.1 }}' serial : ENTITY-MIB::entPhysicalSerialNum.1 version : ENTITY-MIB::entPhysicalSoftwareRev.1 version_regex : '/V(?.*)/'","title":"Yaml based OS discovery"},{"location":"Developing/os/Initial-Detection/#php-based-os-discovery","text":"public function discoverOS ( \\App\\Models\\Device $device ) : void { $info = snmp_getnext_multi ( $this -> getDeviceArray (), [ 'enclosureModel' , 'enclosureSerialNum' , 'entPhysicalFirmwareRev' ], '-OQUs' , 'NAS-MIB:ENTITY-MIB' ); $device -> version = $info [ 'entPhysicalFirmwareRev' ]; $device -> hardware = $info [ 'enclosureModel' ]; $device -> serial = $info [ 'enclosureSerialNum' ]; }","title":"PHP based OS discovery"},{"location":"Developing/os/Initial-Detection/#mibs","text":"If the device has MIBs available and you use it in the detection then you can add these in. It is highly recommended that you add mibs to a vendor specific directory. For instance HP mibs are in mibs/hp . Please ensure that these directories are specified in the yaml detection file, see mib_dir above.","title":"MIBs"},{"location":"Developing/os/Initial-Detection/#icon-and-logo","text":"It is highly recommended to use SVG images where possible, these scale and provide a nice visual image for users with HiDPI screens. If you can't find SVG images then please use png. Create an SVG image of the icon and logo. Legacy PNG bitmaps are also supported but look bad on HiDPI. A vector image should not contain padding. The file should not be larger than 20 Kb. Simplify paths to reduce large files. Use plain SVG without gzip compression. The SVG root element must not contain length and width attributes, only viewBox.","title":"Icon and Logo"},{"location":"Developing/os/Initial-Detection/#icon","text":"Save the icon SVG to html/images/os/$os.svg . Icons should look good when viewed at 32x32 px. Square icons are preferred to full logos with text. Remove small ornaments that are almost not visible when displayed with 32px width (e.g. \u00ae or \u2122).","title":"Icon"},{"location":"Developing/os/Initial-Detection/#logo","text":"Save the logo SVG to html/images/logos/$os.svg . Logos can be any dimension, but often are wide and contain the company name. If a logo is not present, the icon will be used.","title":"Logo"},{"location":"Developing/os/Initial-Detection/#hints","text":"Hints for Inkscape : You can open a PDF or EPS to extract the logo. Ungroup elements to isolate the logo. Use Path -> Simplify to simplify paths of large files. Use File -> Document Properties\u2026 -> Resize page to content\u2026 to remove padding. Use File -> Clean up document to remove unused gradients, patterns, or markers. Use File -> Save As -> Plain SVG to save the final image. By optimizing the SVG you can shrink the file size in some cases to less than 20 %. SVG Optimizer does a great job. There is also an online version .","title":"Hints"},{"location":"Developing/os/Initial-Detection/#the-final-check","text":"Discovery ./discovery.php -d -h HOSTNAME Polling lnms device:poll HOSTNAME At this step we should see all the values retrieved in LibreNMS. Note: If you have made a number of changes to either the OS's Discovery files, it's possible earlier edits have been cached. As such, if you do not get expected behaviour when completing the final check above, try removing the cache file first: rm -f cache/os_defs.cache","title":"The final check"},{"location":"Developing/os/Mem-CPU-Information/","text":"This document will guide you through adding detection for Memory / Processor for your new device. Memory LibreNMS will attempt to detect memory statistics using the standard HOST-RESOURCES-MIB and UCD-SNMP-MIB MIBs. To detect non-standard MIBs, they can be defined via Yaml. YAML In order to successfully detect memory amount and usage, two of the for keys below are required. Some OS only provide a usage percentage, which will work, but a total RAM amount will not be displayed. total used free percent_used includes/definitions/discovery/mempools/arubaos.yaml mempools : data : - total : WLSX-SWITCH-MIB::sysXMemorySize used : WLSX-SWITCH-MIB::sysXMemoryUsed precision : 1024 The code can also interpret table based OIDs and supports many of the same features as Health Sensors including {{ }} parsing, skip_values, and precache. Valid data entry keys: oid oid to walk to collect processor data total oid or integer total memory size in bytes (or precision) used oid memory used in bytes (or precision) free oid memory free in bytes (or precision) percent_used oid of percentage of used memory descr A visible description of the memory measurement defaults to \"Memory\" warn_percent Usage percentage to used for alert purposes precision precision for all byte values, typically a power of 2 (1024 for example) class used to generate rrd filename, defaults to system. If system, buffers, and cached exist they will be combined to calculate available memory. type used to generate rrd filename, defaults to the os name index used to generate rrd filename, defaults to the oid index skip_values skip values see Health Sensors for specification snmp_flags additional net-snmp flags Custom Processor Discovery and Polling If you need to implement custom discovery or polling you can implement the MempoolsDiscovery interface and the MempoolsPolling interface in the OS class. MempoolsPolling is optional, standard polling will be used based on OIDs stored in the database. OS Class files reside under LibreNMS\\OS php namespace LibreNMS\\OS ; use LibreNMS\\Interfaces\\Discovery\\MempoolsDiscovery ; use LibreNMS\\Interfaces\\Polling\\MempoolsPolling ; class Example extends \\LibreNMS\\OS implements MempoolsDiscovery , MempoolsPolling { /** * Discover a Collection of Mempool models. * Will be keyed by mempool_type and mempool_index * * @return \\Illuminate\\Support\\Collection \\App\\Models\\Mempool */ public function discoverMempools () { // TODO: Implement discoverMempools() method. } /** * @param \\Illuminate\\Support\\Collection $mempools \\App\\Models\\Mempool * @return \\Illuminate\\Support\\Collection \\App\\Models\\Mempool */ public function pollMempools ( $mempools ) { // TODO: Implement pollMempools() method. } } Processor Detection for processors is done via a yaml file unless custom processing of data is required. YAML includes/definitions/discovery/pulse.yaml mib : PULSESECURE-PSG-MIB modules : processors : data : - oid : iveCpuUtil num_oid : '.1.3.6.1.4.1.12532.10.{{ $index }}' type : pulse Available yaml data keys: Key Default Description oid required The string based oid to fetch data, could be a table or a single value num_oid optional The numerical oid to fetch data from when polling, usually should be appended by {{ $index }}. Computed by discovery process if not provided. value optional Oid to retrieve data from, primarily used for tables precision 1 The multiplier to multiply the data by. If this is negative, the data will be multiplied then subtracted from 100. descr Processor Description of this processor, may be an oid or plain string. Helpful values {{ $index }} and {{$count}} type Name of this sensor. This is used with the index to generate a unique id for this sensor. index {{ $index }} The index of this sensor, defaults to the index of the oid. skip_values optional Do not detect this sensor if the value matches Accessing values within yaml: {{ $index }} The index after the given oid {{ $count }} The count of entries (starting with 1) {{ $ oid }} Any oid in the table or pre-fetched Custom Processor Discovery and Polling If you need to implement custom discovery or polling you can implement the ProcessorDiscovery interface and the ProcessorPolling interface in the OS class. OS Class files reside under LibreNMS\\OS php namespace LibreNMS\\OS ; use LibreNMS\\Device\\Processor ; use LibreNMS\\Interfaces\\Discovery\\ProcessorDiscovery ; use LibreNMS\\Interfaces\\Polling\\ProcessorPolling ; use LibreNMS\\OS ; class ExampleOS extends OS implements ProcessorDiscovery , ProcessorPolling { /** * Discover processors. * Returns an array of LibreNMS\\Device\\Processor objects that have been discovered * * @return array Processors */ public function discoverProcessors () { // discovery code here } /** * Poll processor data. This can be implemented if custom polling is needed. * * @param array $processors Array of processor entries from the database that need to be polled * @return array of polled data */ public function pollProcessors ( array $processors ) { // polling code here } }","title":"Mem/CPU Information"},{"location":"Developing/os/Mem-CPU-Information/#memory","text":"LibreNMS will attempt to detect memory statistics using the standard HOST-RESOURCES-MIB and UCD-SNMP-MIB MIBs. To detect non-standard MIBs, they can be defined via Yaml.","title":"Memory"},{"location":"Developing/os/Mem-CPU-Information/#yaml","text":"In order to successfully detect memory amount and usage, two of the for keys below are required. Some OS only provide a usage percentage, which will work, but a total RAM amount will not be displayed. total used free percent_used includes/definitions/discovery/mempools/arubaos.yaml mempools : data : - total : WLSX-SWITCH-MIB::sysXMemorySize used : WLSX-SWITCH-MIB::sysXMemoryUsed precision : 1024 The code can also interpret table based OIDs and supports many of the same features as Health Sensors including {{ }} parsing, skip_values, and precache. Valid data entry keys: oid oid to walk to collect processor data total oid or integer total memory size in bytes (or precision) used oid memory used in bytes (or precision) free oid memory free in bytes (or precision) percent_used oid of percentage of used memory descr A visible description of the memory measurement defaults to \"Memory\" warn_percent Usage percentage to used for alert purposes precision precision for all byte values, typically a power of 2 (1024 for example) class used to generate rrd filename, defaults to system. If system, buffers, and cached exist they will be combined to calculate available memory. type used to generate rrd filename, defaults to the os name index used to generate rrd filename, defaults to the oid index skip_values skip values see Health Sensors for specification snmp_flags additional net-snmp flags","title":"YAML"},{"location":"Developing/os/Mem-CPU-Information/#custom-processor-discovery-and-polling","text":"If you need to implement custom discovery or polling you can implement the MempoolsDiscovery interface and the MempoolsPolling interface in the OS class. MempoolsPolling is optional, standard polling will be used based on OIDs stored in the database. OS Class files reside under LibreNMS\\OS php namespace LibreNMS\\OS ; use LibreNMS\\Interfaces\\Discovery\\MempoolsDiscovery ; use LibreNMS\\Interfaces\\Polling\\MempoolsPolling ; class Example extends \\LibreNMS\\OS implements MempoolsDiscovery , MempoolsPolling { /** * Discover a Collection of Mempool models. * Will be keyed by mempool_type and mempool_index * * @return \\Illuminate\\Support\\Collection \\App\\Models\\Mempool */ public function discoverMempools () { // TODO: Implement discoverMempools() method. } /** * @param \\Illuminate\\Support\\Collection $mempools \\App\\Models\\Mempool * @return \\Illuminate\\Support\\Collection \\App\\Models\\Mempool */ public function pollMempools ( $mempools ) { // TODO: Implement pollMempools() method. } }","title":"Custom Processor Discovery and Polling"},{"location":"Developing/os/Mem-CPU-Information/#processor","text":"Detection for processors is done via a yaml file unless custom processing of data is required.","title":"Processor"},{"location":"Developing/os/Mem-CPU-Information/#yaml_1","text":"includes/definitions/discovery/pulse.yaml mib : PULSESECURE-PSG-MIB modules : processors : data : - oid : iveCpuUtil num_oid : '.1.3.6.1.4.1.12532.10.{{ $index }}' type : pulse Available yaml data keys: Key Default Description oid required The string based oid to fetch data, could be a table or a single value num_oid optional The numerical oid to fetch data from when polling, usually should be appended by {{ $index }}. Computed by discovery process if not provided. value optional Oid to retrieve data from, primarily used for tables precision 1 The multiplier to multiply the data by. If this is negative, the data will be multiplied then subtracted from 100. descr Processor Description of this processor, may be an oid or plain string. Helpful values {{ $index }} and {{$count}} type Name of this sensor. This is used with the index to generate a unique id for this sensor. index {{ $index }} The index of this sensor, defaults to the index of the oid. skip_values optional Do not detect this sensor if the value matches Accessing values within yaml: {{ $index }} The index after the given oid {{ $count }} The count of entries (starting with 1) {{ $ oid }} Any oid in the table or pre-fetched","title":"YAML"},{"location":"Developing/os/Mem-CPU-Information/#custom-processor-discovery-and-polling_1","text":"If you need to implement custom discovery or polling you can implement the ProcessorDiscovery interface and the ProcessorPolling interface in the OS class. OS Class files reside under LibreNMS\\OS php namespace LibreNMS\\OS ; use LibreNMS\\Device\\Processor ; use LibreNMS\\Interfaces\\Discovery\\ProcessorDiscovery ; use LibreNMS\\Interfaces\\Polling\\ProcessorPolling ; use LibreNMS\\OS ; class ExampleOS extends OS implements ProcessorDiscovery , ProcessorPolling { /** * Discover processors. * Returns an array of LibreNMS\\Device\\Processor objects that have been discovered * * @return array Processors */ public function discoverProcessors () { // discovery code here } /** * Poll processor data. This can be implemented if custom polling is needed. * * @param array $processors Array of processor entries from the database that need to be polled * @return array of polled data */ public function pollProcessors ( array $processors ) { // polling code here } }","title":"Custom Processor Discovery and Polling"},{"location":"Developing/os/Settings/","text":"Optional OS Settings This page documents settings that can be set in the os yaml files or in config.php. All settings listed here are optional. If they are not set, the global default will be used. User override in config.php Users can override these settings in their config.php. For example, to set an alternate icon for ios: $config [ 'os' ][ 'ios' ][ 'icon' ] = 'fuzzybunny' ; Ignoring Sensors It is possible to filter some sensors from the configuration: Filter all 'current' sensors for Operating System 'vrp'. $config [ 'os' ][ 'vrp' ][ 'disabled_sensors' ][ 'current' ] = true ; Filter all sensors with description matching regexp '/PEM Iout/' for Operating System iosxe. $config [ 'os' ][ 'iosxe' ][ 'disabled_sensors_regex' ][] = '/PEM Iout/' ; Filter all 'power' sensors with description matching regexp '/ Power [TR]x /' for Operating System iosxr. $config [ 'os' ][ 'iosxr' ][ 'disabled_sensors_regex' ][ 'power' ][] = '/ Power [TR]x /' ; Ignore all temperature sensors $config [ 'disabled_sensors' ][ 'temperature' ] = true ; Filter all sensors matching with description regexp '/PEM Iout/' . $config [ 'disabled_sensors_regex' ][] = '/PEM Iout/' ; Ignoring Interfaces See also: Global Ignoring Interfaces Config These settings are merged with the global settings, so you can only undo global ones with good_if empty_ifdescr : false # allow empty ifDescr bad_if : # ifDescr (substring, case insensitive) - lp0 bad_if_regexp : # ifDescr (regex, case insensitive) - \"/^ng[0-9]+$/\" bad_ifname_regexp : # ifName (regex, case insensitive) - \"/^xdsl_channel /\" bad_ifalias_regexp : # ifAlias (regex, case insensitive) - \"/^vlan/\" bad_iftype : # ifType (substring) - sonet good_if : # ignore all other bad_if settings ifDescr (substring, case insensitive) - virtual bad_ifoperstatus # IfOperStatus (substring, case insensitive) - notPresent Controlling interface labels By default we use ifDescr to label ports/interfaces. Setting either ifname or ifalias will override that. Only set one of these. ifAlias is user supplied. ifindex will append the ifindex to the port label. ifname : true ifalias : true ifindex : true Poller and Discovery Modules The various discovery and poller modules can be enabled or disabled per OS. The defaults are usually reasonable, so likely you won't want to change more than a few. These modules can be enabled or disabled per-device in the webui and per os or globally in config.php. Usually, a poller module will not work if it's corresponding discovery module is not enabled. You should avoid setting these to false in the OS definitions unless it has a significant negative impact on polling. Setting modules in the definition reduces user control of modules. poller_modules : bgp-peers : true discovery_modules : arp-table : false SNMP Settings Disable snmpbulkwalk Some devices have buggy snmp implementations and don't respond well to the more efficient snmpbulkwalk. To disable snmpbulkwalk and only use snmpwalk for an OS set the following. snmp_bulk : false If only some specific OIDs fail with snmpbulkwalk. You can disable just those OIDs. This needs to match exactly the OID being walked by LibreNMS. MIB::oid is preferred to prevent name collisions. oids : no_bulk : - UCD-SNMP-MIB::laLoadInt Limit the oids per snmpget snmp_max_oid : 8 Storage Settings See also: Global Storage Config ignore_mount_array : # exact match - /var/run ignore_mount_string : # substring - run ignore_mount_regexp : # regex - \"/^ \\ /var/\"","title":"Settings"},{"location":"Developing/os/Settings/#optional-os-settings","text":"This page documents settings that can be set in the os yaml files or in config.php. All settings listed here are optional. If they are not set, the global default will be used.","title":"Optional OS Settings"},{"location":"Developing/os/Settings/#user-override-in-configphp","text":"Users can override these settings in their config.php. For example, to set an alternate icon for ios: $config [ 'os' ][ 'ios' ][ 'icon' ] = 'fuzzybunny' ;","title":"User override in config.php"},{"location":"Developing/os/Settings/#ignoring-sensors","text":"It is possible to filter some sensors from the configuration: Filter all 'current' sensors for Operating System 'vrp'. $config [ 'os' ][ 'vrp' ][ 'disabled_sensors' ][ 'current' ] = true ; Filter all sensors with description matching regexp '/PEM Iout/' for Operating System iosxe. $config [ 'os' ][ 'iosxe' ][ 'disabled_sensors_regex' ][] = '/PEM Iout/' ; Filter all 'power' sensors with description matching regexp '/ Power [TR]x /' for Operating System iosxr. $config [ 'os' ][ 'iosxr' ][ 'disabled_sensors_regex' ][ 'power' ][] = '/ Power [TR]x /' ; Ignore all temperature sensors $config [ 'disabled_sensors' ][ 'temperature' ] = true ; Filter all sensors matching with description regexp '/PEM Iout/' . $config [ 'disabled_sensors_regex' ][] = '/PEM Iout/' ;","title":"Ignoring Sensors"},{"location":"Developing/os/Settings/#ignoring-interfaces","text":"See also: Global Ignoring Interfaces Config These settings are merged with the global settings, so you can only undo global ones with good_if empty_ifdescr : false # allow empty ifDescr bad_if : # ifDescr (substring, case insensitive) - lp0 bad_if_regexp : # ifDescr (regex, case insensitive) - \"/^ng[0-9]+$/\" bad_ifname_regexp : # ifName (regex, case insensitive) - \"/^xdsl_channel /\" bad_ifalias_regexp : # ifAlias (regex, case insensitive) - \"/^vlan/\" bad_iftype : # ifType (substring) - sonet good_if : # ignore all other bad_if settings ifDescr (substring, case insensitive) - virtual bad_ifoperstatus # IfOperStatus (substring, case insensitive) - notPresent","title":"Ignoring Interfaces"},{"location":"Developing/os/Settings/#controlling-interface-labels","text":"By default we use ifDescr to label ports/interfaces. Setting either ifname or ifalias will override that. Only set one of these. ifAlias is user supplied. ifindex will append the ifindex to the port label. ifname : true ifalias : true ifindex : true","title":"Controlling interface labels"},{"location":"Developing/os/Settings/#poller-and-discovery-modules","text":"The various discovery and poller modules can be enabled or disabled per OS. The defaults are usually reasonable, so likely you won't want to change more than a few. These modules can be enabled or disabled per-device in the webui and per os or globally in config.php. Usually, a poller module will not work if it's corresponding discovery module is not enabled. You should avoid setting these to false in the OS definitions unless it has a significant negative impact on polling. Setting modules in the definition reduces user control of modules. poller_modules : bgp-peers : true discovery_modules : arp-table : false","title":"Poller and Discovery Modules"},{"location":"Developing/os/Settings/#snmp-settings","text":"","title":"SNMP Settings"},{"location":"Developing/os/Settings/#disable-snmpbulkwalk","text":"Some devices have buggy snmp implementations and don't respond well to the more efficient snmpbulkwalk. To disable snmpbulkwalk and only use snmpwalk for an OS set the following. snmp_bulk : false If only some specific OIDs fail with snmpbulkwalk. You can disable just those OIDs. This needs to match exactly the OID being walked by LibreNMS. MIB::oid is preferred to prevent name collisions. oids : no_bulk : - UCD-SNMP-MIB::laLoadInt","title":"Disable snmpbulkwalk"},{"location":"Developing/os/Settings/#limit-the-oids-per-snmpget","text":"snmp_max_oid : 8","title":"Limit the oids per snmpget"},{"location":"Developing/os/Settings/#storage-settings","text":"See also: Global Storage Config ignore_mount_array : # exact match - /var/run ignore_mount_string : # substring - run ignore_mount_regexp : # regex - \"/^ \\ /var/\"","title":"Storage Settings"},{"location":"Developing/os/Test-Units/","text":"Tests Tests ensure LibreNMS works as expected, now and in the future. New OS should provide as much test data as needed and added test data for existing OS is welcome. Saved snmp data can be found in tests/snmpsim/*.snmprec and saved database data can be found in tests/data/*.json . Please review this for any sensitive data before submitting. When replacing data, make sure it is modified in a consistent manner. We utilise snmpsim to do unit testing. For OS discovery, we can mock snmpsim, but for other tests you will need it installed and functioning. We run snmpsim during our integration tests, but not by default when running lnms dev:check . You can install snmpsim with the command pip3 install snmpsim . Capturing test data If test data already exists If test data already exists, but is for a different device/configuration with the same OS. Then you should use the --variant (-v) option to specify a different variant of the OS, this will be tested completely separate from other variants. If there is only one variant, please do not specify one. 1. Collect SNMP data ./scripts/collect-snmp-data.php is provided to make it easy to collect data for tests. Running collect-snmp-data.php with the --hostname (-h) allows you to capture all data used to discover and poll a device already added to LibreNMS. Make sure to re-run the script if you add additional support. Check the command-line help for more options. 2. Save test data After you have collected snmp data, run ./scripts/save-test-data.php with the --os (-o) option to dump the post discovery and post poll database entries to json files. This step requires snmpsim, if you are having issues, the maintainers may help you generate it from the snmprec you created in the previous step. Generally, you will only need to collect data once. After you have the data you need in the snmprec file, you can just use save-test-data.php to update the database dump (json) after that. Running tests Note: To run tests, ensure you have executed ./scripts/composer_wrapper.php install from your LibreNMS root directory. This will read composer.json and install any dependencies required. After you have saved your test data, you should run lnms dev:check verify they pass. To run the full suite of tests enable database and snmpsim reliant tests: lnms dev:check unit --db --snmpsim Specific OS lnms dev:check unit -o osname Specific Module lnms dev:check unit -m modulename Using snmpsim for testing You can run snmpsim to access test data by running lnms dev:simulate You may then run snmp queries against it using the os (and variant) as the community and 127.1.6.1:1161 as the host. snmpget -v 2c -c ios_c3560e 127 .1.6.1:1161 sysDescr.0 Snmprec format Snmprec files are simple files that store the snmp data. The data format is simple with three columns: numeric oid, type code, and data. Here is an example snippet. 1.3.6.1.2.1.1.1.0|4|Pulse Secure,LLC,MAG-2600,8.0R14 (build 41869) 1.3.6.1.2.1.1.2.0|6|1.3.6.1.4.1.12532.254.1.1 During testing LibreNMS will use any info in the snmprec file for snmp calls. This one provides sysDescr ( .1.3.6.1.2.1.1.1.0 , 4 = Octet String) and sysObjectID ( .1.3.6.1.2.1.1.2.0 , 6 = Object Identifier), which is the minimum that should be provided for new snmprec files. To look up the numeric OID and type of an string OID with snmptranslate: snmptranslate -On -Td SNMPv2-MIB::sysDescr.0 List of SNMP data types: Type Value OCTET STRING 4 HEX STRING 4x Integer32 2 NULL 5 OBJECT IDENTIFIER 6 IpAddress 64 Counter32 65 Gauge32 66 TimeTicks 67 Opaque 68 Counter64 70 Hex encoded strings (4x) should be used for any strings that contain line returns. New discovery/poller modules New discovery or poller modules should define database capture parameters in /tests/module_tables.yaml . Example workflow If the base os ( .snmprec) already contains test data for the module you are testing or that data conflicts with your new data, you must use a variant to store your test data (-v). Add initial detection Add device to LibreNMS. It is generic and device_id = 42 Run ./scripts/collect-snmp-data.php -h 42 , initial snmprec will be created Add initial detection for example-os Run discovery to make sure it detects properly ./discovery.php -h 42 Add any additional os items like version, hardware, features, or serial. If there is additional snmp data required, run ./scripts/collect-snmp-data.php -h 42 Run ./scripts/save-test-data.php -o example-os to update the dumped database data. Review data. If you modified the snmprec or code (don't modify json manually) run ./scripts/save-test-data.php -o example-os -m os Run lnms dev:check unit --db --snmpsim If the tests succeed submit a pull request Additional module support or test data Add code to support module or support already exists. ./scripts/collect-snmp-data.php -h 42 -m , this will add more data to the snmprec file Review data. If you modified the snmprec (don't modify json manually) run ./scripts/save-test-data.php -o example-os -m Run lnms dev:check unit --db --snmpsim If the tests succeed submit a pull request JSON Application Test Writing Using ./scripts/json-app-tool.php First you will need a good example JSON output produced via SNMP extend in question. Read the help via ./scripts/json-app-tool.php -h . Generate the SNMPrec data via ./scripts/json-app-tool.php -a appName -s > ./tests/snmpsim/linux_appName-v1.snmprec . If the SNMP extend name OID different than the application name, then you will need to pass the -S flag for over riding that. Generate the test JSON data via ./scripts/json-app-tool.php -a appName -t > ./tests/data/linux_appName-v1.json . Update the generated './tests/data/linux_appName-v1.json' making sure that all the expected metrics are present. This assumes that everything under .data in the JSON will be collapsed and used. During test runs if it does not appear to be detecting the app and it has a different app name and SNMP extend name OID, make sure that -S is set properly and that 'includes/discovery/applications.inc.php' has been updated.","title":"Test Units"},{"location":"Developing/os/Test-Units/#tests","text":"Tests ensure LibreNMS works as expected, now and in the future. New OS should provide as much test data as needed and added test data for existing OS is welcome. Saved snmp data can be found in tests/snmpsim/*.snmprec and saved database data can be found in tests/data/*.json . Please review this for any sensitive data before submitting. When replacing data, make sure it is modified in a consistent manner. We utilise snmpsim to do unit testing. For OS discovery, we can mock snmpsim, but for other tests you will need it installed and functioning. We run snmpsim during our integration tests, but not by default when running lnms dev:check . You can install snmpsim with the command pip3 install snmpsim .","title":"Tests"},{"location":"Developing/os/Test-Units/#capturing-test-data","text":"If test data already exists If test data already exists, but is for a different device/configuration with the same OS. Then you should use the --variant (-v) option to specify a different variant of the OS, this will be tested completely separate from other variants. If there is only one variant, please do not specify one.","title":"Capturing test data"},{"location":"Developing/os/Test-Units/#1-collect-snmp-data","text":"./scripts/collect-snmp-data.php is provided to make it easy to collect data for tests. Running collect-snmp-data.php with the --hostname (-h) allows you to capture all data used to discover and poll a device already added to LibreNMS. Make sure to re-run the script if you add additional support. Check the command-line help for more options.","title":"1. Collect SNMP data"},{"location":"Developing/os/Test-Units/#2-save-test-data","text":"After you have collected snmp data, run ./scripts/save-test-data.php with the --os (-o) option to dump the post discovery and post poll database entries to json files. This step requires snmpsim, if you are having issues, the maintainers may help you generate it from the snmprec you created in the previous step. Generally, you will only need to collect data once. After you have the data you need in the snmprec file, you can just use save-test-data.php to update the database dump (json) after that.","title":"2. Save test data"},{"location":"Developing/os/Test-Units/#running-tests","text":"Note: To run tests, ensure you have executed ./scripts/composer_wrapper.php install from your LibreNMS root directory. This will read composer.json and install any dependencies required. After you have saved your test data, you should run lnms dev:check verify they pass. To run the full suite of tests enable database and snmpsim reliant tests: lnms dev:check unit --db --snmpsim","title":"Running tests"},{"location":"Developing/os/Test-Units/#specific-os","text":"lnms dev:check unit -o osname","title":"Specific OS"},{"location":"Developing/os/Test-Units/#specific-module","text":"lnms dev:check unit -m modulename","title":"Specific Module"},{"location":"Developing/os/Test-Units/#using-snmpsim-for-testing","text":"You can run snmpsim to access test data by running lnms dev:simulate You may then run snmp queries against it using the os (and variant) as the community and 127.1.6.1:1161 as the host. snmpget -v 2c -c ios_c3560e 127 .1.6.1:1161 sysDescr.0","title":"Using snmpsim for testing"},{"location":"Developing/os/Test-Units/#snmprec-format","text":"Snmprec files are simple files that store the snmp data. The data format is simple with three columns: numeric oid, type code, and data. Here is an example snippet. 1.3.6.1.2.1.1.1.0|4|Pulse Secure,LLC,MAG-2600,8.0R14 (build 41869) 1.3.6.1.2.1.1.2.0|6|1.3.6.1.4.1.12532.254.1.1 During testing LibreNMS will use any info in the snmprec file for snmp calls. This one provides sysDescr ( .1.3.6.1.2.1.1.1.0 , 4 = Octet String) and sysObjectID ( .1.3.6.1.2.1.1.2.0 , 6 = Object Identifier), which is the minimum that should be provided for new snmprec files. To look up the numeric OID and type of an string OID with snmptranslate: snmptranslate -On -Td SNMPv2-MIB::sysDescr.0 List of SNMP data types: Type Value OCTET STRING 4 HEX STRING 4x Integer32 2 NULL 5 OBJECT IDENTIFIER 6 IpAddress 64 Counter32 65 Gauge32 66 TimeTicks 67 Opaque 68 Counter64 70 Hex encoded strings (4x) should be used for any strings that contain line returns.","title":"Snmprec format"},{"location":"Developing/os/Test-Units/#new-discoverypoller-modules","text":"New discovery or poller modules should define database capture parameters in /tests/module_tables.yaml .","title":"New discovery/poller modules"},{"location":"Developing/os/Test-Units/#example-workflow","text":"If the base os ( .snmprec) already contains test data for the module you are testing or that data conflicts with your new data, you must use a variant to store your test data (-v).","title":"Example workflow"},{"location":"Developing/os/Test-Units/#add-initial-detection","text":"Add device to LibreNMS. It is generic and device_id = 42 Run ./scripts/collect-snmp-data.php -h 42 , initial snmprec will be created Add initial detection for example-os Run discovery to make sure it detects properly ./discovery.php -h 42 Add any additional os items like version, hardware, features, or serial. If there is additional snmp data required, run ./scripts/collect-snmp-data.php -h 42 Run ./scripts/save-test-data.php -o example-os to update the dumped database data. Review data. If you modified the snmprec or code (don't modify json manually) run ./scripts/save-test-data.php -o example-os -m os Run lnms dev:check unit --db --snmpsim If the tests succeed submit a pull request","title":"Add initial detection"},{"location":"Developing/os/Test-Units/#additional-module-support-or-test-data","text":"Add code to support module or support already exists. ./scripts/collect-snmp-data.php -h 42 -m , this will add more data to the snmprec file Review data. If you modified the snmprec (don't modify json manually) run ./scripts/save-test-data.php -o example-os -m Run lnms dev:check unit --db --snmpsim If the tests succeed submit a pull request","title":"Additional module support or test data"},{"location":"Developing/os/Test-Units/#json-application-test-writing-using-scriptsjson-app-toolphp","text":"First you will need a good example JSON output produced via SNMP extend in question. Read the help via ./scripts/json-app-tool.php -h . Generate the SNMPrec data via ./scripts/json-app-tool.php -a appName -s > ./tests/snmpsim/linux_appName-v1.snmprec . If the SNMP extend name OID different than the application name, then you will need to pass the -S flag for over riding that. Generate the test JSON data via ./scripts/json-app-tool.php -a appName -t > ./tests/data/linux_appName-v1.json . Update the generated './tests/data/linux_appName-v1.json' making sure that all the expected metrics are present. This assumes that everything under .data in the JSON will be collapsed and used. During test runs if it does not appear to be detecting the app and it has a different app name and SNMP extend name OID, make sure that -S is set properly and that 'includes/discovery/applications.inc.php' has been updated.","title":"JSON Application Test Writing Using ./scripts/json-app-tool.php"},{"location":"Developing/os/Wireless-Sensors/","text":"This document will guide you through adding wireless sensors for your new wireless device. Currently we have support for the following wireless metrics along with the values we expect to see the data in: Type Measurement Interface Description ap-count % WirelessApCountDiscovery The number of APs attached to this controller capacity % WirelessCapacityDiscovery The % of operating rate vs theoretical max ccq % WirelessCcqDiscovery The Client Connection Quality channel count WirelessChannelDiscovery The channel, use of frequency is preferred cell count WirelessCellDiscovery The cell in a multicell technology clients count WirelessClientsDiscovery The number of clients connected to/managed by this device distance km WirelessDistanceDiscovery The distance of a radio link in Kilometers error-rate bps WirelessErrorRateDiscovery The rate of errored packets or bits, etc error-ratio % WirelessErrorRatioDiscovery The percent of errored packets or bits, etc errors count WirelessErrorsDiscovery The total bits of errored packets or bits, etc frequency MHz WirelessFrequencyDiscovery The frequency of the radio in MHz, channels can be converted mse dB WirelessMseDiscovery The Mean Square Error noise-floor dBm WirelessNoiseFloorDiscovery The amount of noise received by the radio power dBm WirelessPowerDiscovery The power of transmit or receive, including signal level quality % WirelessQualityDiscovery The % of quality of the link, 100% = perfect link rate bps WirelessRateDiscovery The negotiated rate of the connection (not data transfer) rssi dBm WirelessRssiDiscovery The Received Signal Strength Indicator snr dB WirelessSnrDiscovery The Signal to Noise ratio, which is signal - noise floor sinr dB WirelessSinrDiscovery The Signal-to-Interference-plus-Noise Ratio rsrq dB WirelessRsrqDiscovery The Reference Signal Received Quality rsrp dBm WirelessRsrpDiscovery The Reference Signals Received Power xpi dBm WirelessXpiDiscovery The Cross Polar Interference values ssr dB WirelessSsrDiscovery The Signal strength ratio, the ratio(or difference) of Vertical rx power to Horizontal rx power utilization % WirelessUtilizationDiscovery The % of utilization compared to the current rate You will need to create a new OS class for your os if one doesn't exist under LibreNMS/OS . The name of this file should be the os name in camel case for example airos -> Airos , ios-wlc -> IosWlc . Your new OS class should extend LibreNMS\\OS and implement the interfaces for the sensors your os supports. namespace LibreNMS\\OS ; use LibreNMS\\Device\\WirelessSensor ; use LibreNMS\\Interfaces\\Discovery\\Sensors\\WirelessClientsDiscovery ; use LibreNMS\\OS ; class Airos extends OS implements WirelessClientsDiscovery { public function discoverWirelessClients () { $oid = '.1.3.6.1.4.1.41112.1.4.5.1.15.1' ; //UBNT-AirMAX-MIB::ubntWlStatStaCount.1 return array ( new WirelessSensor ( 'clients' , $this -> getDeviceId (), $oid , 'airos' , 1 , 'Clients' ) ); } } All discovery interfaces will require you to return an array of WirelessSensor objects. new WirelessSensor() Accepts the following arguments: $type = Required. This is the sensor class from the table above (i.e humidity). $device_id = Required. You can get this value with $this->getDeviceId() $oids = Required. This must be the numerical OID for where the data can be found, i.e .1.2.3.4.5.6.7.0. If this is an array of oids, you should probably specify an $aggregator. $subtype = Required. This should be the OS name, i.e airos. $index = Required. This must be unique for this sensor type, device and subtype. Typically it's the index from the table being walked or it could be the name of the OID if it's a single value. $description = Required. This is a descriptive value for the sensor. Shown to the user, if this is a per-ssid statistic, using SSID: $ssid here is appropriate $current = Defaults to null. Can be used to set the current value on discovery. If this is null the values will be polled right away and if they do not return valid value(s), the sensor will not be discovered. Supplying a value here implies you have already verified this sensor is valid. $multiplier = Defaults to 1. This is used to multiply the returned value. $divisor = Defaults to 1. This is used to divided the returned value. $aggregator = Defaults to sum. Valid values: sum, avg. This will combine multiple values from multiple oids into one. $access_point_id = Defaults to null. If this is a wireless controller, you can link sensors to entries in the access_points table. $high_limit = Defaults to null. Sets the high limit for the sensor, used in alerting to report out range sensors. $low_limit = Defaults to null. Sets the low threshold limit for the sensor, used in alerting to report out range sensors. $high_warn = Defaults to null. Sets the high warning limit for the sensor, used in alerting to report near out of range sensors. $low_warn = Defaults to null. Sets the low warning limit for the sensor, used in alerting to report near out of range sensors. $entPhysicalIndex = Defaults to null. Sets the entPhysicalIndex to be used to look up further hardware if available. $entPhysicalIndexMeasured = Defaults to null. Sets the type of entPhysicalIndex used, i.e ports. Polling is done automatically based on the discovered data. If for some reason you need to override polling, you can implement the required polling interface in LibreNMS/Interfaces/Polling/Sensors . Using the polling interfaces should be avoided if possible. Graphing is performed automatically for wireless sensors, no custom graphing is required or supported.","title":"Wireless Sensors"},{"location":"Extensions/Agent-Setup/","text":"Check_MK Setup The agent can be used to gather data from remote systems you can use LibreNMS in combination with check_mk (found here ). The agent can be extended to include data about applications on the remote system. Installation Linux / BSD Make sure that systemd or xinetd is installed on the host you want to run the agent on. The agent uses TCP-Port 6556, please allow access from the LibreNMS host and poller nodes if you're using the Distributed Polling setup. On each of the hosts you would like to use the agent on, you need to do the following: 1: Clone the librenms-agent repository: cd /opt/ git clone https://github.com/librenms/librenms-agent.git cd librenms-agent 2: Copy the relevant check_mk_agent to /usr/bin : linux freebsd cp check_mk_agent /usr/bin/check_mk_agent cp check_mk_agent_freebsd /usr/bin/check_mk_agent chmod +x /usr/bin/check_mk_agent 3: Copy the service file(s) into place. xinetd systemd cp check_mk_xinetd /etc/xinetd.d/check_mk cp check_mk@.service check_mk.socket /etc/systemd/system 4: Create the relevant directories. mkdir -p /usr/lib/check_mk_agent/plugins /usr/lib/check_mk_agent/local 5: Copy each of the scripts from agent-local/ into /usr/lib/check_mk_agent/local that you require to be graphed. You can find detail setup instructions for specific applications above. 6: Make each one executable that you want to use with chmod +x /usr/lib/check_mk_agent/local/$script 7: Enable the check_mk service xinetd systemd /etc/init.d/xinetd restart systemctl enable check_mk.socket && systemctl start check_mk.socket 8: Login to the LibreNMS web interface and edit the device you want to monitor. Under the modules section, ensure that unix-agent is enabled. 9: Then under Applications, enable the apps that you plan to monitor. 10: Wait for around 10 minutes and you should start seeing data in your graphs under Apps for the device. Restrict the devices on which the agent listens: Linux systemd If you want to restrict which network adapter the agent listens on, do the following: 1: Edit /etc/systemd/system/check_mk.socket 2: Under the [Socket] section, add a new line BindToDevice= and the name of your network adapter. 3: If the script has already been enabled in systemd, you may need to issue a systemctl daemon-reload and then systemctl restart check_mk.socket Windows Grab version 1.2.6b5 of the check_mk agent from the check_mk github repo (exe/msi or compile it yourself depending on your usage): https://github.com/tribe29/checkmk/tree/v1.2.6b5/agents/windows Run the msi / exe Make sure your LibreNMS instance can reach TCP port 6556 on your target.","title":"Check_MK Setup"},{"location":"Extensions/Agent-Setup/#check_mk-setup","text":"The agent can be used to gather data from remote systems you can use LibreNMS in combination with check_mk (found here ). The agent can be extended to include data about applications on the remote system.","title":"Check_MK Setup"},{"location":"Extensions/Agent-Setup/#installation","text":"","title":"Installation"},{"location":"Extensions/Agent-Setup/#linux-bsd","text":"Make sure that systemd or xinetd is installed on the host you want to run the agent on. The agent uses TCP-Port 6556, please allow access from the LibreNMS host and poller nodes if you're using the Distributed Polling setup. On each of the hosts you would like to use the agent on, you need to do the following: 1: Clone the librenms-agent repository: cd /opt/ git clone https://github.com/librenms/librenms-agent.git cd librenms-agent 2: Copy the relevant check_mk_agent to /usr/bin : linux freebsd cp check_mk_agent /usr/bin/check_mk_agent cp check_mk_agent_freebsd /usr/bin/check_mk_agent chmod +x /usr/bin/check_mk_agent 3: Copy the service file(s) into place. xinetd systemd cp check_mk_xinetd /etc/xinetd.d/check_mk cp check_mk@.service check_mk.socket /etc/systemd/system 4: Create the relevant directories. mkdir -p /usr/lib/check_mk_agent/plugins /usr/lib/check_mk_agent/local 5: Copy each of the scripts from agent-local/ into /usr/lib/check_mk_agent/local that you require to be graphed. You can find detail setup instructions for specific applications above. 6: Make each one executable that you want to use with chmod +x /usr/lib/check_mk_agent/local/$script 7: Enable the check_mk service xinetd systemd /etc/init.d/xinetd restart systemctl enable check_mk.socket && systemctl start check_mk.socket 8: Login to the LibreNMS web interface and edit the device you want to monitor. Under the modules section, ensure that unix-agent is enabled. 9: Then under Applications, enable the apps that you plan to monitor. 10: Wait for around 10 minutes and you should start seeing data in your graphs under Apps for the device.","title":"Linux / BSD"},{"location":"Extensions/Agent-Setup/#restrict-the-devices-on-which-the-agent-listens-linux-systemd","text":"If you want to restrict which network adapter the agent listens on, do the following: 1: Edit /etc/systemd/system/check_mk.socket 2: Under the [Socket] section, add a new line BindToDevice= and the name of your network adapter. 3: If the script has already been enabled in systemd, you may need to issue a systemctl daemon-reload and then systemctl restart check_mk.socket","title":"Restrict the devices on which the agent listens: Linux systemd"},{"location":"Extensions/Agent-Setup/#windows","text":"Grab version 1.2.6b5 of the check_mk agent from the check_mk github repo (exe/msi or compile it yourself depending on your usage): https://github.com/tribe29/checkmk/tree/v1.2.6b5/agents/windows Run the msi / exe Make sure your LibreNMS instance can reach TCP port 6556 on your target.","title":"Windows"},{"location":"Extensions/Applications/","text":"Applications You can use Application support to graph performance statistics of many applications. Different applications support a variety of ways to collect data: By direct connection to the application snmpd extend The agent . The monitoring of applications could be added before or after the hosts have been added to LibreNMS. If multiple methods of collection are listed you only need to enable one. SNMP Extend When using the snmp extend method, the application discovery module will pick up which applications you have set up for monitoring automatically, even if the device is already in LibreNMS. The application discovery module is enabled by default for most *nix operating systems, but in some cases you will need to manually enable the application discovery module. SUDO One major thing to keep in mind when using SNMP extend is these run as the snmpd user that can be an unprivileged user. In these situations you need to use sudo. To test if you need sudo, first check the user snmpd is running as. Then test if you can run the extend script as that user without issue. For example if snmpd is running as 'Debian-snmp' and we want to run the extend for proxmox, we check that the following run without error: sudo -u Debian-snmp /usr/local/bin/proxmox If it doesn't work, then you will need to use sudo with the extend command. For the example above, that would mean adding the line below to the sudoers file: Debian-snmp ALL = NOPASSWD: /usr/local/bin/proxmox Finally we would need to add sudo to the extend command, which would look like that for proxmox: extend proxmox /usr/bin/sudo /usr/local/bin/proxmox JSON Return Optimization Using librenms_return_optimizer While the json_app_get does allow for more complex and larger data to be easily returned by a extend and the data to then be worked with, this can also sometimes result in large returns that occasionally don't play nice with SNMP on some networks. librenms_return_optimizer fixes this via taking the extend output piped to it, gzipping it, and then converting it to base64. The later is needed as net-snmp does not play that nice with binary data, converting most of the non-printable characters to . . This does add a bit of additional overhead to the gzipped data, but still tends to be result in a return that is usually a third of the size for JSONs items. The change required is fairly simply. So for the portactivity example below... extend portactivity /etc/snmp/extends/portactivity smtps,http,imap,imaps,postgresql,https,ldap,ldaps,nfsd,syslog-conn,ssh,matrix,gitea Would become this... extend portactivity /usr/local/bin/lnms_return_optimizer -- /etc/snmp/extends/portactivity smtps,http,imap,imaps,postgresql,https,ldap,ldaps,nfsd,syslog-conn,ssh,matrix,gitea The requirements for this are Perl, MIME::Base64, and Gzip::Faster. Installing on FreeBSD... pkg install p5-MIME-Base64 p5-Gzip-Faster wget wget https://raw.githubusercontent.com/librenms/librenms-agent/master/utils/librenms_return_optimizer -O /usr/local/bin/librenms_return_optimizer chmod +x /usr/local/bin/librenms_return_optimizer Installing on Debian... apt-get install zlib1g-dev cpanminus wget cpanm Gzip::Faster cpanm MIME::Base64 wget https://raw.githubusercontent.com/librenms/librenms-agent/master/utils/librenms_return_optimizer -O /usr/local/bin/librenms_return_optimizer chmod +x /usr/local/bin/librenms_return_optimizer Currently supported applications as are below. backupninja certificate chronyd dhcp-stats docker fail2ban fbsd-nfs-client fbsd-nfs-server gpsd mailcow-postfix mdadm ntp-client ntp-server portactivity powerdns powermon puppet-agent pureftpd redis seafile supervisord ups-apcups zfs The following apps have extends that have native support for this, if congiured to do so. suricata Enable the application discovery module Edit the device for which you want to add this support Click on the Modules tab and enable the applications module. This will be automatically saved, and you should get a green confirmation pop-up message. After you have enabled the application module, it would be wise to then also enable which applications you want to monitor, in the rare case where LibreNMS does not automatically detect it. Note : Only do this if an application was not auto-discovered by LibreNMS during discovery and polling. Enable the application(s) to be discovered Go to the device you have just enabled the application module for. Click on the Applications tab and select the applications you want to monitor. This will also be automatically saved, and you should get a green confirmation pop-up message. Agent The unix-agent does not have a discovery module, only a poller module. That poller module is always disabled by default. It needs to be manually enabled if using the agent. Some applications will be automatically enabled by the unix-agent poller module. It is better to ensure that your application is enabled for monitoring. You can check by following the steps under the SNMP Extend heading. Apache Either use SNMP extend or use the agent. Note that you need to install and configure the Apache mod_status module before trying the script. SNMP Extend Download the script onto the desired host (the host must be added to LibreNMS devices) wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/apache-stats.py -O /etc/snmp/apache-stats.py Make the script executable chmod +x /etc/snmp/apache-stats.py Create the cache directory, '/var/cache/librenms/' and make sure that it is owned by the user running the SNMP daemon. mkdir -p /var/cache/librenms/ Verify it is working by running /etc/snmp/apache-stats.py Package urllib3 for python3 needs to be installed. In Debian-based systems for example you can achieve this by issuing: apt-get install python3-urllib3 Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend apache /etc/snmp/apache-stats.py Restart snmpd on your host Test by running snmpwalk localhost NET-SNMP-EXTEND-MIB::nsExtendOutput2Table Agent Install the agent on this device if it isn't already and copy the apache script to /usr/lib/check_mk_agent/local/ Verify it is working by running /usr/lib/check_mk_agent/local/apache (If you get error like \"Can't locate LWP/Simple.pm\". libwww-perl needs to be installed: apt-get install libwww-perl) Create the cache directory, '/var/cache/librenms/' and make sure that it is owned by the user running the SNMP daemon. mkdir -p /var/cache/librenms/ On the device page in Librenms, edit your host and check the Apache under the Applications tab. Asterisk A small shell script that reports various Asterisk call status. SNMP Extend Download the asterisk script to /etc/snmp/ on your asterisk server. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/asterisk -O /etc/snmp/asterisk Make the script executable chmod +x /etc/snmp/asterisk Configure ASCLI in the script. Verify it is working by running /etc/snmp/asterisk Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend asterisk /etc/snmp/asterisk Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. backupninja A small shell script that reports status of last backupninja backup. SNMP Extend Download the backupninja script to /etc/snmp/backupninja.py on your backuped server. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/backupninja.py -O /etc/snmp/backupninja.py` Make the script executable: chmod +x /etc/snmp/backupninja.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend backupninja /etc/snmp/backupninja.py Restart snmpd on your host BIND9 aka named Create stats file with appropriate permissions: touch /var/cache/bind/stats chown bind:bind /var/cache/bind/stats Change user:group to the user and group that's running bind/named. Bind/named configuration: options { ... statistics-file \"/var/cache/bind/stats\"; zone-statistics yes; ... }; Restart your bind9/named after changing the configuration. Verify that everything works by executing rndc stats && cat /var/cache/bind/stats . In case you get a Permission Denied error, make sure you changed the ownership correctly. Also be aware that this file is appended to each time rndc stats is called. Given this it is suggested you setup file rotation for it. Alternatively you can also set zero_stats to 1 in the config. The script for this also requires the Perl module File::ReadBackwards . FreeBSD => p5-File-ReadBackwards CentOS/RedHat => perl-File-ReadBackwards Debian/Ubuntu => libfile-readbackwards-perl If it is not available, it can be installed by cpan -i File::ReadBackwards . You may possibly need to configure the agent/extend script as well. The config file's path defaults to the same path as the script, but with .config appended. So if the script is located at /etc/snmp/bind , the config file will be /etc/snmp/bind.config . Alternatively you can also specify a config via -c $file . Anything starting with a # is comment. The format for variables are $variable=$value. Empty lines are ignored. Spaces and tabs at either the start or end of a line are ignored. Content of an example /etc/snmp/bind.config . Please edit with your own settings. rndc = The path to rndc. Default: /usr/bin/env rndc call_rndc = A 0/1 boolean on whether or not to call rndc stats. Suggest to set to 0 if using netdata. Default: 1 stats_file = The path to the named stats file. Default: /var/cache/bind/stats agent = A 0/1 boolean for if this is being used as a LibreNMS agent or not. Default: 0 zero_stats = A 0/1 boolean for if the stats file should be zeroed first. Default: 0 (1 if guessed) If you want to guess at the configuration, call the script with -g and it will print out what it thinks it should be. SNMP Extend Copy the bind shell script, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/bind -O /etc/snmp/bind Make the script executable chmod +x /etc/snmp/bind Edit your snmpd.conf file and add: extend bind /etc/snmp/bind Restart snmpd on the host in question. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Agent Install the agent on this device if it isn't already and copy the script to /usr/lib/check_mk_agent/local/bind via wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/bind -O /usr/lib/check_mk_agent/local/bind Make the script executable chmod +x /usr/lib/check_mk_agent/local/bind Set the variable 'agent' to '1' in the config. BIRD2 The BIRD Internet Routing Daemon (BGP) Due to the lack of SNMP support in the BIRD daemon, this application extracts all configured BGP protocols and parses it into LibreNMS. This application supports both IPv4 and IPv6 Peer processing. SNMP Extend Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend bird2 '/usr/bin/sudo /usr/sbin/birdc -r show protocols all' Edit your sudo users (usually visudo ) and add at the bottom: Debian-snmp ALL=(ALL) NOPASSWD: /usr/sbin/birdc If your snmp daemon is running on a user that isnt Debian-snmp make sure that user has the correct permission to execute birdc Verify the time format for bird2 is defined. Otherwise iso short ms (hh:mm:ss) is the default value that will be used. Which is not compatible with the datetime parsing logic used to parse the output from the bird show command. timeformat protocol is the one important to be defibned for the bird2 app parsing logic to work. Example starting point using Bird2 shorthand iso long (YYYY-MM-DD hh:mm:ss): timeformat base iso long; timeformat log iso long; timeformat protocol iso long; timeformat route iso long; Timezone can be manually specified, example \"%F %T %z\" (YYYY-MM-DD hh:mm:ss +11:45). See the Bird 2 docs for more information Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Certificate A small python3 script that checks age and remaining validity of certificates This script needs following packages on Debian/Ubuntu Systems: python3 python3-openssl Content of an example /etc/snmp/certificate.json . Please edit with your own settings. {\"domains\": [ {\"fqdn\": \"www.mydomain.com\"}, {\"fqdn\": \"some.otherdomain.org\", \"port\": 8443}, {\"fqdn\": \"personal.domain.net\"}, {\"fqdn\": \"selfsignedcert_host.domain.com\", \"cert_location\": \"/etc/pki/tls/certs/localhost.pem\"} ] } a. (Required): Key 'domains' contains a list of domains to check. b. (Optional): You can define a port. By default it checks on port 443. c. (Optional): You may define a certificate location for self-signed certificates. SNMP Extend Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/certificate.py -O /etc/snmp/certificate.py Make the script executable chmod +x /etc/snmp/certificate.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend certificate /etc/snmp/certificate.py Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. BorgBackup SNMP Extend Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/borgbackup -O /etc/snmp/borgbackup Make the script executable chmod +x /etc/snmp/borgbackup Install depends. # FreeBSD pkg p5-Config-Tiny p5-JSON p5-File-Slurp p5-MIME-Base64 p5-String-ShellQuote # Debian apt-get install libconfig-tiny-perl libjson-perl libfile-slurp-perl libmime-base64-perl libstring-shellquote-perl # generic cpanm cpanm Config::Tiny File::Slurp JSON MIME::Base64 String::ShellQuote Set it up in cron. */5 * * * /etc/snmp/borgbackup 2> /dev/null > /dev/null Configure it. See further down below or /etc/snmp/borgbackup --help . Add the following to the SNMPD config. extend borgbackup /bin/cat /var/cache/borgbackup_extend/extend_return Restart SNMPD and wait for the device to rediscover or tell it to manually. Config The config file is a ini file and handled by Config::Tiny . - mode :: single or multi, for if this is a single repo or for multiple repos. - Default :: single - repo :: Directory for the borg backup repo. - Default :: undef - passphrase :: Passphrase for the borg backup repo. - Default :: undef - passcommand :: Passcommand for the borg backup repo. - Default :: undef For single repos all those variables are in the root section of the config, so lets the repo is at '/backup/borg' with a passphrase of '1234abc'. repo=/backup/borg repo=1234abc For multi, each section outside of the root represents a repo. So if there is '/backup/borg1' with a passphrase of 'foobar' and '/backup/derp' with a passcommand of 'pass show backup' it would be like below. mode=multi [borg1] repo=/backup/borg1 passphrase=foobar [derp] repo=/backup/derp passcommand=pass show backup If 'passphrase' and 'passcommand' are both specified, then passcommand is used. Metrics The metrics are all from .data.totals in the extend return. Value Type Description errored repos Total number of repos that info could not be fetched for. locked repos Total number of locked repos locked_for seconds Longest time any repo has been locked. time_since_last_modified seconds Largest time - mtime for the repo nonce total_chunks chunks Total number of chunks total_csize bytes Total compressed size of all archives in all repos. total_size byes Total uncompressed size of all archives in all repos. total_unique_chunks chunks Total number of unique chuckes in all repos. unique_csize bytes Total deduplicated size of all archives in all repos. unique_size chunks Total number of chunks in all repos. CAPEv2 Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/cape -O /etc/snmp/cape Make the script executable chmod +x /etc/snmp/cape Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend cape /etc/snmp/cape Install the required packages. apt-get install libfile-readbackwards-perl libjson-perl libconfig-tiny-perl libdbi-perl libfile-slurp-perl libstatistics-lite-perl Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. C.H.I.P C.H.I.P. is a $9 R8 based tiny computer ideal for small projects. Further details: https://getchip.com/pages/chip Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/chip.sh -O /etc/snmp/power-stat.sh Make the script executable chmod +x /etc/snmp/power-stat.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend power-stat /etc/snmp/power-stat.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Docker Stats It gathers metrics about the docker containers, including: - cpu percentage - memory usage - container size - uptime - Totals per status This script requires python3 and the pip module python-dateutil SNMP Extend Install pip module pip3 install python-dateutil Copy the shell script to the desired host. By default, it will only show the status for containers that are running. To include all containers modify the constant in the script at the top of the file and change it to ONLY_RUNNING_CONTAINERS = False wget https://github.com/librenms/librenms-agent/raw/master/snmp/docker-stats.py -O /etc/snmp/docker-stats.py Make the script executable chmod +x /etc/snmp/docker-stats.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend docker /etc/snmp/docker-stats.py If your run Debian, you need to add the Debian-snmp user to the docker group usermod -a -G docker Debian-snmp Restart snmpd on your host systemctl restart snmpd Entropy A small shell script that checks your system's available random entropy. SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/entropy.sh -O /etc/snmp/entropy.sh Make the script executable chmod +x /etc/snmp/entropy.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend entropy /etc/snmp/entropy.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. EXIM Stats SNMP extend script to get your exim stats data into your host. SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/exim-stats.sh -O /etc/snmp/exim-stats.sh Make the script executable chmod +x /etc/snmp/exim-stats.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend exim-stats /etc/snmp/exim-stats.sh If you are using sudo edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /etc/snmp/exim-stats.sh, /usr/bin/exim* Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Fail2ban SNMP Extend Copy the shell script, fail2ban, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/fail2ban -O /etc/snmp/fail2ban Make the script executable chmod +x /etc/snmp/fail2ban Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend fail2ban /etc/snmp/fail2ban If you want to use the cache, it is as below, by using the -c switch. extend fail2ban /etc/snmp/fail2ban -c If you want to use the cache and update it if needed, this can by using the -c and -U switches. extend fail2ban /etc/snmp/fail2ban -c -U If you need to specify a custom location for the fail2ban-client, that can be done via the -f switch. extend fail2ban /etc/snmp/fail2ban -f /foo/bin/fail2ban-client If not specified, \"/usr/bin/env fail2ban-client\" is used. Restart snmpd on your host If you wish to use caching, add the following to /etc/crontab and restart cron. */3 * * * * root /etc/snmp/fail2ban -u Restart or reload cron on your system. If you have more than a few jails configured, you may need to use caching as each jail needs to be polled and fail2ban-client can't do so in a timely manner for than a few. This can result in failure of other SNMP information being polled. For additional details of the switches, please see the POD in the script it self at the top. FreeBSD NFS Client SNMP Extend Copy the shell script, fbsdnfsserver, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/fbsdnfsclient -O /etc/snmp/fbsdnfsclient Make the script executable chmod +x /etc/snmp/fbsdnfsclient Edit your snmpd.conf file and add: extend fbsdnfsclient /etc/snmp/fbsdnfsclient Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. FreeBSD NFS Server SNMP Extend Copy the shell script, fbsdnfsserver, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/fbsdnfsserver -O /etc/snmp/fbsdnfsserver Make the script executable chmod +x /etc/snmp/fbsdnfsserver Edit your snmpd.conf file and add: extend fbsdnfsserver /etc/snmp/fbsdnfsserver Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. FreeRADIUS The FreeRADIUS application extension requires that status_server be enabled in your FreeRADIUS config. For more information see: https://wiki.freeradius.org/config/Status You should note that status requests increment the FreeRADIUS request stats. So LibreNMS polls will ultimately be reflected in your stats/charts. Go to your FreeRADIUS configuration directory (usually /etc/raddb or /etc/freeradius). cd sites-enabled ln -s ../sites-available/status status Restart FreeRADIUS. You should be able to test with the radclient as follows... echo \"Message-Authenticator = 0x00, FreeRADIUS-Statistics-Type = 31, Response-Packet-Type = Access-Accept\" | \\ radclient -x localhost:18121 status adminsecret Note that adminsecret is the default secret key in status_server. Change if you've modified this. SNMP Extend Copy the freeradius shell script, to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/freeradius.sh -O /etc/snmp/freeradius.sh Make the script executable chmod +x /etc/snmp/freeradius.sh If you've made any changes to the FreeRADIUS status_server config (secret key, port, etc.) edit freeradius.sh and adjust the config variable accordingly. Edit your snmpd.conf file and add: extend freeradius /etc/snmp/freeradius.sh Restart snmpd on the host in question. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Agent Install the script to your agent wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/freeradius.sh -O /usr/lib/check_mk_agent/local/freeradius.sh` Make the script executable chmod +x /usr/lib/check_mk_agent/local/freeradius.sh If you've made any changes to the FreeRADIUS status_server config (secret key, port, etc.) edit freeradius.sh and adjust the config variable accordingly. Edit the freeradius.sh script and set the variable 'AGENT' to '1' in the config. Freeswitch A small shell script that reports various Freeswitch call status. Agent Install the agent on this device if it isn't already and copy the freeswitch script to /usr/lib/check_mk_agent/local/ wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/freeswitch -O /usr/lib/check_mk_agent/local/freeswitch` Make the script executable chmod +x /usr/lib/check_mk_agent/local/freeswitch Configure FSCLI in the script. You may also have to create an /etc/fs_cli.conf file if your fs_cli command requires authentication. Verify it is working by running /usr/lib/check_mk_agent/local/freeswitch SNMP Extend Download the script onto the desired host wget https://github.com/librenms/librenms-agent/raw/master/agent-local/freeswitch -O /etc/snmp/freeswitch Make the script executable chmod +x /etc/snmp/freeswitch Configure FSCLI in the script. You may also have to create an /etc/fs_cli.conf file if your fs_cli command requires authentication. Verify it is working by running /etc/snmp/freeswitch Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend freeswitch /etc/snmp/freeswitch Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. GPSD SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/gpsd -O /etc/snmp/gpsd Make the script executable chmod +x /etc/snmp/gpsd Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend gpsd /etc/snmp/gpsd Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading at the top of the page. Agent Install the agent on this device if it isn't already and copy the gpsd script to /usr/lib/check_mk_agent/local/ You may need to configure $server or $port . Verify it is working by running /usr/lib/check_mk_agent/local/gpsd HV Monitor HV Monitor provides a generic way to monitor hypervisors. Currently CBSD+bhyve on FreeBSD and Libvirt+QEMU on Linux are support. For more information see HV::Monitor on Github or MetaCPAN . SNMP Extend Install the SNMP Extend. For Debian based systems this is as below. apt-get install zlib1g-dev cpanminus libjson-perl cpanm HV::Monitor And on FreeBSD as below. pkg install p5-App-cpanminus p5-JSON p5-MIME-Base64 p5-Gzip-Faster cpanm HV::Monitor Set it up to be be ran by cron by root. Yes, you can directly call this script from SNMPD, but be aware, especially with Libvirt, there is a very real possibility of the snmpget timing out, especially if a VM is spinning up/down as virsh domstats can block for a few seconds or so then. */5 * * * * /usr/local/bin/hv_monitor > /var/cache/hv_monitor.json -c 2> /dev/null Setup snmpd.conf as below. extend hv-monitor /bin/cat /var/cache/hv_monitor.json Restart SNMPD. Either wait for it to be re-discovered or manually enable it. Icecast Shell script that reports load average/memory/open-files stats of Icecast SNMP Extend Copy the shell script, icecast-stats.sh, to the desired host (the host must be added to LibreNMS devices) wget https://github.com/librenms/librenms-agent/raw/master/snmp/icecast-stats.sh -O /etc/snmp/icecast-stats.sh Make the script executable chmod +x /etc/snmp/icecast-stats.sh Verify it is working by running /etc/snmp/icecast-stats.sh Edit your snmpd.conf file (usually /etc/snmp/icecast-stats.sh ) and add: extend icecast /etc/snmp/icecast-stats.sh ISC DHCP Stats A small python3 script that reports current DHCP leases stats and pool usage of ISC DHCP Server. Also you have to install the dhcpd-pools and the required Perl modules. Under Ubuntu/Debian just run apt install cpanminus ; cpanm Net::ISC::DHCPd::Leases Mime::Base64 File::Slurp or under FreeBSD pkg install p5-JSON p5-MIME-Base64 p5-App-cpanminus p5-File-Slurp ; cpanm Net::ISC::DHCPd::Leases . SNMP Extend Copy the shell script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/dhcp -O /etc/snmp/dhcp Make the script executable chmod +x /etc/snmp/dhcp Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: # without using cron extend dhcpstats /etc/snmp/dhcp -Z # using cron extend dhcpstats /bin/cat /var/cache/dhcp_extend If on a slow system running it via cron may be needed. */5 * * * * /etc/snmp/dhcp -Z -w /var/cache/dhcp_extend The following options are also supported. Option Description -c $file Path to dhcpd.conf. -l $file Path to lease file. -Z Enable GZip+Base64 compression. -d Do not de-dup. -w $file File to write it out to. Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Logsize SNMP Extend Download the script and make it executable. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/logsize -O /etc/snmp/logsize chmod +x /etc/snmp/logsize Install the requirements. # FreeBSD pkg install p5-File-Find-Rule p5-JSON p5-TOML p5-Time-Piece p5-MIME-Base64 p5-File-Slurp p5-Statistics-Lite # Debian apt-get install cpanminus cpanm File::Find::Rule JSON TOML Time::Piece MIME::Base64 File::Slurp Statistics::Lite Configure the config at /usr/local/etc/logsize.conf . You can find the documentation for the config file in the extend. Below is a small example. # monitor log sizes of logs directly udner /var/log [sets.var_log] dir=\"/var/log/\" # monitor remote logs from network devices [sets.remote_network] dir=\"/var/log/remote/network/\" # monitor remote logs from windows sources [sets.remote_windows] dir=\"/var/log/remote/windows/\" # monitor suricata flows logs sizes [sets.suricata_flows] dir=\"/var/log/suricata/flows/current\" If the directories all readable via SNMPD, this script can be ran via snmpd. Otherwise it needs setup in cron. Similarly is processing a large number of files, it may also need setup in cron if it takes the script awhile to run. */5 * * * * /etc/snmp/logsize -b 2> /dev/null > /dev/null Make sure that /var/cache/logsize_extend exists and is writable by the user running the extend. mkdir -p /var/cache/logsize_extend Configure it in the SNMPD config. # if not using cron extend logsize /etc/snmp/logsize -b # if using cron extend logsize /bin/cat /var/cache/logsize_extend/extend_return linux_config_files linux_config_files is an application intended to monitor a Linux distribution's configuration files via that distribution's configuration management tool/system. At this time, ONLY RPM-based (Fedora/RHEL) SYSTEMS ARE SUPPORTED utilizing the rpmconf tool. The linux_config_files application collects and graphs the total count of configuration files that are out of sync and graphs that number. Fedora/RHEL: Rpmconf is a utility that analyzes rpm configuration files using the RPM Package Manager. Rpmconf reports when a new configuration file standard has been issued for an upgraded/downgraded piece of software. Typically, rpmconf is used to provide a diff of the current configuration file versus the new, standard configuration file. The administrator can then choose to install the new configuration file or keep the old one. SNMP Extend Copy the python script, linux_config_files.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/linux_config_files.py -O /etc/snmp/linux_config_files.py Make the script executable chmod +x /etc/snmp/linux_config_files.py Edit your snmpd.conf file and add: extend linux_config_files /etc/snmp/linux_config_files.py (Optional on an RPM-based distribution) Create a /etc/snmp/linux_config_files.json file and specify the following: \"pkg_system\" - String designating the distribution name of the system. At the moment only \"rpm\" is supported [\"rpm\"] \"pkg_tool_cmd\" - String path to the package tool binary [\"/sbin/rpmconf\"] { \"pkg_system\": \"rpm\", \"pkg_tool_cmd\": \"/bin/rpmconf\", } Restart snmpd. Linux Softnet Stat SNMP Extend 1: Install the depends, which on a Debian based system would be as below. apt-get install -y cpanminus zlib1g-dev cpanm File::Slurp MIME::Base64 JSON Gzip::Faster Download the script into the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/linux_softnet_stat -O /etc/snmp/linux_softnet_stat Make the script executable chmod +x /etc/snmp/linux_softnet_stat Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend linux_softnet_stat /etc/snmp/linux_softnet_stat -b Then either enable the application Linux Softnet Stat or wait for it to be re-discovered. mailcow-dockerized postfix SNMP Extend Download the script into the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/mailcow-dockerized-postfix -O /etc/snmp/mailcow-dockerized-postfix Make the script executable chmod +x /etc/snmp/mailcow-dockerized-postfix Maybe you will need to install pflogsumm on debian based OS. Please check if you have package installed. Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend mailcow-postfix /etc/snmp/mailcow-dockerized-postfix Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Mailscanner SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/mailscanner.php -O /etc/snmp/mailscanner.php Make the script executable chmod +x /etc/snmp/mailscanner.php Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend mailscanner /etc/snmp/mailscanner.php Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Mdadm It allows you to checks mdadm health and array data This script require: jq SNMP Extend Install jq sudo apt install jq Download the script onto the desired host. sudo wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/mdadm -O /etc/snmp/mdadm Make the script executable sudo chmod +x /etc/snmp/mdadm Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend mdadm /etc/snmp/mdadm Verify it is working by running sudo /etc/snmp/mdadm Restart snmpd on your host sudo service snmpd restart The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. MegaRAID This software from Broadcom/LSI let you monitor MegaRAID controller. Download the external software and follow the included install instructions. Add the following line to your snmpd.conf file (usually /etc/snmp/snmpd.conf) pass .1.3.6.1.4.1.3582 /usr/sbin/lsi_mrdsnmpmain Restart snmpd on your host Memcached SNMP Extend Copy the memcached script to /etc/snmp/ on your remote server. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/memcached -O /etc/snmp/memcached Make the script executable: chmod +x /etc/snmp/memcached Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend memcached /etc/snmp/memcached Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Mojo CAPE Submit SNMP This assumes you've already configured mojo_cape_submit from CAPE::Utils. Add the following to snmpd.conf and restarted SNMPD extend mojo_cape_submit /usr/local/bin/mojo_cape_submit_extend Then just wait for the machine in question to be rediscovered or enabled it in the device settings app page. Munin Agent Install the script to your agent: wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/munin -O /usr/lib/check_mk_agent/local/munin Make the script executable chmod +x /usr/lib/check_mk_agent/local/munin Create the munin scripts dir: mkdir -p /usr/share/munin/munin-scripts Install your munin scripts into the above directory. To create your own custom munin scripts, please see this example: #!/bin/bash if [ \" $1 \" = \"config\" ] ; then echo 'graph_title Some title' echo 'graph_args --base 1000 -l 0' #not required echo 'graph_vlabel Some label' echo 'graph_scale no' #not required, can be yes/no echo 'graph_category system' #Choose something meaningful, can be anything echo 'graph_info This graph shows something awesome.' #Short desc echo 'foobar.label Label for your unit' # Repeat these two lines as much as you like echo 'foobar.info Desc for your unit.' exit 0 fi echo -n \"foobar.value \" $( date +%s ) #Populate a value, here unix-timestamp MySQL Create the cache directory, '/var/cache/librenms/' and make sure that it is owned by the user running the SNMP daemon. mkdir -p /var/cache/librenms/ The MySQL script requires PHP-CLI and the PHP MySQL extension, so please verify those are installed. CentOS (May vary based on PHP version) yum install php-cli php-mysql Debian (May vary based on PHP version) apt-get install php-cli php-mysql Unlike most other scripts, the MySQL script requires a configuration file mysql.cnf in the same directory as the extend or agent script with following content: php $mysql_user = 'root' ; $mysql_pass = 'toor' ; $mysql_host = 'localhost' ; $mysql_port = 3306 ; Note that depending on your MySQL installation (chrooted install for example), you may have to specify 127.0.0.1 instead of localhost. Localhost make a MySQL connection via the mysql socket, while 127.0.0.1 make a standard IP connection to mysql. Note also if you get a mysql error Uncaught TypeError: mysqli_num_rows(): Argument #1 , this is because you are using a newer mysql version which doesnt support UNBLOCKING for slave statuses, so you need to also include the line $chk_options['slave'] = false; into mysql.cnf to skip checking slave statuses Agent Install the agent on this device if it isn't already and copy the mysql script to /usr/lib/check_mk_agent/local/ Verify it is working by running /usr/lib/check_mk_agent/local/mysql SNMP extend Copy the mysql script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/mysql -O /etc/snmp/mysql Make the file executable chmod +x /etc/snmp/mysql Edit /etc/snmp/mysql to set your MySQL connection constants or declare them in /etc/snmp/mysql.cnf (new file) Edit your snmpd.conf file and add: extend mysql /etc/snmp/mysql Restart snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. NGINX NGINX is a free, open-source, high-performance HTTP server: https://www.nginx.org/ It's required to have the following directive in your nginx configuration responsible for the localhost server: location /nginx-status { stub_status on; access_log off; allow 127.0.0.1; allow ::1; deny all; } SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/nginx -O /etc/snmp/nginx Make the script executable chmod +x /etc/snmp/nginx Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend nginx /etc/snmp/nginx (Optional) If you have SELinux in Enforcing mode, you must add a module so the script can request /nginx-status: cat << EOF > snmpd_nginx.te module snmpd_nginx 1.0; require { type httpd_t; type http_port_t; type snmpd_t; class tcp_socket name_connect; } #============= snmpd_t ============== allow snmpd_t http_port_t:tcp_socket name_connect; EOF checkmodule -M -m -o snmpd_nginx.mod snmpd_nginx.te semodule_package -o snmpd_nginx.pp -m snmpd_nginx.mod semodule -i snmpd_nginx.pp Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Agent Install the agent on this device if it isn't already and copy the nginx script to /usr/lib/check_mk_agent/local/ NFS Server Export the NFS stats from as server. SNMP Extend Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add : extend nfs-server /bin/cat /proc/net/rpc/nfsd find out where cat is located using : which cat reload snmpd service to activate the configuration NTP Client A shell script that gets stats from ntp client. SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/ntp-client -O /etc/snmp/ntp-client Make the script executable chmod +x /etc/snmp/ntp-client Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ntp-client /etc/snmp/ntp-client Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. NTP Server aka NTPD A shell script that gets stats from ntp server (ntpd). SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/ntp-server.sh -O /etc/snmp/ntp-server.sh Make the script executable chmod +x /etc/snmp/ntp-server.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ntp-server /etc/snmp/ntp-server.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Chronyd A shell script that gets the stats from chronyd and exports them with SNMP Extend. SNMP Extend Download the shell script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/chrony -O /etc/snmp/chrony Make the script executable chmod +x /etc/snmp/chrony Edit the snmpd.conf file to include the extend by adding the following line to the end of the config file: extend chronyd /etc/snmp/chrony Note: Some distributions need sudo-permissions for the script to work with SNMP Extend. See the instructions on the section SUDO for more information. Restart snmpd service on the host Application should be auto-discovered and its stats presented on the Apps-page on the host. Note: Applications module needs to be enabled on the host or globally for the statistics to work as intended. Nvidia GPU SNMP Extend Copy the shell script, nvidia, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/nvidia -O /etc/snmp/nvidia Make the script executable chmod +x /etc/snmp/nvidia Edit your snmpd.conf file and add: extend nvidia /etc/snmp/nvidia Restart snmpd on your host. Verify you have nvidia-smi installed, which it generally should be if you have the driver from Nvida installed. The GPU numbering on the graphs will correspond to how the nvidia-smi sees them as being. For questions about what the various values are/mean, please see the nvidia-smi man file under the section covering dmon. Opensearch\\Elasticsearch SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/opensearch -O /etc/snmp/opensearch Make it executable chmod +x /etc/snmp/opensearch Install the required Perl dependencies. # FreeBSD pkg install p5-JSON p5-libwww # Debian/Ubuntu apt-get install libjson-perl libwww-perl # cpanm cpanm JSON Libwww Update your snmpd.conf. extend opensearch /bin/cat /var/cache/opensearch.json Update root crontab with. This is required as it will this will likely time out otherwise. Use */1 if you want to have the most recent stats when polled or to */5 if you just want at exactly a 5 minute interval. */5 * * * * /etc/snmp/opensearch > /var/cache/opensearch.json Enable it or wait for the device to be re-disocvered. Open Grid Scheduler Shell script to track the OGS/GE jobs running on clusters. SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/rocks.sh -O /etc/snmp/rocks.sh Make the script executable chmod +x /etc/snmp/rocks.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ogs /etc/snmp/rocks.sh Restart snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Opensips Script that reports load-average/memory/open-files stats of Opensips SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/opensips-stats.sh -O /etc/snmp/opensips-stats.sh Make the script executable: chmod +x /etc/snmp/opensips-stats.sh Verify it is working by running /etc/snmp/opensips-stats.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend opensips /etc/snmp/opensips-stats.sh OS Updates A small shell script that checks your system package manager for any available updates. Supports apt-get/pacman/yum/zypper package managers. For pacman users automatically refreshing the database, it is recommended you use an alternative database location --dbpath=/var/lib/pacman/checkupdate SNMP Extend Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/osupdate -O /etc/snmp/osupdate Make the script executable chmod +x /etc/snmp/osupdate Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend osupdate /etc/snmp/osupdate Restart snmpd on your host Note : apt-get depends on an updated package index. There are several ways to have your system run apt-get update automatically. The easiest is to create /etc/apt/apt.conf.d/10periodic and pasting the following in it: APT::Periodic::Update-Package-Lists \"1\"; . If you have apticron, cron-apt or apt-listchanges installed and configured, chances are that packages are already updated periodically . The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Agent Install the agent on this device if it isn't already and copy the osupdate script to /usr/lib/check_mk_agent/local/ Then uncomment the line towards the top marked to be uncommented if using it as a agent. PHP-FPM SNMP Extend Copy the shell script, phpfpmsp, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/phpfpmsp -O /etc/snmp/phpfpmsp Make the script executable chmod +x /etc/snmp/phpfpmsp Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend phpfpmsp /etc/snmp/phpfpmsp Edit /etc/snmp/phpfpmsp to include the status URL for the PHP-FPM pool you are monitoring. Restart snmpd on your host It is worth noting that this only monitors a single pool. If you want to monitor multiple pools, this won't do it. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Agent Install the agent on this device if it isn't already and copy the phpfpmsp script to /usr/lib/check_mk_agent/local/ Pi-hole SNMP Extend Copy the shell script, pi-hole, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/pi-hole -O /etc/snmp/pi-hole Make the script executable chmod +x /etc/snmp/pi-hole Edit your snmpd.conf file and add: extend pi-hole /etc/snmp/pi-hole To get all data you must get your API auth token from Pi-hole server and change the API_AUTH_KEY entry inside the snmp script. Restard snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Portactivity SNMP Extend Install missing packages - Ubuntu is shown below. apt install libparse-netstat-perl apt install libjson-perl Copy the Perl script to the desired host (the host must be added to LibreNMS devices) wget https://github.com/librenms/librenms-agent/raw/master/snmp/portactivity -O /etc/snmp/portactivity Make the script executable chmod +x /etc/snmp/portactivity Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend portactivity /etc/snmp/portactivity -p http,ldap,imap Will monitor HTTP, LDAP, and IMAP. The -p switch specifies what ports to use. This is a comma seperated list. These must be found in '/etc/services' or where ever NSS is set to fetch it from. If not, it will throw an error. If you want to JSON returned by it to be printed in a pretty format use the -P flag. Restart snmpd on your host. Please note that for only TCP[46] services are supported. Postfix SNMP Extend Copy the shell script, postfix-queues, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/postfix-queues -O /etc/snmp/postfix-queues Copy the Perl script, postfixdetailed, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/postfixdetailed -O /etc/snmp/postfixdetailed Make both scripts executable chmod +x /etc/snmp/postfixdetailed /etc/snmp/postfix-queues Edit your snmpd.conf file and add: extend mailq /etc/snmp/postfix-queues extend postfixdetailed /etc/snmp/postfixdetailed Restart snmpd. Install pflogsumm for your OS. Make sure the cache file in /etc/snmp/postfixdetailed is some place that snmpd can write too. This file is used for tracking changes between various values between each time it is called by snmpd. Also make sure the path for pflogsumm is correct. Run /etc/snmp/postfixdetailed to create the initial cache file so you don't end up with some crazy initial starting value. Please note that each time /etc/snmp/postfixdetailed is ran, the cache file is updated, so if this happens in between LibreNMS doing it then the values will be thrown off for that polling period. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. NOTE: If using RHEL for your postfix server, qshape must be installed manually as it is not officially supported. CentOs 6 rpms seem to work without issues. Postgres SNMP Extend Copy the shell script, postgres, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/postgres -O /etc/snmp/postgres Make the script executable chmod +x /etc/snmp/postgres Edit your snmpd.conf file and add: extend postgres /etc/snmp/postgres Restart snmpd on your host Install the Nagios check check_postgres.pl on your system: https://github.com/bucardo/check_postgres Verify the path to check_postgres.pl in /etc/snmp/postgres is correct. (Optional) If you wish to change the DB username (default: pgsql), enable the postgres DB in totalling (e.g. set ignorePG to 0, default: 1), or set a hostname for check_postgres.pl to connect to (default: the Unix Socket postgresql is running on), then create the file /etc/snmp/postgres.config with the following contents (note that not all of them need be defined, just whichever you'd like to change): DBuser=monitoring ignorePG=0 DBhost=localhost Note that if you are using netdata or the like, you may wish to set ignorePG to 1 or otherwise that total will be very skewed on systems with light or moderate usage. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. PowerDNS An authoritative DNS server: https://www.powerdns.com/auth.html SNMP Extend Copy the shell script, powerdns.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/powerdns.py -O /etc/snmp/powerdns.py Make the script executable chmod +x /etc/snmp/powerdns.py Edit your snmpd.conf file and add: extend powerdns /etc/snmp/powerdns.py Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Agent Install the agent on this device if it isn't already and copy the powerdns script to /usr/lib/check_mk_agent/local/ PowerDNS Recursor A recursive DNS server: https://www.powerdns.com/recursor.html Direct The LibreNMS polling host must be able to connect to port 8082 on the monitored device. The web-server must be enabled, see the Recursor docs: https://doc.powerdns.com/md/recursor/settings/#webserver Variables $config['apps']['powerdns-recursor']['api-key'] required, this is defined in the Recursor config $config['apps']['powerdns-recursor']['port'] numeric, defines the port to connect to PowerDNS Recursor on. The default is 8082 $config['apps']['powerdns-recursor']['https'] true or false, defaults to use http. SNMP Extend Copy the shell script, powerdns-recursor, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/powerdns-recursor -O /etc/snmp/powerdns-recursor Make the script executable chmod +x /etc/snmp/powerdns-recursor Edit your snmpd.conf file and add: extend powerdns-recursor /etc/snmp/powerdns-recursor Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Agent Install the agent on this device if it isn't already and copy the powerdns-recursor script to /usr/lib/check_mk_agent/local/ This script uses rec_control get-all to collect stats. PowerDNS-dnsdist SNMP Extend Copy the BASH script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/powerdns-dnsdist -O /etc/snmp/powerdns-dnsdist Make the script executable chmod +x /etc/snmp/powerdns-dnsdist Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend powerdns-dnsdist /etc/snmp/powerdns-dnsdist Restart snmpd on your host. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. PowerMon PowerMon tracks the power usage on your host and can report on both consumption and cost, using a python script installed on the host. PowerMon consumption graph Currently the script uses one of two methods to determine current power usage: ACPI via libsensors HP-Health (HP Proliant servers only) The ACPI method is quite unreliable as it is usually only implemented by battery-powered devices, e.g. laptops. YMMV. However, it's possible to support any method as long as it can return a power value, usually in Watts. TIP: You can achieve this by adding a method and a function for that method to the script. It should be called by getData() and return a dictionary. Because the methods are unreliable for all hardware, you need to declare to the script which method to use. The are several options to assist with testing, see --help . SNMP Extend Initial setup Download the python script onto the host: wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/powermon-snmp.py -O /usr/local/bin/powermon-snmp.py Make the script executable: chmod +x /usr/local/bin/powermon-snmp.py Edit the script and set the cost per kWh for your supply. You must uncomment this line for the script to work: vi /usr/local/bin/powermon-snmp.py #costPerkWh = 0.15 Choose you method below: Method 1. sensors Method 2. hpasmcli Install dependencies: dnf install lm_sensors pip install PySensors Test the script from the command-line. For example: $ /usr/local/bin/powermon-snmp.py -m sensors -n -p { \"meter\": { \"0\": { \"reading\": 0.0 } }, \"psu\": {}, \"supply\": { \"rate\": 0.15 }, \"reading\": \"0.0\" } If you see a reading of 0.0 it is likely this method is not supported for your system. If not, continue. Obtain the hp-health package for your system. Generally there are three options: Standalone package from HPE Support From the HP Management Component Pack (MCP). Included in the HP Service Pack for Proliant (SPP) If you've downloaded the standalone package, install it. For example: rpm -ivh hp-health-10.91-1878.11.rhel8.x86_64.rpm Check the service is running: systemctl status hp-health Test the script from the command-line. For example: $ /usr/local/bin/powermon-snmp.py -m hpasmcli -n -p { \"meter\": { \"1\": { \"reading\": 338.0 } }, \"psu\": { \"1\": { \"present\": \"Yes\", \"redundant\": \"No\", \"condition\": \"Ok\", \"hotplug\": \"Supported\", \"reading\": 315.0 }, \"2\": { \"present\": \"Yes\", \"redundant\": \"No\", \"condition\": \"FAILED\", \"hotplug\": \"Supported\" } }, \"supply\": { \"rate\": 0.224931 }, \"reading\": 338.0 } If you see a reading of 0.0 it is likely this method is not supported for your system. If not, continue. Finishing Up Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add the following: extend powermon /usr/local/bin/powermon-snmp.py -m hpasmcli NOTE: Avoid using other script options in the snmpd config as the results may not be interpreted correctly by LibreNMS. Reload your snmpd service: systemctl reload snmpd You're now ready to enable the application in LibreNMS. Privoxy For this to work, the following log items need enabled for Privoxy. debug 2 # show each connection status debug 512 # Common Log Format debug 1024 # Log the destination for requests Privoxy didn't let through, and the reason why. debug 4096 # Startup banner and warnings debug 8192 # Non-fatal errors SNMP Extend Download the extend and make sure it is executable. wget https://github.com/librenms/librenms-agent/raw/master/snmp/privoxy -O /etc/snmp/privoxy chmod +x /etc/snmp/privoxy Install the depdenencies. # FreeBSD pkg install p5-File-ReadBackwards p5-Time-Piece p5-JSON p5-IPC-Run3 p5-Gzip-Faster p5-MIME-Base64 # Debian apt-get install cpanminus zlib1g cpanm File::ReadBackwards Time::Piece JSON IPC::Run3 MIME::Base64 Gzip::Faster Add the extend to snmpd.conf and restart snmpd. extend privoxy /etc/snmp/privoxy If your logfile is not at /var/log/privoxy/logfile , that may be changed via the -f option. If privoxy-log-parser.pl is not found in your standard $PATH setting, you may will need up call the extend via /usr/bin/env with a $PATH set to something that includes it. Once that is done, just wait for the server to be rediscovered or just enable it manually. Pwrstatd Pwrstatd (commonly known as powerpanel) is an application/service available from CyberPower to monitor their PSUs over USB. It is currently capable of reading the status of only one PSU connected via USB at a time. The powerpanel software is available here: https://www.cyberpowersystems.com/products/software/power-panel-personal/ SNMP Extend Copy the python script, pwrstatd.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/pwrstatd.py -O /etc/snmp/pwrstatd.py Make the script executable chmod +x /etc/snmp/pwrstatd.py Edit your snmpd.conf file and add: extend pwrstatd /etc/snmp/pwrstatd.py (Optional) Create a /etc/snmp/pwrstatd.json file and specify the path to the pwrstat executable [the default path is /sbin/pwrstat]: { \"pwrstat_cmd\": \"/sbin/pwrstat\" } Restart snmpd. Proxmox For Proxmox 4.4+ install the libpve-apiclient-perl package apt install libpve-apiclient-perl Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/proxmox -O /usr/local/bin/proxmox Make the script executable chmod +x /usr/local/bin/proxmox Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend proxmox /usr/local/bin/proxmox Note: if your snmpd doesn't run as root, you might have to invoke the script using sudo and modify the \"extend\" line extend proxmox /usr/bin/sudo /usr/local/bin/proxmox after, edit your sudo users (usually visudo ) and add at the bottom: Debian-snmp ALL=(ALL) NOPASSWD: /usr/local/bin/proxmox Restart snmpd on your host Puppet Agent SNMP extend script to get your Puppet Agent data into your host. SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/puppet_agent.py -O /etc/snmp/puppet_agent.py Make the script executable chmod +x /etc/snmp/puppet_agent.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend puppet-agent /etc/snmp/puppet_agent.py The Script needs python3-yaml package to be installed. Per default script searches for on of this files: /var/cache/puppet/state/last_run_summary.yaml /opt/puppetlabs/puppet/cache/state/last_run_summary.yaml optionally you can add a specific summary file with creating /etc/snmp/puppet.json { \"agent\": { \"summary_file\": \"/my/custom/path/to/summary_file\" } } custom summary file has highest priority Restart snmpd on the host PureFTPd SNMP extend script to monitor PureFTPd. SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/pureftpd.py -O /etc/snmp/pureftpd.py Make the script executable chmod +x /etc/snmp/pureftpd.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend pureftpd sudo /etc/snmp/pureftpd.py Edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /etc/snmp/pureftpd.py or the path where your pure-ftpwho is located If pure-ftpwho is not located in /usr/sbin you will also need to create a config file, which is named pureftpd.json. The file has to be located in /etc/snmp/. {\"pureftpwho_cmd\": \"/usr/sbin/pure-ftpwho\" } Restart snmpd on your host Raspberry PI SNMP extend script to get your PI data into your host. SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/raspberry.sh -O /etc/snmp/raspberry.sh Make the script executable chmod +x /etc/snmp/raspberry.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend raspberry /usr/bin/sudo /bin/sh /etc/snmp/raspberry.sh Edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /bin/sh /etc/snmp/raspberry.sh Note: If you are using Raspian, the default user is Debian-snmp . Change snmp above to Debian-snmp . You can verify the user snmpd is using with ps aux | grep snmpd Restart snmpd on PI host Raspberry Pi GPIO Monitor SNMP extend script to monitor your IO pins or sensor modules connected to your GPIO header. SNMP Extend 1: Make sure you have wiringpi installed on your Raspberry Pi. In Debian-based systems for example you can achieve this by issuing: apt-get install wiringpi 2: Download the script to your Raspberry Pi. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/rpigpiomonitor.php -O /etc/snmp/rpigpiomonitor.php 3: (optional) Download the example configuration to your Raspberry Pi. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/rpigpiomonitor.ini -O /etc/snmp/rpigpiomonitor.ini 4: Make the script executable: chmod +x /etc/snmp/rpigpiomonitor.php 5: Create or edit your rpigpiomonitor.ini file according to your needs. 6: Check your configuration with rpigpiomonitor.php -validate 7: Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend rpigpiomonitor /etc/snmp/rpigpiomonitor.php 8: Restart snmpd on your Raspberry Pi and, if your Raspberry Pi is already present in LibreNMS, perform a manual rediscover. Redis Script to monitor your Redis Server SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/redis.py -O /etc/snmp/redis.py Make the script executable chmod +x /etc/snmp/redis.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend redis /etc/snmp/redis.py (Optional) If you have SELinux in Enforcing mode, you must add a module so the script can get redis informations and write them: cat << EOF > snmpd_redis.te module snmpd_redis 1.0; require { type tmp_t; type redis_port_t; type snmpd_t; class tcp_socket name_connect; class dir { add_name write }; } #============= snmpd_t ============== allow snmpd_t redis_port_t:tcp_socket name_connect; allow snmpd_t tmp_t:dir { write add_name }; EOF checkmodule -M -m -o snmpd_redis.mod snmpd_redis.te semodule_package -o snmpd_redis.pp -m snmpd_redis.mod semodule -i snmpd_redis.pp Agent Install the agent on this device if it isn't already and copy the redis script to /usr/lib/check_mk_agent/local/ RRDCached Install/Setup: For Install/Setup Local Librenms RRDCached: Please see RRDCached Will collect stats by: 1. Connecting directly to the associated device on port 42217 2. Monitor thru snmp with SNMP extend, as outlined below 3. Connecting to the rrdcached server specified by the rrdcached setting SNMP extend script to monitor your (remote) RRDCached via snmp SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/rrdcached -O /etc/snmp/rrdcached Make the script executable chmod +x /etc/snmp/rrdcached Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend rrdcached /etc/snmp/rrdcached SDFS info A small shell script that exportfs SDFS volume info. SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/sdfsinfo -O /etc/snmp/sdfsinfo Make the script executable chmod +x /etc/snmp/sdfsinfo Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend sdfsinfo /etc/snmp/sdfsinfo Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Seafile SNMP extend script to monitor your Seafile Server SNMP Extend Copy the Python script, seafile.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/seafile.py -O /etc/snmp/seafile.py Also you have to install the requests Package for Python3. Under Ubuntu/Debian just run apt install python3-requests Make the script executable chmod +x /etc/snmp/seafile.py Edit your snmpd.conf file and add: extend seafile /etc/snmp/seafile.py You will also need to create the config file, which is named seafile.json . The script has to be located at /etc/snmp/. {\"url\": \"https://seafile.mydomain.org\", \"username\": \"some_admin_login@mail.address\", \"password\": \"password\", \"account_identifier\": \"name\" \"hide_monitoring_account\": true } The variables are as below. url = Url how to get access to Seafile Server username = Login to Seafile Server. It is important that used Login has admin privileges. Otherwise most API calls will be denied. password = Password to the configured login. account_identifier = Defines how user accounts are listed in RRD Graph. Options are: name, email hide_monitoring_account = With this Boolean you can hide the Account which you use to access Seafile API Note: It is recommended to use a dedicated Administrator account for monitoring. SMART SNMP Extend Copy the Perl script, smart, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/smart-v1 -O /etc/snmp/smart Install the depends. # FreeBSD pkg install p5-JSON p5-MIME-Base64 smartmontools # Debian apt-get install cpanminus smartmontools cpanm MIME::Base64 JSON # CentOS dnf install smartmontools perl-JSON perl-MIME-Base64 Make the script executable chmod +x /etc/snmp/smart Edit your snmpd.conf file and add: extend smart /etc/snmp/smart You will also need to create the config file, which defaults to the same path as the script, but with .config appended. So if the script is located at /etc/snmp/smart, the config file will be /etc/snmp/smart.config . Alternatively you can also specific a config via -c . Anything starting with a # is comment. The format for variables is $variable=$value. Empty lines are ignored. Spaces and tabes at either the start or end of a line are ignored. Any line with out a matched variable or # are treated as a disk. #This is a comment cache=/var/cache/smart smartctl=/usr/bin/env smartctl useSN=1 ada0 ada1 da5 /dev/da5 -d sat twl0,0 /dev/twl0 -d 3ware,0 twl0,1 /dev/twl0 -d 3ware,1 twl0,2 /dev/twl0 -d 3ware,2 The variables are as below. cache = The path to the cache file to use. Default: /var/cache/smart smartctl = The path to use for smartctl. Default: /usr/bin/env smartctl useSN = If set to 1, it will use the disks SN for reporting instead of the device name. 1 is the default. 0 will use the device name. A disk line is can be as simple as just a disk name under /dev/. Such as in the config above The line \"ada0\" would resolve to \"/dev/ada0\" and would be called with no special argument. If a line has a space in it, everything before the space is treated as the disk name and is what used for reporting and everything after that is used as the argument to be passed to smartctl. If you want to guess at the configuration, call it with -g and it will print out what it thinks it should be. Restart snmpd on your host If you have a large number of more than one or two disks on a system, you should consider adding this to cron. Also make sure the cache file is some place it can be written to. */5 * * * * /etc/snmp/smart -u If your snmp agent runs as user \"snmp\", edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /etc/snmp/smart, /usr/bin/env smartctl and modify your snmpd.conf file accordingly, sudo can be excluded if running it via cron: extend smart /usr/bin/sudo /etc/snmp/smart The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Optionally setup nightly self tests for the disks. The exend will run the specified test on all configured disks if called with the -t flag and the name of the SMART test to run. 0 0 * * * /etc/snmp/smart -t long Sneck This is for replacing Nagios/Icinga or the LibreNMS service integration in regards to NRPE. This allows LibreNMS to query what checks were ran on the server and keep track of totals of OK, WARNING, CRITICAL, and UNKNOWN statuses. The big advantage over this compared to a NRPE are as below. It does not need to know what checks are configured on it. Also does not need to wait for the tests to run as sneck is meant to be ran via cron and the then return the cache when queried via SNMP, meaning a lot faster response time, especially if slow checks are being performed. Works over proxied SNMP connections. Included are alert examples. Although for setting up custom ones, the metrics below are provided. Metric Description ok Total OK checks warning Total WARNING checks critical Total CRITICAL checks unknown Total UNKNOWN checks errored Total checks that errored time_to_polling Differnce in seconds between when polling data was generated and when polled time_to_polling_abs The absolute value of time_to_polling. check_$CHECK Exit status of a specific check $CHECK is equal to the name of the check in question. So foo would be check_foo The standard Nagios/Icinga style exit codes are used and those are as below. Exit Meaning 0 okay 1 warning 2 critical 3+ unknown To use time_to_polling , it will need to enabled via setting the config item below. The default is false. Unless set to true, this value will default to 0. If enabling this, one will want to make sure that NTP is in use every were or it will alert if it goes over a difference of 540s. lnms config:set app.sneck.polling_time_diff true For more information on Sneck, check it out at MetaCPAN or Github . For poking systems using Sneck, also check out boop_snoot if one wants to query those systems via the CLI. Docs on it at MetaCPAN and Github . SNMP Extend Install the extend. # FreeBSD pkg install p5-JSON p5-File-Slurp p5-MIME-Base64 p5-Gzip-Faster p5-App-cpanminus cpanm Monitoring::Sneck # Debian based systems apt-get install zlib1g-dev cpanminus cpanm Monitoring::Sneck Configure any of the checks you want to run in /usr/local/etc/sneck.conf . You con find it documented here . Set it up in cron. This will mean you don't need to wait for all the checks to complete when polled via SNMP, which for like SMART or other long running checks will mean it timing out. Also means it does not need called via sudo as well. */5 * * * * /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin /usr/local/bin/sneck -u 2> /dev/null > /dev/null Set it up in the snmpd config and restart snmpd. The -c flag will tell read it to read from cache instead of rerunning the checks. extend sneck /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin /usr/local/bin/sneck -c In LibreNMS, enable the application for the server in question or wait for auto discovery to find it. Squid SNMP Proxy Enable SNMP for Squid like below, if you have not already, and restart it. acl snmppublic snmp_community public snmp_port 3401 snmp_access allow snmppublic localhost snmp_access deny all Restart squid on your host. Edit your snmpd.conf file and add, making sure you have the same community, host, and port as above: proxy -v 2c -Cc -c public 127.0.0.1:3401 1.3.6.1.4.1.3495 For more advanced information on Squid and SNMP or setting up proxying for net-snmp, please see the links below. http://wiki.squid-cache.org/Features/Snmp http://www.net-snmp.org/wiki/index.php/Snmpd_proxy Supervisord It shows you the totals per status and also the uptime per process. That way you can add alerts for instance when there are process in state FATAL . SNMP Extend Copy the python script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/supervisord.py -O /etc/snmp/supervisord.py Notice that this will use the default unix socket path. Modify the unix_socket_path variable in the script if your path differs from the default. Make the script executable chmod +x /etc/snmp/supervisord.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend supervisord /etc/snmp/supervisord.py Restart snmpd on your host systemctl restart snmpd Sagan For metrics the stats are migrated as below from the stats JSON. f_drop_percent and drop_percent are computed based on the found data. Instance Key Stats JSON Key uptime .stats.uptime total .stats.captured.total drop .stats.captured.drop ignore .stats.captured.ignore threshold .stats.captured.theshold after .stats.captured.after match .stats.captured.match bytes .stats.captured.bytes_total bytes_ignored .stats.captured.bytes_ignored max_bytes_log_line .stats.captured.max_bytes_log_line eps .stats.captured.eps f_total .stats.flow.total f_dropped .stats.flow.dropped Those keys are appended with the name of the instance running with _ between the instance name and instance metric key. So uptime for ids would be ids_uptime . The default is named 'ids' unless otherwise specified via the extend. There is a special instance name of .total which is the total of all the instances. So if you want the total eps, the metric would be .total_eps . Also worth noting that the alert value is the highest one found among all the instances. SNMP Extend Install the extend. cpanm Sagan::Monitoring Setup cron. Below is a example. */5 * * * * /usr/local/bin/sagan_stat_check > /dev/null Configure snmpd.conf extend sagan-stats /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin sagan_stat_check -c Restart snmpd on your system. You will want to make sure that sagan is setup to with the values set below for stats-json processor, for a single instance setup.. enabled: yes time: 300 subtract_old_values: true filename: \"$LOG_PATH/stats.json\" Any configuration of sagan_stat_check should be done in the cron setup. If the default does not work, check the docs for it at MetaCPAN for sagan_stat_check Socket Statistics (ss) The Socket Statistics application polls ss and scrapes socket statuses. Individual sockets and address-families may be filtered out within the script's optional configuration JSON file. The following socket types are polled directly. Filtering a socket type will disable direct polling as-well-as indirect polling within any address-families that list the socket type as their child: dccp (also exists within address-families \"inet\" and \"inet6\") mptcp (also exists within address-families \"inet\" and \"inet6\") raw (also exists within address-families \"inet\" and \"inet6\") sctp (also exists within address-families \"inet\" and \"inet6\") tcp (also exists within address-families \"inet\" and \"inet6\") udp (also exists within address-families \"inet\" and \"inet6\") xdp The following socket types are polled within an address-family only: inet6 (within address-family \"inet6\") p_dgr (within address-family \"link\") p_raw (within address-family \"link\") ti_dg (within address-family \"tipc\") ti_rd (within address-family \"tipc\") ti_sq (within address-family \"tipc\") ti_st (within address-family \"tipc\") v_dgr (within address-family \"vsock\") v_str (within address-family \"vsock\") unknown (within address-families \"inet\", \"inet6\", \"link\", \"tipc\", and \"vsock\") The following address-families are polled directly and have their child socket types tab-indented below them. Filtering a socket type (see \"1\" above) will filter it from the address-family. Filtering an address-family will filter out all of its child socket types. However, if those socket types are not DIRECTLY filtered out (see \"1\" above), then they will continue to be monitored either directly or within other address-families in which they exist: inet dccp mptcp raw sctp tcp udp unknown inet6 dccp icmp6 mptcp raw sctp tcp udp unknown link p_dgr p_raw unknown netlink tipc ti_dg ti_rd ti_sq ti_st unknown unix u_dgr u_seq u_str vsock v_dgr v_str unknown SNMP Extend Copy the python script, ss.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/ss.py -O /etc/snmp/ss.py Make the script executable chmod +x /etc/snmp/ss.py Edit your snmpd.conf file and add: extend ss /etc/snmp/ss.py (Optional) Create a /etc/snmp/ss.json file and specify: \"ss_cmd\" - String path to the ss binary: [\"/sbin/ss\"] \"socket_types\" - A comma-delimited list of socket types to include. The following socket types are valid: dccp, icmp6, mptcp, p_dgr, p_raw, raw, sctp, tcp, ti_dg, ti_rd, ti_sq, ti_st, u_dgr, u_seq, u_str, udp, unknown, v_dgr, v_dgr, xdp. Please note that the \"unknown\" socket type is represented in /sbin/ss output with the netid \"???\". Please also note that the p_dgr and p_raw socket types are specific to the \"link\" address family; the ti_dg, ti_rd, ti_sq, and ti_st socket types are specific to the \"tipc\" address family; the u_dgr, u_seq, and u_str socket types are specific to the \"unix\" address family; and the v_dgr and v_str socket types are specific to the \"vsock\" address family. Filtering out the parent address families for the aforementioned will also filter out their specific socket types. Specifying \"all\" includes all of the socket types. For example: to include only tcp, udp, icmp6 sockets, you would specify \"tcp,udp,icmp6\": [\"all\"] \"addr_families\" - A comma-delimited list of address families to include. The following families are valid: inet, inet6, link, netlink, tipc, unix, vsock. As mentioned above under (b), filtering out the link, tipc, unix, or vsock address families will also filter out their respective socket types. Specifying \"all\" includes all of the families. For example: to include only inet and inet6 families, you would specify \"inet,inet6\": [\"all\"] { \"ss_cmd\": \"/sbin/ss\", \"socket_types\": \"all\" \"addr_families\": \"all\" } In order to filter out uncommon/unused socket types, the following JSON configuration is recommended: { \"ss_cmd\": \"/sbin/ss\", \"socket_types\": \"icmp6,p_dgr,p_raw,raw,tcp,u_dgr,u_seq,u_str,udp\", \"addr_families\": \"inet,inet6,link,netlink,unix\" } (Optional) If SELinux is in Enforcing mode, you must add a module so the script can poll sockets: cat << EOF > snmpd_ss.te module snmp_ss 1.0; require { type snmpd_t; class netlink_tcpdiag_socket { bind create getattr nlmsg_read read setopt write }; } #============= snmpd_t ============== allow snmpd_t self:netlink_tcpdiag_socket { bind create getattr nlmsg_read read setopt write }; EOF checkmodule -M -m -o snmpd_ss.mod snmpd_ss.te semodule_package -o snmpd_ss.pp -m snmpd_ss.mod semodule -i snmpd_ss.pp Restart snmpd. Suricata SNMP Extend Install the extend. cpanm Suricata::Monitoring Setup cron. Below is a example. */5 * * * * /usr/local/bin/suricata_stat_check > /dev/null Configure snmpd.conf extend suricata-stats /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin suricata_stat_check -c Or if you want to use try compressing the return via Base64+GZIP... extend suricata-stats /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin suricata_stat_check -c -b Restart snmpd on your system. You will want to make sure Suricata is set to output the stats to the eve file once a minute. This will help make sure that it won't be to far back in the file and will make sure it is recent when the cronjob runs. Any configuration of suricata_stat_check should be done in the cron setup. If the default does not work, check the docs for it at MetaCPAN for suricata_stat_check Suricata Extract SNMP Add the following to your snmpd config and restart. Path may have to be adjusted depending on where suricata_extract_submit_extend is installed to. extend suricata_extract /usr/local/bin/suricata_extract_submit_extend Then just wait for the system to be rediscovered or enable it manually for the server in question. Systemd The systemd application polls systemd and scrapes systemd units' load, activation, and sub states. SNMP Extend Copy the python script, systemd.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/systemd.py -O /etc/snmp/systemd.py Make the script executable chmod +x /etc/snmp/systemd.py Edit your snmpd.conf file and add: extend systemd /etc/snmp/systemd.py (Optional) Create a /etc/snmp/systemd.json file and specify: \"systemctl_cmd\" - String path to the systemctl binary [Default: \"/usr/bin/systemctl\"] \"include_inactive_units\" - True/False string to include inactive units in results [Default: \"False\"] { \"systemctl_cmd\": \"/bin/systemctl\", \"include_inactive_units\": \"True\" } (Optional) If you have SELinux in Enforcing mode, you must add a module so the script can access systemd state: cat << EOF > snmpd_systemctl.te module snmpd_systemctl 1.0; require { type snmpd_t; type systemd_systemctl_exec_t; type init_t; class file { execute execute_no_trans map open read }; class unix_stream_socket connectto; class system status; } #============= snmpd_t ============== allow snmpd_t init_t:system status; allow snmpd_t init_t:unix_stream_socket connectto; allow snmpd_t systemd_systemctl_exec_t:file { execute execute_no_trans map open read }; EOF checkmodule -M -m -o snmpd_systemctl.mod snmpd_systemctl.te semodule_package -o snmpd_systemctl.pp -m snmpd_systemctl.mod semodule -i snmpd_systemctl.pp Restart snmpd. TinyDNS aka djbdns Agent Install the agent on this device if it isn't already and copy the tinydns script to /usr/lib/check_mk_agent/local/ Note : We assume that you use DJB's Daemontools to start/stop tinydns. And that your tinydns instance is located in /service/dns , adjust this path if necessary. Replace your log 's run file, typically located in /service/dns/log/run with: #!/bin/sh exec setuidgid dnslog tinystats ./main/tinystats/ multilog t n3 s250000 ./main/ Create tinystats directory and chown: mkdir /service/dns/log/main/tinystats chown dnslog:nofiles /service/dns/log/main/tinystats Restart TinyDNS and Daemontools: /etc/init.d/svscan restart Note : Some say svc -t /service/dns is enough, on my install (Gentoo) it doesn't rehook the logging and I'm forced to restart it entirely. Unbound Unbound configuration: # Enable extended statistics. server: extended-statistics: yes statistics-cumulative: yes remote-control: control-enable: yes control-interface: 127.0.0.1 Restart your unbound after changing the configuration, verify it is working by running unbound-control stats . Option 1. SNMP Extend (Preferred and easiest method) Copy the shell script, unbound, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/unbound -O /etc/snmp/unbound Make the script executable chmod +x /etc/snmp/unbound Edit your snmpd.conf file and add: extend unbound /usr/bin/sudo /etc/snmp/unbound Restart snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Option 2. Agent Install the agent on this device if it isn't already and copy the unbound.sh script to /usr/lib/check_mk_agent/local/ UPS-nut A small shell script that exports nut ups status. SNMP Extend Copy the shell script, unbound, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/ups-nut.sh -O /etc/snmp/ups-nut.sh Make the script executable chmod +x /etc/snmp/ups-nut.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ups-nut /etc/snmp/ups-nut.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Optionally if you have multiple UPS or your UPS is not named APCUPS you can specify its name as an argument into /etc/snmp/ups-nut.sh extend ups-nut /etc/snmp/ups-nut.sh ups1 extend ups-nut /etc/snmp/ups-nut.sh ups2 UPS-apcups A small shell script that exports apcacess ups status. SNMP Extend Copy the shell script, unbound, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/ups-apcups -O /etc/snmp/ups-apcups Make the script executable chmod +x /etc/snmp/ups-apcups Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ups-apcups /etc/snmp/ups-apcups If 'apcaccess' is not in the PATH enviromental variable snmpd is using, you may need to do something like below. extend ups-apcups/usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin /etc/snmp/ups-apcups Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Voip-monitor Shell script that reports cpu-load/memory/open-files files stats of Voip Monitor SNMP Extend Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/voipmon-stats.sh -O /etc/snmp/voipmon-stats.sh Make the script executable chmod +x /etc/snmp/voipmon-stats.sh Edit your snmpd.conf file (usually /etc/snmp/voipmon-stats.sh ) and add: extend voipmon /etc/snmp/voipmon-stats.sh Wireguard The Wireguard application polls the Wireguard service and scrapes all client statistics for all interfaces configured as Wireguard interfaces. SNMP Extend Copy the python script, wireguard.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/wireguard.py -O /etc/snmp/wireguard.py Make the script executable chmod +x /etc/snmp/wireguard.py Edit your snmpd.conf file and add: extend wireguard /etc/snmp/wireguard.py Create a /etc/snmp/wireguard.json file and specify: (optional) \"wg_cmd\" - String path to the wg binary [\"/usr/bin/wg\"] \"public_key_to_arbitrary_name\" - A dictionary to convert between the publickey assigned to the client (specified in the wireguard interface conf file) to an arbitrary, friendly name. The friendly names MUST be unique within each interface. Also note that the interface name and friendly names are used in the RRD filename, so using special characters is highly discouraged. { \"wg_cmd\": \"/bin/wg\", \"public_key_to_arbitrary_name\": { \"wg0\": { \"z1iSIymFEFi/PS8rR19AFBle7O4tWowMWuFzHO7oRlE=\": \"client1\", \"XqWJRE21Fw1ke47mH1yPg/lyWqCCfjkIXiS6JobuhTI=\": \"server.domain.com\" } } } Restart snmpd. ZFS SNMP Extend 1: Install the depends. ### FreeBSD pkg install p5-JSON p5-MIME-Base64 p5-Gzip-Faster ### Debian apt-get install -y cpanminus zlib1g-dev cpanm Mime::Base64 JSON Gzip::Faster 2: Fetch the script in question and make it executable. wget https://github.com/librenms/librenms-agent/raw/master/snmp/zfs -O /etc/snmp/zfs chmod +x /etc/snmp/zfs 3: Add the following to snmpd.conf and restart snmpd. extend zfs /etc/snmp/zfs","title":"Applications"},{"location":"Extensions/Applications/#applications","text":"You can use Application support to graph performance statistics of many applications. Different applications support a variety of ways to collect data: By direct connection to the application snmpd extend The agent . The monitoring of applications could be added before or after the hosts have been added to LibreNMS. If multiple methods of collection are listed you only need to enable one.","title":"Applications"},{"location":"Extensions/Applications/#snmp-extend","text":"When using the snmp extend method, the application discovery module will pick up which applications you have set up for monitoring automatically, even if the device is already in LibreNMS. The application discovery module is enabled by default for most *nix operating systems, but in some cases you will need to manually enable the application discovery module.","title":"SNMP Extend"},{"location":"Extensions/Applications/#sudo","text":"One major thing to keep in mind when using SNMP extend is these run as the snmpd user that can be an unprivileged user. In these situations you need to use sudo. To test if you need sudo, first check the user snmpd is running as. Then test if you can run the extend script as that user without issue. For example if snmpd is running as 'Debian-snmp' and we want to run the extend for proxmox, we check that the following run without error: sudo -u Debian-snmp /usr/local/bin/proxmox If it doesn't work, then you will need to use sudo with the extend command. For the example above, that would mean adding the line below to the sudoers file: Debian-snmp ALL = NOPASSWD: /usr/local/bin/proxmox Finally we would need to add sudo to the extend command, which would look like that for proxmox: extend proxmox /usr/bin/sudo /usr/local/bin/proxmox","title":"SUDO"},{"location":"Extensions/Applications/#json-return-optimization-using-librenms_return_optimizer","text":"While the json_app_get does allow for more complex and larger data to be easily returned by a extend and the data to then be worked with, this can also sometimes result in large returns that occasionally don't play nice with SNMP on some networks. librenms_return_optimizer fixes this via taking the extend output piped to it, gzipping it, and then converting it to base64. The later is needed as net-snmp does not play that nice with binary data, converting most of the non-printable characters to . . This does add a bit of additional overhead to the gzipped data, but still tends to be result in a return that is usually a third of the size for JSONs items. The change required is fairly simply. So for the portactivity example below... extend portactivity /etc/snmp/extends/portactivity smtps,http,imap,imaps,postgresql,https,ldap,ldaps,nfsd,syslog-conn,ssh,matrix,gitea Would become this... extend portactivity /usr/local/bin/lnms_return_optimizer -- /etc/snmp/extends/portactivity smtps,http,imap,imaps,postgresql,https,ldap,ldaps,nfsd,syslog-conn,ssh,matrix,gitea The requirements for this are Perl, MIME::Base64, and Gzip::Faster. Installing on FreeBSD... pkg install p5-MIME-Base64 p5-Gzip-Faster wget wget https://raw.githubusercontent.com/librenms/librenms-agent/master/utils/librenms_return_optimizer -O /usr/local/bin/librenms_return_optimizer chmod +x /usr/local/bin/librenms_return_optimizer Installing on Debian... apt-get install zlib1g-dev cpanminus wget cpanm Gzip::Faster cpanm MIME::Base64 wget https://raw.githubusercontent.com/librenms/librenms-agent/master/utils/librenms_return_optimizer -O /usr/local/bin/librenms_return_optimizer chmod +x /usr/local/bin/librenms_return_optimizer Currently supported applications as are below. backupninja certificate chronyd dhcp-stats docker fail2ban fbsd-nfs-client fbsd-nfs-server gpsd mailcow-postfix mdadm ntp-client ntp-server portactivity powerdns powermon puppet-agent pureftpd redis seafile supervisord ups-apcups zfs The following apps have extends that have native support for this, if congiured to do so. suricata","title":"JSON Return Optimization Using librenms_return_optimizer"},{"location":"Extensions/Applications/#enable-the-application-discovery-module","text":"Edit the device for which you want to add this support Click on the Modules tab and enable the applications module. This will be automatically saved, and you should get a green confirmation pop-up message. After you have enabled the application module, it would be wise to then also enable which applications you want to monitor, in the rare case where LibreNMS does not automatically detect it. Note : Only do this if an application was not auto-discovered by LibreNMS during discovery and polling.","title":"Enable the application discovery module"},{"location":"Extensions/Applications/#enable-the-applications-to-be-discovered","text":"Go to the device you have just enabled the application module for. Click on the Applications tab and select the applications you want to monitor. This will also be automatically saved, and you should get a green confirmation pop-up message.","title":"Enable the application(s) to be discovered"},{"location":"Extensions/Applications/#agent","text":"The unix-agent does not have a discovery module, only a poller module. That poller module is always disabled by default. It needs to be manually enabled if using the agent. Some applications will be automatically enabled by the unix-agent poller module. It is better to ensure that your application is enabled for monitoring. You can check by following the steps under the SNMP Extend heading.","title":"Agent"},{"location":"Extensions/Applications/#apache","text":"Either use SNMP extend or use the agent. Note that you need to install and configure the Apache mod_status module before trying the script.","title":"Apache"},{"location":"Extensions/Applications/#snmp-extend_1","text":"Download the script onto the desired host (the host must be added to LibreNMS devices) wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/apache-stats.py -O /etc/snmp/apache-stats.py Make the script executable chmod +x /etc/snmp/apache-stats.py Create the cache directory, '/var/cache/librenms/' and make sure that it is owned by the user running the SNMP daemon. mkdir -p /var/cache/librenms/ Verify it is working by running /etc/snmp/apache-stats.py Package urllib3 for python3 needs to be installed. In Debian-based systems for example you can achieve this by issuing: apt-get install python3-urllib3 Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend apache /etc/snmp/apache-stats.py Restart snmpd on your host Test by running snmpwalk localhost NET-SNMP-EXTEND-MIB::nsExtendOutput2Table","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_1","text":"Install the agent on this device if it isn't already and copy the apache script to /usr/lib/check_mk_agent/local/ Verify it is working by running /usr/lib/check_mk_agent/local/apache (If you get error like \"Can't locate LWP/Simple.pm\". libwww-perl needs to be installed: apt-get install libwww-perl) Create the cache directory, '/var/cache/librenms/' and make sure that it is owned by the user running the SNMP daemon. mkdir -p /var/cache/librenms/ On the device page in Librenms, edit your host and check the Apache under the Applications tab.","title":"Agent"},{"location":"Extensions/Applications/#asterisk","text":"A small shell script that reports various Asterisk call status.","title":"Asterisk"},{"location":"Extensions/Applications/#snmp-extend_2","text":"Download the asterisk script to /etc/snmp/ on your asterisk server. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/asterisk -O /etc/snmp/asterisk Make the script executable chmod +x /etc/snmp/asterisk Configure ASCLI in the script. Verify it is working by running /etc/snmp/asterisk Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend asterisk /etc/snmp/asterisk Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#backupninja","text":"A small shell script that reports status of last backupninja backup.","title":"backupninja"},{"location":"Extensions/Applications/#snmp-extend_3","text":"Download the backupninja script to /etc/snmp/backupninja.py on your backuped server. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/backupninja.py -O /etc/snmp/backupninja.py` Make the script executable: chmod +x /etc/snmp/backupninja.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend backupninja /etc/snmp/backupninja.py Restart snmpd on your host","title":"SNMP Extend"},{"location":"Extensions/Applications/#bind9-aka-named","text":"Create stats file with appropriate permissions: touch /var/cache/bind/stats chown bind:bind /var/cache/bind/stats Change user:group to the user and group that's running bind/named. Bind/named configuration: options { ... statistics-file \"/var/cache/bind/stats\"; zone-statistics yes; ... }; Restart your bind9/named after changing the configuration. Verify that everything works by executing rndc stats && cat /var/cache/bind/stats . In case you get a Permission Denied error, make sure you changed the ownership correctly. Also be aware that this file is appended to each time rndc stats is called. Given this it is suggested you setup file rotation for it. Alternatively you can also set zero_stats to 1 in the config. The script for this also requires the Perl module File::ReadBackwards . FreeBSD => p5-File-ReadBackwards CentOS/RedHat => perl-File-ReadBackwards Debian/Ubuntu => libfile-readbackwards-perl If it is not available, it can be installed by cpan -i File::ReadBackwards . You may possibly need to configure the agent/extend script as well. The config file's path defaults to the same path as the script, but with .config appended. So if the script is located at /etc/snmp/bind , the config file will be /etc/snmp/bind.config . Alternatively you can also specify a config via -c $file . Anything starting with a # is comment. The format for variables are $variable=$value. Empty lines are ignored. Spaces and tabs at either the start or end of a line are ignored. Content of an example /etc/snmp/bind.config . Please edit with your own settings. rndc = The path to rndc. Default: /usr/bin/env rndc call_rndc = A 0/1 boolean on whether or not to call rndc stats. Suggest to set to 0 if using netdata. Default: 1 stats_file = The path to the named stats file. Default: /var/cache/bind/stats agent = A 0/1 boolean for if this is being used as a LibreNMS agent or not. Default: 0 zero_stats = A 0/1 boolean for if the stats file should be zeroed first. Default: 0 (1 if guessed) If you want to guess at the configuration, call the script with -g and it will print out what it thinks it should be.","title":"BIND9 aka named"},{"location":"Extensions/Applications/#snmp-extend_4","text":"Copy the bind shell script, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/bind -O /etc/snmp/bind Make the script executable chmod +x /etc/snmp/bind Edit your snmpd.conf file and add: extend bind /etc/snmp/bind Restart snmpd on the host in question. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_2","text":"Install the agent on this device if it isn't already and copy the script to /usr/lib/check_mk_agent/local/bind via wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/bind -O /usr/lib/check_mk_agent/local/bind Make the script executable chmod +x /usr/lib/check_mk_agent/local/bind Set the variable 'agent' to '1' in the config.","title":"Agent"},{"location":"Extensions/Applications/#bird2","text":"The BIRD Internet Routing Daemon (BGP) Due to the lack of SNMP support in the BIRD daemon, this application extracts all configured BGP protocols and parses it into LibreNMS. This application supports both IPv4 and IPv6 Peer processing.","title":"BIRD2"},{"location":"Extensions/Applications/#snmp-extend_5","text":"Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend bird2 '/usr/bin/sudo /usr/sbin/birdc -r show protocols all' Edit your sudo users (usually visudo ) and add at the bottom: Debian-snmp ALL=(ALL) NOPASSWD: /usr/sbin/birdc If your snmp daemon is running on a user that isnt Debian-snmp make sure that user has the correct permission to execute birdc Verify the time format for bird2 is defined. Otherwise iso short ms (hh:mm:ss) is the default value that will be used. Which is not compatible with the datetime parsing logic used to parse the output from the bird show command. timeformat protocol is the one important to be defibned for the bird2 app parsing logic to work. Example starting point using Bird2 shorthand iso long (YYYY-MM-DD hh:mm:ss): timeformat base iso long; timeformat log iso long; timeformat protocol iso long; timeformat route iso long; Timezone can be manually specified, example \"%F %T %z\" (YYYY-MM-DD hh:mm:ss +11:45). See the Bird 2 docs for more information Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#certificate","text":"A small python3 script that checks age and remaining validity of certificates This script needs following packages on Debian/Ubuntu Systems: python3 python3-openssl Content of an example /etc/snmp/certificate.json . Please edit with your own settings. {\"domains\": [ {\"fqdn\": \"www.mydomain.com\"}, {\"fqdn\": \"some.otherdomain.org\", \"port\": 8443}, {\"fqdn\": \"personal.domain.net\"}, {\"fqdn\": \"selfsignedcert_host.domain.com\", \"cert_location\": \"/etc/pki/tls/certs/localhost.pem\"} ] } a. (Required): Key 'domains' contains a list of domains to check. b. (Optional): You can define a port. By default it checks on port 443. c. (Optional): You may define a certificate location for self-signed certificates.","title":"Certificate"},{"location":"Extensions/Applications/#snmp-extend_6","text":"Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/certificate.py -O /etc/snmp/certificate.py Make the script executable chmod +x /etc/snmp/certificate.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend certificate /etc/snmp/certificate.py Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#borgbackup","text":"","title":"BorgBackup"},{"location":"Extensions/Applications/#snmp-extend_7","text":"Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/borgbackup -O /etc/snmp/borgbackup Make the script executable chmod +x /etc/snmp/borgbackup Install depends. # FreeBSD pkg p5-Config-Tiny p5-JSON p5-File-Slurp p5-MIME-Base64 p5-String-ShellQuote # Debian apt-get install libconfig-tiny-perl libjson-perl libfile-slurp-perl libmime-base64-perl libstring-shellquote-perl # generic cpanm cpanm Config::Tiny File::Slurp JSON MIME::Base64 String::ShellQuote Set it up in cron. */5 * * * /etc/snmp/borgbackup 2> /dev/null > /dev/null Configure it. See further down below or /etc/snmp/borgbackup --help . Add the following to the SNMPD config. extend borgbackup /bin/cat /var/cache/borgbackup_extend/extend_return Restart SNMPD and wait for the device to rediscover or tell it to manually.","title":"SNMP Extend"},{"location":"Extensions/Applications/#config","text":"The config file is a ini file and handled by Config::Tiny . - mode :: single or multi, for if this is a single repo or for multiple repos. - Default :: single - repo :: Directory for the borg backup repo. - Default :: undef - passphrase :: Passphrase for the borg backup repo. - Default :: undef - passcommand :: Passcommand for the borg backup repo. - Default :: undef For single repos all those variables are in the root section of the config, so lets the repo is at '/backup/borg' with a passphrase of '1234abc'. repo=/backup/borg repo=1234abc For multi, each section outside of the root represents a repo. So if there is '/backup/borg1' with a passphrase of 'foobar' and '/backup/derp' with a passcommand of 'pass show backup' it would be like below. mode=multi [borg1] repo=/backup/borg1 passphrase=foobar [derp] repo=/backup/derp passcommand=pass show backup If 'passphrase' and 'passcommand' are both specified, then passcommand is used.","title":"Config"},{"location":"Extensions/Applications/#metrics","text":"The metrics are all from .data.totals in the extend return. Value Type Description errored repos Total number of repos that info could not be fetched for. locked repos Total number of locked repos locked_for seconds Longest time any repo has been locked. time_since_last_modified seconds Largest time - mtime for the repo nonce total_chunks chunks Total number of chunks total_csize bytes Total compressed size of all archives in all repos. total_size byes Total uncompressed size of all archives in all repos. total_unique_chunks chunks Total number of unique chuckes in all repos. unique_csize bytes Total deduplicated size of all archives in all repos. unique_size chunks Total number of chunks in all repos.","title":"Metrics"},{"location":"Extensions/Applications/#capev2","text":"Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/cape -O /etc/snmp/cape Make the script executable chmod +x /etc/snmp/cape Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend cape /etc/snmp/cape Install the required packages. apt-get install libfile-readbackwards-perl libjson-perl libconfig-tiny-perl libdbi-perl libfile-slurp-perl libstatistics-lite-perl Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"CAPEv2"},{"location":"Extensions/Applications/#chip","text":"C.H.I.P. is a $9 R8 based tiny computer ideal for small projects. Further details: https://getchip.com/pages/chip Copy the shell script to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/chip.sh -O /etc/snmp/power-stat.sh Make the script executable chmod +x /etc/snmp/power-stat.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend power-stat /etc/snmp/power-stat.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"C.H.I.P"},{"location":"Extensions/Applications/#docker-stats","text":"It gathers metrics about the docker containers, including: - cpu percentage - memory usage - container size - uptime - Totals per status This script requires python3 and the pip module python-dateutil","title":"Docker Stats"},{"location":"Extensions/Applications/#snmp-extend_8","text":"Install pip module pip3 install python-dateutil Copy the shell script to the desired host. By default, it will only show the status for containers that are running. To include all containers modify the constant in the script at the top of the file and change it to ONLY_RUNNING_CONTAINERS = False wget https://github.com/librenms/librenms-agent/raw/master/snmp/docker-stats.py -O /etc/snmp/docker-stats.py Make the script executable chmod +x /etc/snmp/docker-stats.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend docker /etc/snmp/docker-stats.py If your run Debian, you need to add the Debian-snmp user to the docker group usermod -a -G docker Debian-snmp Restart snmpd on your host systemctl restart snmpd","title":"SNMP Extend"},{"location":"Extensions/Applications/#entropy","text":"A small shell script that checks your system's available random entropy.","title":"Entropy"},{"location":"Extensions/Applications/#snmp-extend_9","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/entropy.sh -O /etc/snmp/entropy.sh Make the script executable chmod +x /etc/snmp/entropy.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend entropy /etc/snmp/entropy.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#exim-stats","text":"SNMP extend script to get your exim stats data into your host.","title":"EXIM Stats"},{"location":"Extensions/Applications/#snmp-extend_10","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/exim-stats.sh -O /etc/snmp/exim-stats.sh Make the script executable chmod +x /etc/snmp/exim-stats.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend exim-stats /etc/snmp/exim-stats.sh If you are using sudo edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /etc/snmp/exim-stats.sh, /usr/bin/exim* Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#fail2ban","text":"","title":"Fail2ban"},{"location":"Extensions/Applications/#snmp-extend_11","text":"Copy the shell script, fail2ban, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/fail2ban -O /etc/snmp/fail2ban Make the script executable chmod +x /etc/snmp/fail2ban Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend fail2ban /etc/snmp/fail2ban If you want to use the cache, it is as below, by using the -c switch. extend fail2ban /etc/snmp/fail2ban -c If you want to use the cache and update it if needed, this can by using the -c and -U switches. extend fail2ban /etc/snmp/fail2ban -c -U If you need to specify a custom location for the fail2ban-client, that can be done via the -f switch. extend fail2ban /etc/snmp/fail2ban -f /foo/bin/fail2ban-client If not specified, \"/usr/bin/env fail2ban-client\" is used. Restart snmpd on your host If you wish to use caching, add the following to /etc/crontab and restart cron. */3 * * * * root /etc/snmp/fail2ban -u Restart or reload cron on your system. If you have more than a few jails configured, you may need to use caching as each jail needs to be polled and fail2ban-client can't do so in a timely manner for than a few. This can result in failure of other SNMP information being polled. For additional details of the switches, please see the POD in the script it self at the top.","title":"SNMP Extend"},{"location":"Extensions/Applications/#freebsd-nfs-client","text":"","title":"FreeBSD NFS Client"},{"location":"Extensions/Applications/#snmp-extend_12","text":"Copy the shell script, fbsdnfsserver, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/fbsdnfsclient -O /etc/snmp/fbsdnfsclient Make the script executable chmod +x /etc/snmp/fbsdnfsclient Edit your snmpd.conf file and add: extend fbsdnfsclient /etc/snmp/fbsdnfsclient Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#freebsd-nfs-server","text":"","title":"FreeBSD NFS Server"},{"location":"Extensions/Applications/#snmp-extend_13","text":"Copy the shell script, fbsdnfsserver, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/fbsdnfsserver -O /etc/snmp/fbsdnfsserver Make the script executable chmod +x /etc/snmp/fbsdnfsserver Edit your snmpd.conf file and add: extend fbsdnfsserver /etc/snmp/fbsdnfsserver Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#freeradius","text":"The FreeRADIUS application extension requires that status_server be enabled in your FreeRADIUS config. For more information see: https://wiki.freeradius.org/config/Status You should note that status requests increment the FreeRADIUS request stats. So LibreNMS polls will ultimately be reflected in your stats/charts. Go to your FreeRADIUS configuration directory (usually /etc/raddb or /etc/freeradius). cd sites-enabled ln -s ../sites-available/status status Restart FreeRADIUS. You should be able to test with the radclient as follows... echo \"Message-Authenticator = 0x00, FreeRADIUS-Statistics-Type = 31, Response-Packet-Type = Access-Accept\" | \\ radclient -x localhost:18121 status adminsecret Note that adminsecret is the default secret key in status_server. Change if you've modified this.","title":"FreeRADIUS"},{"location":"Extensions/Applications/#snmp-extend_14","text":"Copy the freeradius shell script, to the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/freeradius.sh -O /etc/snmp/freeradius.sh Make the script executable chmod +x /etc/snmp/freeradius.sh If you've made any changes to the FreeRADIUS status_server config (secret key, port, etc.) edit freeradius.sh and adjust the config variable accordingly. Edit your snmpd.conf file and add: extend freeradius /etc/snmp/freeradius.sh Restart snmpd on the host in question. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_3","text":"Install the script to your agent wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/freeradius.sh -O /usr/lib/check_mk_agent/local/freeradius.sh` Make the script executable chmod +x /usr/lib/check_mk_agent/local/freeradius.sh If you've made any changes to the FreeRADIUS status_server config (secret key, port, etc.) edit freeradius.sh and adjust the config variable accordingly. Edit the freeradius.sh script and set the variable 'AGENT' to '1' in the config.","title":"Agent"},{"location":"Extensions/Applications/#freeswitch","text":"A small shell script that reports various Freeswitch call status.","title":"Freeswitch"},{"location":"Extensions/Applications/#agent_4","text":"Install the agent on this device if it isn't already and copy the freeswitch script to /usr/lib/check_mk_agent/local/ wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/freeswitch -O /usr/lib/check_mk_agent/local/freeswitch` Make the script executable chmod +x /usr/lib/check_mk_agent/local/freeswitch Configure FSCLI in the script. You may also have to create an /etc/fs_cli.conf file if your fs_cli command requires authentication. Verify it is working by running /usr/lib/check_mk_agent/local/freeswitch","title":"Agent"},{"location":"Extensions/Applications/#snmp-extend_15","text":"Download the script onto the desired host wget https://github.com/librenms/librenms-agent/raw/master/agent-local/freeswitch -O /etc/snmp/freeswitch Make the script executable chmod +x /etc/snmp/freeswitch Configure FSCLI in the script. You may also have to create an /etc/fs_cli.conf file if your fs_cli command requires authentication. Verify it is working by running /etc/snmp/freeswitch Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend freeswitch /etc/snmp/freeswitch Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#gpsd","text":"","title":"GPSD"},{"location":"Extensions/Applications/#snmp-extend_16","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/gpsd -O /etc/snmp/gpsd Make the script executable chmod +x /etc/snmp/gpsd Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend gpsd /etc/snmp/gpsd Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading at the top of the page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_5","text":"Install the agent on this device if it isn't already and copy the gpsd script to /usr/lib/check_mk_agent/local/ You may need to configure $server or $port . Verify it is working by running /usr/lib/check_mk_agent/local/gpsd","title":"Agent"},{"location":"Extensions/Applications/#hv-monitor","text":"HV Monitor provides a generic way to monitor hypervisors. Currently CBSD+bhyve on FreeBSD and Libvirt+QEMU on Linux are support. For more information see HV::Monitor on Github or MetaCPAN .","title":"HV Monitor"},{"location":"Extensions/Applications/#snmp-extend_17","text":"Install the SNMP Extend. For Debian based systems this is as below. apt-get install zlib1g-dev cpanminus libjson-perl cpanm HV::Monitor And on FreeBSD as below. pkg install p5-App-cpanminus p5-JSON p5-MIME-Base64 p5-Gzip-Faster cpanm HV::Monitor Set it up to be be ran by cron by root. Yes, you can directly call this script from SNMPD, but be aware, especially with Libvirt, there is a very real possibility of the snmpget timing out, especially if a VM is spinning up/down as virsh domstats can block for a few seconds or so then. */5 * * * * /usr/local/bin/hv_monitor > /var/cache/hv_monitor.json -c 2> /dev/null Setup snmpd.conf as below. extend hv-monitor /bin/cat /var/cache/hv_monitor.json Restart SNMPD. Either wait for it to be re-discovered or manually enable it.","title":"SNMP Extend"},{"location":"Extensions/Applications/#icecast","text":"Shell script that reports load average/memory/open-files stats of Icecast","title":"Icecast"},{"location":"Extensions/Applications/#snmp-extend_18","text":"Copy the shell script, icecast-stats.sh, to the desired host (the host must be added to LibreNMS devices) wget https://github.com/librenms/librenms-agent/raw/master/snmp/icecast-stats.sh -O /etc/snmp/icecast-stats.sh Make the script executable chmod +x /etc/snmp/icecast-stats.sh Verify it is working by running /etc/snmp/icecast-stats.sh Edit your snmpd.conf file (usually /etc/snmp/icecast-stats.sh ) and add: extend icecast /etc/snmp/icecast-stats.sh","title":"SNMP Extend"},{"location":"Extensions/Applications/#isc-dhcp-stats","text":"A small python3 script that reports current DHCP leases stats and pool usage of ISC DHCP Server. Also you have to install the dhcpd-pools and the required Perl modules. Under Ubuntu/Debian just run apt install cpanminus ; cpanm Net::ISC::DHCPd::Leases Mime::Base64 File::Slurp or under FreeBSD pkg install p5-JSON p5-MIME-Base64 p5-App-cpanminus p5-File-Slurp ; cpanm Net::ISC::DHCPd::Leases .","title":"ISC DHCP Stats"},{"location":"Extensions/Applications/#snmp-extend_19","text":"Copy the shell script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/dhcp -O /etc/snmp/dhcp Make the script executable chmod +x /etc/snmp/dhcp Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: # without using cron extend dhcpstats /etc/snmp/dhcp -Z # using cron extend dhcpstats /bin/cat /var/cache/dhcp_extend If on a slow system running it via cron may be needed. */5 * * * * /etc/snmp/dhcp -Z -w /var/cache/dhcp_extend The following options are also supported. Option Description -c $file Path to dhcpd.conf. -l $file Path to lease file. -Z Enable GZip+Base64 compression. -d Do not de-dup. -w $file File to write it out to. Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#logsize","text":"","title":"Logsize"},{"location":"Extensions/Applications/#snmp-extend_20","text":"Download the script and make it executable. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/logsize -O /etc/snmp/logsize chmod +x /etc/snmp/logsize Install the requirements. # FreeBSD pkg install p5-File-Find-Rule p5-JSON p5-TOML p5-Time-Piece p5-MIME-Base64 p5-File-Slurp p5-Statistics-Lite # Debian apt-get install cpanminus cpanm File::Find::Rule JSON TOML Time::Piece MIME::Base64 File::Slurp Statistics::Lite Configure the config at /usr/local/etc/logsize.conf . You can find the documentation for the config file in the extend. Below is a small example. # monitor log sizes of logs directly udner /var/log [sets.var_log] dir=\"/var/log/\" # monitor remote logs from network devices [sets.remote_network] dir=\"/var/log/remote/network/\" # monitor remote logs from windows sources [sets.remote_windows] dir=\"/var/log/remote/windows/\" # monitor suricata flows logs sizes [sets.suricata_flows] dir=\"/var/log/suricata/flows/current\" If the directories all readable via SNMPD, this script can be ran via snmpd. Otherwise it needs setup in cron. Similarly is processing a large number of files, it may also need setup in cron if it takes the script awhile to run. */5 * * * * /etc/snmp/logsize -b 2> /dev/null > /dev/null Make sure that /var/cache/logsize_extend exists and is writable by the user running the extend. mkdir -p /var/cache/logsize_extend Configure it in the SNMPD config. # if not using cron extend logsize /etc/snmp/logsize -b # if using cron extend logsize /bin/cat /var/cache/logsize_extend/extend_return","title":"SNMP Extend"},{"location":"Extensions/Applications/#linux_config_files","text":"linux_config_files is an application intended to monitor a Linux distribution's configuration files via that distribution's configuration management tool/system. At this time, ONLY RPM-based (Fedora/RHEL) SYSTEMS ARE SUPPORTED utilizing the rpmconf tool. The linux_config_files application collects and graphs the total count of configuration files that are out of sync and graphs that number. Fedora/RHEL: Rpmconf is a utility that analyzes rpm configuration files using the RPM Package Manager. Rpmconf reports when a new configuration file standard has been issued for an upgraded/downgraded piece of software. Typically, rpmconf is used to provide a diff of the current configuration file versus the new, standard configuration file. The administrator can then choose to install the new configuration file or keep the old one.","title":"linux_config_files"},{"location":"Extensions/Applications/#snmp-extend_21","text":"Copy the python script, linux_config_files.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/linux_config_files.py -O /etc/snmp/linux_config_files.py Make the script executable chmod +x /etc/snmp/linux_config_files.py Edit your snmpd.conf file and add: extend linux_config_files /etc/snmp/linux_config_files.py (Optional on an RPM-based distribution) Create a /etc/snmp/linux_config_files.json file and specify the following: \"pkg_system\" - String designating the distribution name of the system. At the moment only \"rpm\" is supported [\"rpm\"] \"pkg_tool_cmd\" - String path to the package tool binary [\"/sbin/rpmconf\"] { \"pkg_system\": \"rpm\", \"pkg_tool_cmd\": \"/bin/rpmconf\", } Restart snmpd.","title":"SNMP Extend"},{"location":"Extensions/Applications/#linux-softnet-stat","text":"","title":"Linux Softnet Stat"},{"location":"Extensions/Applications/#snmp-extend_22","text":"1: Install the depends, which on a Debian based system would be as below. apt-get install -y cpanminus zlib1g-dev cpanm File::Slurp MIME::Base64 JSON Gzip::Faster Download the script into the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/linux_softnet_stat -O /etc/snmp/linux_softnet_stat Make the script executable chmod +x /etc/snmp/linux_softnet_stat Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend linux_softnet_stat /etc/snmp/linux_softnet_stat -b Then either enable the application Linux Softnet Stat or wait for it to be re-discovered.","title":"SNMP Extend"},{"location":"Extensions/Applications/#mailcow-dockerized-postfix","text":"","title":"mailcow-dockerized postfix"},{"location":"Extensions/Applications/#snmp-extend_23","text":"Download the script into the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/mailcow-dockerized-postfix -O /etc/snmp/mailcow-dockerized-postfix Make the script executable chmod +x /etc/snmp/mailcow-dockerized-postfix Maybe you will need to install pflogsumm on debian based OS. Please check if you have package installed. Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend mailcow-postfix /etc/snmp/mailcow-dockerized-postfix Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#mailscanner","text":"","title":"Mailscanner"},{"location":"Extensions/Applications/#snmp-extend_24","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/mailscanner.php -O /etc/snmp/mailscanner.php Make the script executable chmod +x /etc/snmp/mailscanner.php Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend mailscanner /etc/snmp/mailscanner.php Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#mdadm","text":"It allows you to checks mdadm health and array data This script require: jq","title":"Mdadm"},{"location":"Extensions/Applications/#snmp-extend_25","text":"Install jq sudo apt install jq Download the script onto the desired host. sudo wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/mdadm -O /etc/snmp/mdadm Make the script executable sudo chmod +x /etc/snmp/mdadm Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend mdadm /etc/snmp/mdadm Verify it is working by running sudo /etc/snmp/mdadm Restart snmpd on your host sudo service snmpd restart The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#megaraid","text":"This software from Broadcom/LSI let you monitor MegaRAID controller. Download the external software and follow the included install instructions. Add the following line to your snmpd.conf file (usually /etc/snmp/snmpd.conf) pass .1.3.6.1.4.1.3582 /usr/sbin/lsi_mrdsnmpmain Restart snmpd on your host","title":"MegaRAID"},{"location":"Extensions/Applications/#memcached","text":"","title":"Memcached"},{"location":"Extensions/Applications/#snmp-extend_26","text":"Copy the memcached script to /etc/snmp/ on your remote server. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/memcached -O /etc/snmp/memcached Make the script executable: chmod +x /etc/snmp/memcached Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend memcached /etc/snmp/memcached Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#mojo-cape-submit","text":"","title":"Mojo CAPE Submit"},{"location":"Extensions/Applications/#snmp","text":"This assumes you've already configured mojo_cape_submit from CAPE::Utils. Add the following to snmpd.conf and restarted SNMPD extend mojo_cape_submit /usr/local/bin/mojo_cape_submit_extend Then just wait for the machine in question to be rediscovered or enabled it in the device settings app page.","title":"SNMP"},{"location":"Extensions/Applications/#munin","text":"","title":"Munin"},{"location":"Extensions/Applications/#agent_6","text":"Install the script to your agent: wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/munin -O /usr/lib/check_mk_agent/local/munin Make the script executable chmod +x /usr/lib/check_mk_agent/local/munin Create the munin scripts dir: mkdir -p /usr/share/munin/munin-scripts Install your munin scripts into the above directory. To create your own custom munin scripts, please see this example: #!/bin/bash if [ \" $1 \" = \"config\" ] ; then echo 'graph_title Some title' echo 'graph_args --base 1000 -l 0' #not required echo 'graph_vlabel Some label' echo 'graph_scale no' #not required, can be yes/no echo 'graph_category system' #Choose something meaningful, can be anything echo 'graph_info This graph shows something awesome.' #Short desc echo 'foobar.label Label for your unit' # Repeat these two lines as much as you like echo 'foobar.info Desc for your unit.' exit 0 fi echo -n \"foobar.value \" $( date +%s ) #Populate a value, here unix-timestamp","title":"Agent"},{"location":"Extensions/Applications/#mysql","text":"Create the cache directory, '/var/cache/librenms/' and make sure that it is owned by the user running the SNMP daemon. mkdir -p /var/cache/librenms/ The MySQL script requires PHP-CLI and the PHP MySQL extension, so please verify those are installed. CentOS (May vary based on PHP version) yum install php-cli php-mysql Debian (May vary based on PHP version) apt-get install php-cli php-mysql Unlike most other scripts, the MySQL script requires a configuration file mysql.cnf in the same directory as the extend or agent script with following content: php $mysql_user = 'root' ; $mysql_pass = 'toor' ; $mysql_host = 'localhost' ; $mysql_port = 3306 ; Note that depending on your MySQL installation (chrooted install for example), you may have to specify 127.0.0.1 instead of localhost. Localhost make a MySQL connection via the mysql socket, while 127.0.0.1 make a standard IP connection to mysql. Note also if you get a mysql error Uncaught TypeError: mysqli_num_rows(): Argument #1 , this is because you are using a newer mysql version which doesnt support UNBLOCKING for slave statuses, so you need to also include the line $chk_options['slave'] = false; into mysql.cnf to skip checking slave statuses","title":"MySQL"},{"location":"Extensions/Applications/#agent_7","text":"Install the agent on this device if it isn't already and copy the mysql script to /usr/lib/check_mk_agent/local/ Verify it is working by running /usr/lib/check_mk_agent/local/mysql","title":"Agent"},{"location":"Extensions/Applications/#snmp-extend_27","text":"Copy the mysql script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/mysql -O /etc/snmp/mysql Make the file executable chmod +x /etc/snmp/mysql Edit /etc/snmp/mysql to set your MySQL connection constants or declare them in /etc/snmp/mysql.cnf (new file) Edit your snmpd.conf file and add: extend mysql /etc/snmp/mysql Restart snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP extend"},{"location":"Extensions/Applications/#nginx","text":"NGINX is a free, open-source, high-performance HTTP server: https://www.nginx.org/ It's required to have the following directive in your nginx configuration responsible for the localhost server: location /nginx-status { stub_status on; access_log off; allow 127.0.0.1; allow ::1; deny all; }","title":"NGINX"},{"location":"Extensions/Applications/#snmp-extend_28","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/nginx -O /etc/snmp/nginx Make the script executable chmod +x /etc/snmp/nginx Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend nginx /etc/snmp/nginx (Optional) If you have SELinux in Enforcing mode, you must add a module so the script can request /nginx-status: cat << EOF > snmpd_nginx.te module snmpd_nginx 1.0; require { type httpd_t; type http_port_t; type snmpd_t; class tcp_socket name_connect; } #============= snmpd_t ============== allow snmpd_t http_port_t:tcp_socket name_connect; EOF checkmodule -M -m -o snmpd_nginx.mod snmpd_nginx.te semodule_package -o snmpd_nginx.pp -m snmpd_nginx.mod semodule -i snmpd_nginx.pp Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_8","text":"Install the agent on this device if it isn't already and copy the nginx script to /usr/lib/check_mk_agent/local/","title":"Agent"},{"location":"Extensions/Applications/#nfs-server","text":"Export the NFS stats from as server.","title":"NFS Server"},{"location":"Extensions/Applications/#snmp-extend_29","text":"Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add : extend nfs-server /bin/cat /proc/net/rpc/nfsd find out where cat is located using : which cat reload snmpd service to activate the configuration","title":"SNMP Extend"},{"location":"Extensions/Applications/#ntp-client","text":"A shell script that gets stats from ntp client.","title":"NTP Client"},{"location":"Extensions/Applications/#snmp-extend_30","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/ntp-client -O /etc/snmp/ntp-client Make the script executable chmod +x /etc/snmp/ntp-client Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ntp-client /etc/snmp/ntp-client Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#ntp-server-aka-ntpd","text":"A shell script that gets stats from ntp server (ntpd).","title":"NTP Server aka NTPD"},{"location":"Extensions/Applications/#snmp-extend_31","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/ntp-server.sh -O /etc/snmp/ntp-server.sh Make the script executable chmod +x /etc/snmp/ntp-server.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ntp-server /etc/snmp/ntp-server.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#chronyd","text":"A shell script that gets the stats from chronyd and exports them with SNMP Extend.","title":"Chronyd"},{"location":"Extensions/Applications/#snmp-extend_32","text":"Download the shell script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/chrony -O /etc/snmp/chrony Make the script executable chmod +x /etc/snmp/chrony Edit the snmpd.conf file to include the extend by adding the following line to the end of the config file: extend chronyd /etc/snmp/chrony Note: Some distributions need sudo-permissions for the script to work with SNMP Extend. See the instructions on the section SUDO for more information. Restart snmpd service on the host Application should be auto-discovered and its stats presented on the Apps-page on the host. Note: Applications module needs to be enabled on the host or globally for the statistics to work as intended.","title":"SNMP Extend"},{"location":"Extensions/Applications/#nvidia-gpu","text":"","title":"Nvidia GPU"},{"location":"Extensions/Applications/#snmp-extend_33","text":"Copy the shell script, nvidia, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/nvidia -O /etc/snmp/nvidia Make the script executable chmod +x /etc/snmp/nvidia Edit your snmpd.conf file and add: extend nvidia /etc/snmp/nvidia Restart snmpd on your host. Verify you have nvidia-smi installed, which it generally should be if you have the driver from Nvida installed. The GPU numbering on the graphs will correspond to how the nvidia-smi sees them as being. For questions about what the various values are/mean, please see the nvidia-smi man file under the section covering dmon.","title":"SNMP Extend"},{"location":"Extensions/Applications/#opensearchelasticsearch","text":"","title":"Opensearch\\Elasticsearch"},{"location":"Extensions/Applications/#snmp-extend_34","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/opensearch -O /etc/snmp/opensearch Make it executable chmod +x /etc/snmp/opensearch Install the required Perl dependencies. # FreeBSD pkg install p5-JSON p5-libwww # Debian/Ubuntu apt-get install libjson-perl libwww-perl # cpanm cpanm JSON Libwww Update your snmpd.conf. extend opensearch /bin/cat /var/cache/opensearch.json Update root crontab with. This is required as it will this will likely time out otherwise. Use */1 if you want to have the most recent stats when polled or to */5 if you just want at exactly a 5 minute interval. */5 * * * * /etc/snmp/opensearch > /var/cache/opensearch.json Enable it or wait for the device to be re-disocvered.","title":"SNMP Extend"},{"location":"Extensions/Applications/#open-grid-scheduler","text":"Shell script to track the OGS/GE jobs running on clusters.","title":"Open Grid Scheduler"},{"location":"Extensions/Applications/#snmp-extend_35","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/rocks.sh -O /etc/snmp/rocks.sh Make the script executable chmod +x /etc/snmp/rocks.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ogs /etc/snmp/rocks.sh Restart snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#opensips","text":"Script that reports load-average/memory/open-files stats of Opensips","title":"Opensips"},{"location":"Extensions/Applications/#snmp-extend_36","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/opensips-stats.sh -O /etc/snmp/opensips-stats.sh Make the script executable: chmod +x /etc/snmp/opensips-stats.sh Verify it is working by running /etc/snmp/opensips-stats.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend opensips /etc/snmp/opensips-stats.sh","title":"SNMP Extend"},{"location":"Extensions/Applications/#os-updates","text":"A small shell script that checks your system package manager for any available updates. Supports apt-get/pacman/yum/zypper package managers. For pacman users automatically refreshing the database, it is recommended you use an alternative database location --dbpath=/var/lib/pacman/checkupdate","title":"OS Updates"},{"location":"Extensions/Applications/#snmp-extend_37","text":"Download the script onto the desired host. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/osupdate -O /etc/snmp/osupdate Make the script executable chmod +x /etc/snmp/osupdate Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend osupdate /etc/snmp/osupdate Restart snmpd on your host Note : apt-get depends on an updated package index. There are several ways to have your system run apt-get update automatically. The easiest is to create /etc/apt/apt.conf.d/10periodic and pasting the following in it: APT::Periodic::Update-Package-Lists \"1\"; . If you have apticron, cron-apt or apt-listchanges installed and configured, chances are that packages are already updated periodically . The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_9","text":"Install the agent on this device if it isn't already and copy the osupdate script to /usr/lib/check_mk_agent/local/ Then uncomment the line towards the top marked to be uncommented if using it as a agent.","title":"Agent"},{"location":"Extensions/Applications/#php-fpm","text":"","title":"PHP-FPM"},{"location":"Extensions/Applications/#snmp-extend_38","text":"Copy the shell script, phpfpmsp, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/phpfpmsp -O /etc/snmp/phpfpmsp Make the script executable chmod +x /etc/snmp/phpfpmsp Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend phpfpmsp /etc/snmp/phpfpmsp Edit /etc/snmp/phpfpmsp to include the status URL for the PHP-FPM pool you are monitoring. Restart snmpd on your host It is worth noting that this only monitors a single pool. If you want to monitor multiple pools, this won't do it. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_10","text":"Install the agent on this device if it isn't already and copy the phpfpmsp script to /usr/lib/check_mk_agent/local/","title":"Agent"},{"location":"Extensions/Applications/#pi-hole","text":"","title":"Pi-hole"},{"location":"Extensions/Applications/#snmp-extend_39","text":"Copy the shell script, pi-hole, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/pi-hole -O /etc/snmp/pi-hole Make the script executable chmod +x /etc/snmp/pi-hole Edit your snmpd.conf file and add: extend pi-hole /etc/snmp/pi-hole To get all data you must get your API auth token from Pi-hole server and change the API_AUTH_KEY entry inside the snmp script. Restard snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#portactivity","text":"","title":"Portactivity"},{"location":"Extensions/Applications/#snmp-extend_40","text":"Install missing packages - Ubuntu is shown below. apt install libparse-netstat-perl apt install libjson-perl Copy the Perl script to the desired host (the host must be added to LibreNMS devices) wget https://github.com/librenms/librenms-agent/raw/master/snmp/portactivity -O /etc/snmp/portactivity Make the script executable chmod +x /etc/snmp/portactivity Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend portactivity /etc/snmp/portactivity -p http,ldap,imap Will monitor HTTP, LDAP, and IMAP. The -p switch specifies what ports to use. This is a comma seperated list. These must be found in '/etc/services' or where ever NSS is set to fetch it from. If not, it will throw an error. If you want to JSON returned by it to be printed in a pretty format use the -P flag. Restart snmpd on your host. Please note that for only TCP[46] services are supported.","title":"SNMP Extend"},{"location":"Extensions/Applications/#postfix","text":"","title":"Postfix"},{"location":"Extensions/Applications/#snmp-extend_41","text":"Copy the shell script, postfix-queues, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/postfix-queues -O /etc/snmp/postfix-queues Copy the Perl script, postfixdetailed, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/postfixdetailed -O /etc/snmp/postfixdetailed Make both scripts executable chmod +x /etc/snmp/postfixdetailed /etc/snmp/postfix-queues Edit your snmpd.conf file and add: extend mailq /etc/snmp/postfix-queues extend postfixdetailed /etc/snmp/postfixdetailed Restart snmpd. Install pflogsumm for your OS. Make sure the cache file in /etc/snmp/postfixdetailed is some place that snmpd can write too. This file is used for tracking changes between various values between each time it is called by snmpd. Also make sure the path for pflogsumm is correct. Run /etc/snmp/postfixdetailed to create the initial cache file so you don't end up with some crazy initial starting value. Please note that each time /etc/snmp/postfixdetailed is ran, the cache file is updated, so if this happens in between LibreNMS doing it then the values will be thrown off for that polling period. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. NOTE: If using RHEL for your postfix server, qshape must be installed manually as it is not officially supported. CentOs 6 rpms seem to work without issues.","title":"SNMP Extend"},{"location":"Extensions/Applications/#postgres","text":"","title":"Postgres"},{"location":"Extensions/Applications/#snmp-extend_42","text":"Copy the shell script, postgres, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/postgres -O /etc/snmp/postgres Make the script executable chmod +x /etc/snmp/postgres Edit your snmpd.conf file and add: extend postgres /etc/snmp/postgres Restart snmpd on your host Install the Nagios check check_postgres.pl on your system: https://github.com/bucardo/check_postgres Verify the path to check_postgres.pl in /etc/snmp/postgres is correct. (Optional) If you wish to change the DB username (default: pgsql), enable the postgres DB in totalling (e.g. set ignorePG to 0, default: 1), or set a hostname for check_postgres.pl to connect to (default: the Unix Socket postgresql is running on), then create the file /etc/snmp/postgres.config with the following contents (note that not all of them need be defined, just whichever you'd like to change): DBuser=monitoring ignorePG=0 DBhost=localhost Note that if you are using netdata or the like, you may wish to set ignorePG to 1 or otherwise that total will be very skewed on systems with light or moderate usage. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#powerdns","text":"An authoritative DNS server: https://www.powerdns.com/auth.html","title":"PowerDNS"},{"location":"Extensions/Applications/#snmp-extend_43","text":"Copy the shell script, powerdns.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/powerdns.py -O /etc/snmp/powerdns.py Make the script executable chmod +x /etc/snmp/powerdns.py Edit your snmpd.conf file and add: extend powerdns /etc/snmp/powerdns.py Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_11","text":"Install the agent on this device if it isn't already and copy the powerdns script to /usr/lib/check_mk_agent/local/","title":"Agent"},{"location":"Extensions/Applications/#powerdns-recursor","text":"A recursive DNS server: https://www.powerdns.com/recursor.html","title":"PowerDNS Recursor"},{"location":"Extensions/Applications/#direct","text":"The LibreNMS polling host must be able to connect to port 8082 on the monitored device. The web-server must be enabled, see the Recursor docs: https://doc.powerdns.com/md/recursor/settings/#webserver","title":"Direct"},{"location":"Extensions/Applications/#variables","text":"$config['apps']['powerdns-recursor']['api-key'] required, this is defined in the Recursor config $config['apps']['powerdns-recursor']['port'] numeric, defines the port to connect to PowerDNS Recursor on. The default is 8082 $config['apps']['powerdns-recursor']['https'] true or false, defaults to use http.","title":"Variables"},{"location":"Extensions/Applications/#snmp-extend_44","text":"Copy the shell script, powerdns-recursor, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/powerdns-recursor -O /etc/snmp/powerdns-recursor Make the script executable chmod +x /etc/snmp/powerdns-recursor Edit your snmpd.conf file and add: extend powerdns-recursor /etc/snmp/powerdns-recursor Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_12","text":"Install the agent on this device if it isn't already and copy the powerdns-recursor script to /usr/lib/check_mk_agent/local/ This script uses rec_control get-all to collect stats.","title":"Agent"},{"location":"Extensions/Applications/#powerdns-dnsdist","text":"","title":"PowerDNS-dnsdist"},{"location":"Extensions/Applications/#snmp-extend_45","text":"Copy the BASH script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/powerdns-dnsdist -O /etc/snmp/powerdns-dnsdist Make the script executable chmod +x /etc/snmp/powerdns-dnsdist Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend powerdns-dnsdist /etc/snmp/powerdns-dnsdist Restart snmpd on your host. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#powermon","text":"PowerMon tracks the power usage on your host and can report on both consumption and cost, using a python script installed on the host. PowerMon consumption graph Currently the script uses one of two methods to determine current power usage: ACPI via libsensors HP-Health (HP Proliant servers only) The ACPI method is quite unreliable as it is usually only implemented by battery-powered devices, e.g. laptops. YMMV. However, it's possible to support any method as long as it can return a power value, usually in Watts. TIP: You can achieve this by adding a method and a function for that method to the script. It should be called by getData() and return a dictionary. Because the methods are unreliable for all hardware, you need to declare to the script which method to use. The are several options to assist with testing, see --help .","title":"PowerMon"},{"location":"Extensions/Applications/#snmp-extend_46","text":"","title":"SNMP Extend"},{"location":"Extensions/Applications/#initial-setup","text":"Download the python script onto the host: wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/powermon-snmp.py -O /usr/local/bin/powermon-snmp.py Make the script executable: chmod +x /usr/local/bin/powermon-snmp.py Edit the script and set the cost per kWh for your supply. You must uncomment this line for the script to work: vi /usr/local/bin/powermon-snmp.py #costPerkWh = 0.15 Choose you method below: Method 1. sensors Method 2. hpasmcli Install dependencies: dnf install lm_sensors pip install PySensors Test the script from the command-line. For example: $ /usr/local/bin/powermon-snmp.py -m sensors -n -p { \"meter\": { \"0\": { \"reading\": 0.0 } }, \"psu\": {}, \"supply\": { \"rate\": 0.15 }, \"reading\": \"0.0\" } If you see a reading of 0.0 it is likely this method is not supported for your system. If not, continue. Obtain the hp-health package for your system. Generally there are three options: Standalone package from HPE Support From the HP Management Component Pack (MCP). Included in the HP Service Pack for Proliant (SPP) If you've downloaded the standalone package, install it. For example: rpm -ivh hp-health-10.91-1878.11.rhel8.x86_64.rpm Check the service is running: systemctl status hp-health Test the script from the command-line. For example: $ /usr/local/bin/powermon-snmp.py -m hpasmcli -n -p { \"meter\": { \"1\": { \"reading\": 338.0 } }, \"psu\": { \"1\": { \"present\": \"Yes\", \"redundant\": \"No\", \"condition\": \"Ok\", \"hotplug\": \"Supported\", \"reading\": 315.0 }, \"2\": { \"present\": \"Yes\", \"redundant\": \"No\", \"condition\": \"FAILED\", \"hotplug\": \"Supported\" } }, \"supply\": { \"rate\": 0.224931 }, \"reading\": 338.0 } If you see a reading of 0.0 it is likely this method is not supported for your system. If not, continue.","title":"Initial setup"},{"location":"Extensions/Applications/#finishing-up","text":"Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add the following: extend powermon /usr/local/bin/powermon-snmp.py -m hpasmcli NOTE: Avoid using other script options in the snmpd config as the results may not be interpreted correctly by LibreNMS. Reload your snmpd service: systemctl reload snmpd You're now ready to enable the application in LibreNMS.","title":"Finishing Up"},{"location":"Extensions/Applications/#privoxy","text":"For this to work, the following log items need enabled for Privoxy. debug 2 # show each connection status debug 512 # Common Log Format debug 1024 # Log the destination for requests Privoxy didn't let through, and the reason why. debug 4096 # Startup banner and warnings debug 8192 # Non-fatal errors","title":"Privoxy"},{"location":"Extensions/Applications/#snmp-extend_47","text":"Download the extend and make sure it is executable. wget https://github.com/librenms/librenms-agent/raw/master/snmp/privoxy -O /etc/snmp/privoxy chmod +x /etc/snmp/privoxy Install the depdenencies. # FreeBSD pkg install p5-File-ReadBackwards p5-Time-Piece p5-JSON p5-IPC-Run3 p5-Gzip-Faster p5-MIME-Base64 # Debian apt-get install cpanminus zlib1g cpanm File::ReadBackwards Time::Piece JSON IPC::Run3 MIME::Base64 Gzip::Faster Add the extend to snmpd.conf and restart snmpd. extend privoxy /etc/snmp/privoxy If your logfile is not at /var/log/privoxy/logfile , that may be changed via the -f option. If privoxy-log-parser.pl is not found in your standard $PATH setting, you may will need up call the extend via /usr/bin/env with a $PATH set to something that includes it. Once that is done, just wait for the server to be rediscovered or just enable it manually.","title":"SNMP Extend"},{"location":"Extensions/Applications/#pwrstatd","text":"Pwrstatd (commonly known as powerpanel) is an application/service available from CyberPower to monitor their PSUs over USB. It is currently capable of reading the status of only one PSU connected via USB at a time. The powerpanel software is available here: https://www.cyberpowersystems.com/products/software/power-panel-personal/","title":"Pwrstatd"},{"location":"Extensions/Applications/#snmp-extend_48","text":"Copy the python script, pwrstatd.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/pwrstatd.py -O /etc/snmp/pwrstatd.py Make the script executable chmod +x /etc/snmp/pwrstatd.py Edit your snmpd.conf file and add: extend pwrstatd /etc/snmp/pwrstatd.py (Optional) Create a /etc/snmp/pwrstatd.json file and specify the path to the pwrstat executable [the default path is /sbin/pwrstat]: { \"pwrstat_cmd\": \"/sbin/pwrstat\" } Restart snmpd.","title":"SNMP Extend"},{"location":"Extensions/Applications/#proxmox","text":"For Proxmox 4.4+ install the libpve-apiclient-perl package apt install libpve-apiclient-perl Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/proxmox -O /usr/local/bin/proxmox Make the script executable chmod +x /usr/local/bin/proxmox Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend proxmox /usr/local/bin/proxmox Note: if your snmpd doesn't run as root, you might have to invoke the script using sudo and modify the \"extend\" line extend proxmox /usr/bin/sudo /usr/local/bin/proxmox after, edit your sudo users (usually visudo ) and add at the bottom: Debian-snmp ALL=(ALL) NOPASSWD: /usr/local/bin/proxmox Restart snmpd on your host","title":"Proxmox"},{"location":"Extensions/Applications/#puppet-agent","text":"SNMP extend script to get your Puppet Agent data into your host.","title":"Puppet Agent"},{"location":"Extensions/Applications/#snmp-extend_49","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/puppet_agent.py -O /etc/snmp/puppet_agent.py Make the script executable chmod +x /etc/snmp/puppet_agent.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend puppet-agent /etc/snmp/puppet_agent.py The Script needs python3-yaml package to be installed. Per default script searches for on of this files: /var/cache/puppet/state/last_run_summary.yaml /opt/puppetlabs/puppet/cache/state/last_run_summary.yaml optionally you can add a specific summary file with creating /etc/snmp/puppet.json { \"agent\": { \"summary_file\": \"/my/custom/path/to/summary_file\" } } custom summary file has highest priority Restart snmpd on the host","title":"SNMP Extend"},{"location":"Extensions/Applications/#pureftpd","text":"SNMP extend script to monitor PureFTPd.","title":"PureFTPd"},{"location":"Extensions/Applications/#snmp-extend_50","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/pureftpd.py -O /etc/snmp/pureftpd.py Make the script executable chmod +x /etc/snmp/pureftpd.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend pureftpd sudo /etc/snmp/pureftpd.py Edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /etc/snmp/pureftpd.py or the path where your pure-ftpwho is located If pure-ftpwho is not located in /usr/sbin you will also need to create a config file, which is named pureftpd.json. The file has to be located in /etc/snmp/. {\"pureftpwho_cmd\": \"/usr/sbin/pure-ftpwho\" } Restart snmpd on your host","title":"SNMP Extend"},{"location":"Extensions/Applications/#raspberry-pi","text":"SNMP extend script to get your PI data into your host.","title":"Raspberry PI"},{"location":"Extensions/Applications/#snmp-extend_51","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/raspberry.sh -O /etc/snmp/raspberry.sh Make the script executable chmod +x /etc/snmp/raspberry.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend raspberry /usr/bin/sudo /bin/sh /etc/snmp/raspberry.sh Edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /bin/sh /etc/snmp/raspberry.sh Note: If you are using Raspian, the default user is Debian-snmp . Change snmp above to Debian-snmp . You can verify the user snmpd is using with ps aux | grep snmpd Restart snmpd on PI host","title":"SNMP Extend"},{"location":"Extensions/Applications/#raspberry-pi-gpio-monitor","text":"SNMP extend script to monitor your IO pins or sensor modules connected to your GPIO header.","title":"Raspberry Pi GPIO Monitor"},{"location":"Extensions/Applications/#snmp-extend_52","text":"1: Make sure you have wiringpi installed on your Raspberry Pi. In Debian-based systems for example you can achieve this by issuing: apt-get install wiringpi 2: Download the script to your Raspberry Pi. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/rpigpiomonitor.php -O /etc/snmp/rpigpiomonitor.php 3: (optional) Download the example configuration to your Raspberry Pi. wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/rpigpiomonitor.ini -O /etc/snmp/rpigpiomonitor.ini 4: Make the script executable: chmod +x /etc/snmp/rpigpiomonitor.php 5: Create or edit your rpigpiomonitor.ini file according to your needs. 6: Check your configuration with rpigpiomonitor.php -validate 7: Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend rpigpiomonitor /etc/snmp/rpigpiomonitor.php 8: Restart snmpd on your Raspberry Pi and, if your Raspberry Pi is already present in LibreNMS, perform a manual rediscover.","title":"SNMP Extend"},{"location":"Extensions/Applications/#redis","text":"Script to monitor your Redis Server","title":"Redis"},{"location":"Extensions/Applications/#snmp-extend_53","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/redis.py -O /etc/snmp/redis.py Make the script executable chmod +x /etc/snmp/redis.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend redis /etc/snmp/redis.py (Optional) If you have SELinux in Enforcing mode, you must add a module so the script can get redis informations and write them: cat << EOF > snmpd_redis.te module snmpd_redis 1.0; require { type tmp_t; type redis_port_t; type snmpd_t; class tcp_socket name_connect; class dir { add_name write }; } #============= snmpd_t ============== allow snmpd_t redis_port_t:tcp_socket name_connect; allow snmpd_t tmp_t:dir { write add_name }; EOF checkmodule -M -m -o snmpd_redis.mod snmpd_redis.te semodule_package -o snmpd_redis.pp -m snmpd_redis.mod semodule -i snmpd_redis.pp","title":"SNMP Extend"},{"location":"Extensions/Applications/#agent_13","text":"Install the agent on this device if it isn't already and copy the redis script to /usr/lib/check_mk_agent/local/","title":"Agent"},{"location":"Extensions/Applications/#rrdcached","text":"Install/Setup: For Install/Setup Local Librenms RRDCached: Please see RRDCached Will collect stats by: 1. Connecting directly to the associated device on port 42217 2. Monitor thru snmp with SNMP extend, as outlined below 3. Connecting to the rrdcached server specified by the rrdcached setting SNMP extend script to monitor your (remote) RRDCached via snmp","title":"RRDCached"},{"location":"Extensions/Applications/#snmp-extend_54","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/agent-local/rrdcached -O /etc/snmp/rrdcached Make the script executable chmod +x /etc/snmp/rrdcached Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf ) and add: extend rrdcached /etc/snmp/rrdcached","title":"SNMP Extend"},{"location":"Extensions/Applications/#sdfs-info","text":"A small shell script that exportfs SDFS volume info.","title":"SDFS info"},{"location":"Extensions/Applications/#snmp-extend_55","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/sdfsinfo -O /etc/snmp/sdfsinfo Make the script executable chmod +x /etc/snmp/sdfsinfo Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend sdfsinfo /etc/snmp/sdfsinfo Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#seafile","text":"SNMP extend script to monitor your Seafile Server","title":"Seafile"},{"location":"Extensions/Applications/#snmp-extend_56","text":"Copy the Python script, seafile.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/seafile.py -O /etc/snmp/seafile.py Also you have to install the requests Package for Python3. Under Ubuntu/Debian just run apt install python3-requests Make the script executable chmod +x /etc/snmp/seafile.py Edit your snmpd.conf file and add: extend seafile /etc/snmp/seafile.py You will also need to create the config file, which is named seafile.json . The script has to be located at /etc/snmp/. {\"url\": \"https://seafile.mydomain.org\", \"username\": \"some_admin_login@mail.address\", \"password\": \"password\", \"account_identifier\": \"name\" \"hide_monitoring_account\": true } The variables are as below. url = Url how to get access to Seafile Server username = Login to Seafile Server. It is important that used Login has admin privileges. Otherwise most API calls will be denied. password = Password to the configured login. account_identifier = Defines how user accounts are listed in RRD Graph. Options are: name, email hide_monitoring_account = With this Boolean you can hide the Account which you use to access Seafile API Note: It is recommended to use a dedicated Administrator account for monitoring.","title":"SNMP Extend"},{"location":"Extensions/Applications/#smart","text":"","title":"SMART"},{"location":"Extensions/Applications/#snmp-extend_57","text":"Copy the Perl script, smart, to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/smart-v1 -O /etc/snmp/smart Install the depends. # FreeBSD pkg install p5-JSON p5-MIME-Base64 smartmontools # Debian apt-get install cpanminus smartmontools cpanm MIME::Base64 JSON # CentOS dnf install smartmontools perl-JSON perl-MIME-Base64 Make the script executable chmod +x /etc/snmp/smart Edit your snmpd.conf file and add: extend smart /etc/snmp/smart You will also need to create the config file, which defaults to the same path as the script, but with .config appended. So if the script is located at /etc/snmp/smart, the config file will be /etc/snmp/smart.config . Alternatively you can also specific a config via -c . Anything starting with a # is comment. The format for variables is $variable=$value. Empty lines are ignored. Spaces and tabes at either the start or end of a line are ignored. Any line with out a matched variable or # are treated as a disk. #This is a comment cache=/var/cache/smart smartctl=/usr/bin/env smartctl useSN=1 ada0 ada1 da5 /dev/da5 -d sat twl0,0 /dev/twl0 -d 3ware,0 twl0,1 /dev/twl0 -d 3ware,1 twl0,2 /dev/twl0 -d 3ware,2 The variables are as below. cache = The path to the cache file to use. Default: /var/cache/smart smartctl = The path to use for smartctl. Default: /usr/bin/env smartctl useSN = If set to 1, it will use the disks SN for reporting instead of the device name. 1 is the default. 0 will use the device name. A disk line is can be as simple as just a disk name under /dev/. Such as in the config above The line \"ada0\" would resolve to \"/dev/ada0\" and would be called with no special argument. If a line has a space in it, everything before the space is treated as the disk name and is what used for reporting and everything after that is used as the argument to be passed to smartctl. If you want to guess at the configuration, call it with -g and it will print out what it thinks it should be. Restart snmpd on your host If you have a large number of more than one or two disks on a system, you should consider adding this to cron. Also make sure the cache file is some place it can be written to. */5 * * * * /etc/snmp/smart -u If your snmp agent runs as user \"snmp\", edit your sudo users (usually visudo ) and add at the bottom: snmp ALL=(ALL) NOPASSWD: /etc/snmp/smart, /usr/bin/env smartctl and modify your snmpd.conf file accordingly, sudo can be excluded if running it via cron: extend smart /usr/bin/sudo /etc/snmp/smart The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Optionally setup nightly self tests for the disks. The exend will run the specified test on all configured disks if called with the -t flag and the name of the SMART test to run. 0 0 * * * /etc/snmp/smart -t long","title":"SNMP Extend"},{"location":"Extensions/Applications/#sneck","text":"This is for replacing Nagios/Icinga or the LibreNMS service integration in regards to NRPE. This allows LibreNMS to query what checks were ran on the server and keep track of totals of OK, WARNING, CRITICAL, and UNKNOWN statuses. The big advantage over this compared to a NRPE are as below. It does not need to know what checks are configured on it. Also does not need to wait for the tests to run as sneck is meant to be ran via cron and the then return the cache when queried via SNMP, meaning a lot faster response time, especially if slow checks are being performed. Works over proxied SNMP connections. Included are alert examples. Although for setting up custom ones, the metrics below are provided. Metric Description ok Total OK checks warning Total WARNING checks critical Total CRITICAL checks unknown Total UNKNOWN checks errored Total checks that errored time_to_polling Differnce in seconds between when polling data was generated and when polled time_to_polling_abs The absolute value of time_to_polling. check_$CHECK Exit status of a specific check $CHECK is equal to the name of the check in question. So foo would be check_foo The standard Nagios/Icinga style exit codes are used and those are as below. Exit Meaning 0 okay 1 warning 2 critical 3+ unknown To use time_to_polling , it will need to enabled via setting the config item below. The default is false. Unless set to true, this value will default to 0. If enabling this, one will want to make sure that NTP is in use every were or it will alert if it goes over a difference of 540s. lnms config:set app.sneck.polling_time_diff true For more information on Sneck, check it out at MetaCPAN or Github . For poking systems using Sneck, also check out boop_snoot if one wants to query those systems via the CLI. Docs on it at MetaCPAN and Github .","title":"Sneck"},{"location":"Extensions/Applications/#snmp-extend_58","text":"Install the extend. # FreeBSD pkg install p5-JSON p5-File-Slurp p5-MIME-Base64 p5-Gzip-Faster p5-App-cpanminus cpanm Monitoring::Sneck # Debian based systems apt-get install zlib1g-dev cpanminus cpanm Monitoring::Sneck Configure any of the checks you want to run in /usr/local/etc/sneck.conf . You con find it documented here . Set it up in cron. This will mean you don't need to wait for all the checks to complete when polled via SNMP, which for like SMART or other long running checks will mean it timing out. Also means it does not need called via sudo as well. */5 * * * * /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin /usr/local/bin/sneck -u 2> /dev/null > /dev/null Set it up in the snmpd config and restart snmpd. The -c flag will tell read it to read from cache instead of rerunning the checks. extend sneck /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin /usr/local/bin/sneck -c In LibreNMS, enable the application for the server in question or wait for auto discovery to find it.","title":"SNMP Extend"},{"location":"Extensions/Applications/#squid","text":"","title":"Squid"},{"location":"Extensions/Applications/#snmp-proxy","text":"Enable SNMP for Squid like below, if you have not already, and restart it. acl snmppublic snmp_community public snmp_port 3401 snmp_access allow snmppublic localhost snmp_access deny all Restart squid on your host. Edit your snmpd.conf file and add, making sure you have the same community, host, and port as above: proxy -v 2c -Cc -c public 127.0.0.1:3401 1.3.6.1.4.1.3495 For more advanced information on Squid and SNMP or setting up proxying for net-snmp, please see the links below. http://wiki.squid-cache.org/Features/Snmp http://www.net-snmp.org/wiki/index.php/Snmpd_proxy","title":"SNMP Proxy"},{"location":"Extensions/Applications/#supervisord","text":"It shows you the totals per status and also the uptime per process. That way you can add alerts for instance when there are process in state FATAL .","title":"Supervisord"},{"location":"Extensions/Applications/#snmp-extend_59","text":"Copy the python script to the desired host. wget https://github.com/librenms/librenms-agent/raw/master/snmp/supervisord.py -O /etc/snmp/supervisord.py Notice that this will use the default unix socket path. Modify the unix_socket_path variable in the script if your path differs from the default. Make the script executable chmod +x /etc/snmp/supervisord.py Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend supervisord /etc/snmp/supervisord.py Restart snmpd on your host systemctl restart snmpd","title":"SNMP Extend"},{"location":"Extensions/Applications/#sagan","text":"For metrics the stats are migrated as below from the stats JSON. f_drop_percent and drop_percent are computed based on the found data. Instance Key Stats JSON Key uptime .stats.uptime total .stats.captured.total drop .stats.captured.drop ignore .stats.captured.ignore threshold .stats.captured.theshold after .stats.captured.after match .stats.captured.match bytes .stats.captured.bytes_total bytes_ignored .stats.captured.bytes_ignored max_bytes_log_line .stats.captured.max_bytes_log_line eps .stats.captured.eps f_total .stats.flow.total f_dropped .stats.flow.dropped Those keys are appended with the name of the instance running with _ between the instance name and instance metric key. So uptime for ids would be ids_uptime . The default is named 'ids' unless otherwise specified via the extend. There is a special instance name of .total which is the total of all the instances. So if you want the total eps, the metric would be .total_eps . Also worth noting that the alert value is the highest one found among all the instances.","title":"Sagan"},{"location":"Extensions/Applications/#snmp-extend_60","text":"Install the extend. cpanm Sagan::Monitoring Setup cron. Below is a example. */5 * * * * /usr/local/bin/sagan_stat_check > /dev/null Configure snmpd.conf extend sagan-stats /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin sagan_stat_check -c Restart snmpd on your system. You will want to make sure that sagan is setup to with the values set below for stats-json processor, for a single instance setup.. enabled: yes time: 300 subtract_old_values: true filename: \"$LOG_PATH/stats.json\" Any configuration of sagan_stat_check should be done in the cron setup. If the default does not work, check the docs for it at MetaCPAN for sagan_stat_check","title":"SNMP Extend"},{"location":"Extensions/Applications/#socket-statistics-ss","text":"The Socket Statistics application polls ss and scrapes socket statuses. Individual sockets and address-families may be filtered out within the script's optional configuration JSON file. The following socket types are polled directly. Filtering a socket type will disable direct polling as-well-as indirect polling within any address-families that list the socket type as their child: dccp (also exists within address-families \"inet\" and \"inet6\") mptcp (also exists within address-families \"inet\" and \"inet6\") raw (also exists within address-families \"inet\" and \"inet6\") sctp (also exists within address-families \"inet\" and \"inet6\") tcp (also exists within address-families \"inet\" and \"inet6\") udp (also exists within address-families \"inet\" and \"inet6\") xdp The following socket types are polled within an address-family only: inet6 (within address-family \"inet6\") p_dgr (within address-family \"link\") p_raw (within address-family \"link\") ti_dg (within address-family \"tipc\") ti_rd (within address-family \"tipc\") ti_sq (within address-family \"tipc\") ti_st (within address-family \"tipc\") v_dgr (within address-family \"vsock\") v_str (within address-family \"vsock\") unknown (within address-families \"inet\", \"inet6\", \"link\", \"tipc\", and \"vsock\") The following address-families are polled directly and have their child socket types tab-indented below them. Filtering a socket type (see \"1\" above) will filter it from the address-family. Filtering an address-family will filter out all of its child socket types. However, if those socket types are not DIRECTLY filtered out (see \"1\" above), then they will continue to be monitored either directly or within other address-families in which they exist: inet dccp mptcp raw sctp tcp udp unknown inet6 dccp icmp6 mptcp raw sctp tcp udp unknown link p_dgr p_raw unknown netlink tipc ti_dg ti_rd ti_sq ti_st unknown unix u_dgr u_seq u_str vsock v_dgr v_str unknown","title":"Socket Statistics (ss)"},{"location":"Extensions/Applications/#snmp-extend_61","text":"Copy the python script, ss.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/ss.py -O /etc/snmp/ss.py Make the script executable chmod +x /etc/snmp/ss.py Edit your snmpd.conf file and add: extend ss /etc/snmp/ss.py (Optional) Create a /etc/snmp/ss.json file and specify: \"ss_cmd\" - String path to the ss binary: [\"/sbin/ss\"] \"socket_types\" - A comma-delimited list of socket types to include. The following socket types are valid: dccp, icmp6, mptcp, p_dgr, p_raw, raw, sctp, tcp, ti_dg, ti_rd, ti_sq, ti_st, u_dgr, u_seq, u_str, udp, unknown, v_dgr, v_dgr, xdp. Please note that the \"unknown\" socket type is represented in /sbin/ss output with the netid \"???\". Please also note that the p_dgr and p_raw socket types are specific to the \"link\" address family; the ti_dg, ti_rd, ti_sq, and ti_st socket types are specific to the \"tipc\" address family; the u_dgr, u_seq, and u_str socket types are specific to the \"unix\" address family; and the v_dgr and v_str socket types are specific to the \"vsock\" address family. Filtering out the parent address families for the aforementioned will also filter out their specific socket types. Specifying \"all\" includes all of the socket types. For example: to include only tcp, udp, icmp6 sockets, you would specify \"tcp,udp,icmp6\": [\"all\"] \"addr_families\" - A comma-delimited list of address families to include. The following families are valid: inet, inet6, link, netlink, tipc, unix, vsock. As mentioned above under (b), filtering out the link, tipc, unix, or vsock address families will also filter out their respective socket types. Specifying \"all\" includes all of the families. For example: to include only inet and inet6 families, you would specify \"inet,inet6\": [\"all\"] { \"ss_cmd\": \"/sbin/ss\", \"socket_types\": \"all\" \"addr_families\": \"all\" } In order to filter out uncommon/unused socket types, the following JSON configuration is recommended: { \"ss_cmd\": \"/sbin/ss\", \"socket_types\": \"icmp6,p_dgr,p_raw,raw,tcp,u_dgr,u_seq,u_str,udp\", \"addr_families\": \"inet,inet6,link,netlink,unix\" } (Optional) If SELinux is in Enforcing mode, you must add a module so the script can poll sockets: cat << EOF > snmpd_ss.te module snmp_ss 1.0; require { type snmpd_t; class netlink_tcpdiag_socket { bind create getattr nlmsg_read read setopt write }; } #============= snmpd_t ============== allow snmpd_t self:netlink_tcpdiag_socket { bind create getattr nlmsg_read read setopt write }; EOF checkmodule -M -m -o snmpd_ss.mod snmpd_ss.te semodule_package -o snmpd_ss.pp -m snmpd_ss.mod semodule -i snmpd_ss.pp Restart snmpd.","title":"SNMP Extend"},{"location":"Extensions/Applications/#suricata","text":"","title":"Suricata"},{"location":"Extensions/Applications/#snmp-extend_62","text":"Install the extend. cpanm Suricata::Monitoring Setup cron. Below is a example. */5 * * * * /usr/local/bin/suricata_stat_check > /dev/null Configure snmpd.conf extend suricata-stats /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin suricata_stat_check -c Or if you want to use try compressing the return via Base64+GZIP... extend suricata-stats /usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin suricata_stat_check -c -b Restart snmpd on your system. You will want to make sure Suricata is set to output the stats to the eve file once a minute. This will help make sure that it won't be to far back in the file and will make sure it is recent when the cronjob runs. Any configuration of suricata_stat_check should be done in the cron setup. If the default does not work, check the docs for it at MetaCPAN for suricata_stat_check","title":"SNMP Extend"},{"location":"Extensions/Applications/#suricata-extract","text":"","title":"Suricata Extract"},{"location":"Extensions/Applications/#snmp_1","text":"Add the following to your snmpd config and restart. Path may have to be adjusted depending on where suricata_extract_submit_extend is installed to. extend suricata_extract /usr/local/bin/suricata_extract_submit_extend Then just wait for the system to be rediscovered or enable it manually for the server in question.","title":"SNMP"},{"location":"Extensions/Applications/#systemd","text":"The systemd application polls systemd and scrapes systemd units' load, activation, and sub states.","title":"Systemd"},{"location":"Extensions/Applications/#snmp-extend_63","text":"Copy the python script, systemd.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/systemd.py -O /etc/snmp/systemd.py Make the script executable chmod +x /etc/snmp/systemd.py Edit your snmpd.conf file and add: extend systemd /etc/snmp/systemd.py (Optional) Create a /etc/snmp/systemd.json file and specify: \"systemctl_cmd\" - String path to the systemctl binary [Default: \"/usr/bin/systemctl\"] \"include_inactive_units\" - True/False string to include inactive units in results [Default: \"False\"] { \"systemctl_cmd\": \"/bin/systemctl\", \"include_inactive_units\": \"True\" } (Optional) If you have SELinux in Enforcing mode, you must add a module so the script can access systemd state: cat << EOF > snmpd_systemctl.te module snmpd_systemctl 1.0; require { type snmpd_t; type systemd_systemctl_exec_t; type init_t; class file { execute execute_no_trans map open read }; class unix_stream_socket connectto; class system status; } #============= snmpd_t ============== allow snmpd_t init_t:system status; allow snmpd_t init_t:unix_stream_socket connectto; allow snmpd_t systemd_systemctl_exec_t:file { execute execute_no_trans map open read }; EOF checkmodule -M -m -o snmpd_systemctl.mod snmpd_systemctl.te semodule_package -o snmpd_systemctl.pp -m snmpd_systemctl.mod semodule -i snmpd_systemctl.pp Restart snmpd.","title":"SNMP Extend"},{"location":"Extensions/Applications/#tinydns-aka-djbdns","text":"","title":"TinyDNS aka djbdns"},{"location":"Extensions/Applications/#agent_14","text":"Install the agent on this device if it isn't already and copy the tinydns script to /usr/lib/check_mk_agent/local/ Note : We assume that you use DJB's Daemontools to start/stop tinydns. And that your tinydns instance is located in /service/dns , adjust this path if necessary. Replace your log 's run file, typically located in /service/dns/log/run with: #!/bin/sh exec setuidgid dnslog tinystats ./main/tinystats/ multilog t n3 s250000 ./main/ Create tinystats directory and chown: mkdir /service/dns/log/main/tinystats chown dnslog:nofiles /service/dns/log/main/tinystats Restart TinyDNS and Daemontools: /etc/init.d/svscan restart Note : Some say svc -t /service/dns is enough, on my install (Gentoo) it doesn't rehook the logging and I'm forced to restart it entirely.","title":"Agent"},{"location":"Extensions/Applications/#unbound","text":"Unbound configuration: # Enable extended statistics. server: extended-statistics: yes statistics-cumulative: yes remote-control: control-enable: yes control-interface: 127.0.0.1 Restart your unbound after changing the configuration, verify it is working by running unbound-control stats .","title":"Unbound"},{"location":"Extensions/Applications/#option-1-snmp-extend-preferred-and-easiest-method","text":"Copy the shell script, unbound, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/unbound -O /etc/snmp/unbound Make the script executable chmod +x /etc/snmp/unbound Edit your snmpd.conf file and add: extend unbound /usr/bin/sudo /etc/snmp/unbound Restart snmpd. The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"Option 1. SNMP Extend (Preferred and easiest method)"},{"location":"Extensions/Applications/#option-2-agent","text":"Install the agent on this device if it isn't already and copy the unbound.sh script to /usr/lib/check_mk_agent/local/","title":"Option 2. Agent"},{"location":"Extensions/Applications/#ups-nut","text":"A small shell script that exports nut ups status.","title":"UPS-nut"},{"location":"Extensions/Applications/#snmp-extend_64","text":"Copy the shell script, unbound, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/ups-nut.sh -O /etc/snmp/ups-nut.sh Make the script executable chmod +x /etc/snmp/ups-nut.sh Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ups-nut /etc/snmp/ups-nut.sh Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page. Optionally if you have multiple UPS or your UPS is not named APCUPS you can specify its name as an argument into /etc/snmp/ups-nut.sh extend ups-nut /etc/snmp/ups-nut.sh ups1 extend ups-nut /etc/snmp/ups-nut.sh ups2","title":"SNMP Extend"},{"location":"Extensions/Applications/#ups-apcups","text":"A small shell script that exports apcacess ups status.","title":"UPS-apcups"},{"location":"Extensions/Applications/#snmp-extend_65","text":"Copy the shell script, unbound, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/ups-apcups -O /etc/snmp/ups-apcups Make the script executable chmod +x /etc/snmp/ups-apcups Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: extend ups-apcups /etc/snmp/ups-apcups If 'apcaccess' is not in the PATH enviromental variable snmpd is using, you may need to do something like below. extend ups-apcups/usr/bin/env PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin /etc/snmp/ups-apcups Restart snmpd on your host The application should be auto-discovered as described at the top of the page. If it is not, please follow the steps set out under SNMP Extend heading top of page.","title":"SNMP Extend"},{"location":"Extensions/Applications/#voip-monitor","text":"Shell script that reports cpu-load/memory/open-files files stats of Voip Monitor","title":"Voip-monitor"},{"location":"Extensions/Applications/#snmp-extend_66","text":"Download the script onto the desired host wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/voipmon-stats.sh -O /etc/snmp/voipmon-stats.sh Make the script executable chmod +x /etc/snmp/voipmon-stats.sh Edit your snmpd.conf file (usually /etc/snmp/voipmon-stats.sh ) and add: extend voipmon /etc/snmp/voipmon-stats.sh","title":"SNMP Extend"},{"location":"Extensions/Applications/#wireguard","text":"The Wireguard application polls the Wireguard service and scrapes all client statistics for all interfaces configured as Wireguard interfaces.","title":"Wireguard"},{"location":"Extensions/Applications/#snmp-extend_67","text":"Copy the python script, wireguard.py, to the desired host wget https://github.com/librenms/librenms-agent/raw/master/snmp/wireguard.py -O /etc/snmp/wireguard.py Make the script executable chmod +x /etc/snmp/wireguard.py Edit your snmpd.conf file and add: extend wireguard /etc/snmp/wireguard.py Create a /etc/snmp/wireguard.json file and specify: (optional) \"wg_cmd\" - String path to the wg binary [\"/usr/bin/wg\"] \"public_key_to_arbitrary_name\" - A dictionary to convert between the publickey assigned to the client (specified in the wireguard interface conf file) to an arbitrary, friendly name. The friendly names MUST be unique within each interface. Also note that the interface name and friendly names are used in the RRD filename, so using special characters is highly discouraged. { \"wg_cmd\": \"/bin/wg\", \"public_key_to_arbitrary_name\": { \"wg0\": { \"z1iSIymFEFi/PS8rR19AFBle7O4tWowMWuFzHO7oRlE=\": \"client1\", \"XqWJRE21Fw1ke47mH1yPg/lyWqCCfjkIXiS6JobuhTI=\": \"server.domain.com\" } } } Restart snmpd.","title":"SNMP Extend"},{"location":"Extensions/Applications/#zfs","text":"","title":"ZFS"},{"location":"Extensions/Applications/#snmp-extend_68","text":"1: Install the depends. ### FreeBSD pkg install p5-JSON p5-MIME-Base64 p5-Gzip-Faster ### Debian apt-get install -y cpanminus zlib1g-dev cpanm Mime::Base64 JSON Gzip::Faster 2: Fetch the script in question and make it executable. wget https://github.com/librenms/librenms-agent/raw/master/snmp/zfs -O /etc/snmp/zfs chmod +x /etc/snmp/zfs 3: Add the following to snmpd.conf and restart snmpd. extend zfs /etc/snmp/zfs","title":"SNMP Extend"},{"location":"Extensions/Authentication/","text":"Authentication Options LibreNMS supports multiple authentication modules along with Two Factor Auth . Here we will provide configuration details for these modules. Alternatively, you can use Socialite Providers which supports a wide variety of social/OAuth/SAML authentication methods. Available authentication modules MySQL: mysql Active Directory: active_directory LDAP: ldap Radius: radius HTTP Auth: http-auth , ad_authorization , ldap_authorization Single Sign-on: sso \u26a0\ufe0f When enabling a new authentication module, the local users will no longer be available to log in. Enable authentication module To enable a particular authentication module you need to set this up in config.php. Please note that only ONE module can be enabled. LibreNMS doesn't support multiple authentication mechanisms at the same time. auth/general lnms config:set auth_mechanism mysql User levels and User account type 1: Normal User : You will need to assign device / port permissions for users at this level. 5: Global Read : Read only Administrator. 10: Administrator : This is a global read/write admin account. 11: Demo Account : Provides full read/write with certain restrictions (i.e can't delete devices). Note Oxidized configs can often contain sensitive data. Because of that only Administrator account type can see configs. Note for SELinux users When using SELinux on the LibreNMS server, you need to allow Apache (httpd) to connect LDAP/Active Directory server, this is disabled by default. You can use SELinux Booleans to allow network access to LDAP resources with this command: setsebool -P httpd_can_connect_ldap = 1 Testing authentication You can test authentication with this script: ./scripts/auth_test.php Enable debug output to troubleshoot issues MySQL Authentication auth/general lnms config:set auth_mechanism mysql This is default option with LibreNMS so you should have already have the following configuration setup in your environment file (.env). DB_HOST=HOSTNAME DB_DATABASE=DBNAME DB_USERNAME=DBUSER DB_PASSWORD=\"DBPASS\" Active Directory Authentication auth/general lnms config:set auth_mechanism active_directory Install php-ldap or php8.1-ldap , making sure to install the same version as PHP. If you have issues with secure LDAP try setting auth/ad lnms config:set auth_ad_check_certificates 0 this will ignore certificate errors. Require actual membership of the configured groups auth/ad lnms config:set auth_ad_require_groupmembership 1 If you set auth_ad_require_groupmembership to 1, the authenticated user has to be a member of the specific group. Otherwise all users can authenticate, and will be either level 0 or you may set auth_ad_global_read to 1 and all users will have read only access unless otherwise specified. Old account cleanup Cleanup of old accounts is done by checking the authlog. You will need to set the number of days when old accounts will be purged AUTOMATICALLY by daily.sh. Please ensure that you set the authlog_purge value to be greater than active_directory.users_purge otherwise old users won't be removed. Sample configuration auth/general lnms config:set auth_mechanism active_directory lnms config:set auth_ad_url ldaps://server.example.com lnms config:set auth_ad_domain lnms config:set auth_ad_base_dn dc = example,dc = com lnms config:set auth_ad_check_certificates true lnms config:set auth_ad_binduser examplebinduser lnms config:set auth_ad_bindpassword examplepassword lnms config:set auth_ad_timeout 5 lnms config:set auth_ad_debug false lnms config:set active_directory.users_purge 30 lnms config:set auth_ad_require_groupmembership true lnms config:set auth_ad_groups.ad-admingroup.level 10 lnms config:set auth_ad_groups.ad-usergroup.level 5 Replace ad-admingroup with your Active Directory admin-user group and ad-usergroup with your standard user group. It is highly suggested to create a bind user, otherwise \"remember me\", alerting users, and the API will not work. Active Directory redundancy You can set two Active Directory servers by editing the auth_ad_url setting like this example: auth/ad lnms config:set auth_ad_url \"ldaps://dc1.example.com ldaps://dc2.example.com\" Active Directory LDAP filters You can add an LDAP filter to be ANDed with the builtin user filter ( (sAMAccountName=$username) ). The defaults are: auth/ad lnms config:set auth_ad_user_filter \"(objectclass=user)\" lnms config:set auth_ad_group_filter \"(objectclass=group)\" This yields (&(objectclass=user)(sAMAccountName=$username)) for the user filter and (&(objectclass=group)(sAMAccountName=$group)) for the group filter. SELinux configuration On RHEL / CentOS / Fedora, in order for LibreNMS to reach Active Directory, you need to allow LDAP requests in SELinux: setsebool -P httpd_can_connect_ldap 1 LDAP Authentication auth/general lnms config:set auth_mechanism ldap Install php_ldap or php7.0-ldap , making sure to install the same version as PHP. Standard config auth/ldap lnms config:set auth_ldap_server ldap.example.com lnms config:set auth_ldap_suffix ',ou=People,dc=example,dc=com' lnms config:set auth_ldap_groupbase 'ou=groups,dc=example,dc=com' lnms config:set auth_ldap_groups.admin.level 10 lnms config:set auth_ldap_groups.pfy.level 5 lnms config:set auth_ldap_groups.support.level 1 Additional options (usually not needed) auth/ldap lnms config:set auth_ldap_version 3 lnms config:set auth_ldap_port 389 lnms config:set auth_ldap_starttls true lnms config:set auth_ldap_prefix 'uid=' lnms config:set auth_ldap_group 'cn=groupname,ou=groups,dc=example,dc=com' lnms config:set auth_ldap_groupmemberattr memberUid lnms config:set auth_ldap_groupmembertype username lnms config:set auth_ldap_uid_attribute uidnumber lnms config:set auth_ldap_timeout 5 lnms config:set auth_ldap_emailattr mail lnms config:set auth_ldap_attr.uid uid lnms config:set auth_ldap_debug false lnms config:set auth_ldap_userdn true lnms config:set auth_ldap_userlist_filter service = informatique lnms config:set auth_ldap_wildcard_ou false lnms config:set auth_ldap_cacertfile /opt/librenms/ldap-ca-cert lnms config:set auth_ldap_ignorecert false LDAP bind user (optional) If your ldap server does not allow anonymous bind, it is highly suggested to create a bind user, otherwise \"remember me\", alerting users, and the API will not work. auth/ldap lnms config:set auth_ldap_binduser ldapbind lnms config:set auth_ldap_binddn 'CN=John.Smith,CN=Users,DC=MyDomain,DC=com' lnms config:set auth_ldap_bindpassword password LDAP server redundancy You can set two LDAP servers by editing the auth_ldap_server like this example: auth/ldap lnms config:set auth_ldap_server ldaps://dir1.example.com ldaps://dir2.example.com An example config setup for use with Jumpcloud LDAP as a service is: auth/ldap lnms config:set auth_mechanism ldap lnms config:set auth_ldap_version 3 lnms config:set auth_ldap_server ldap.jumpcloud.com lnms config:set auth_ldap_port 389 lnms config:set auth_ldap_prefix 'uid=' ; lnms config:set auth_ldap_suffix ',ou=Users,o={id},dc=jumpcloud,dc=com' lnms config:set auth_ldap_groupbase 'ou=Users,o={id},dc=jumpcloud,dc=com' lnms config:set auth_ldap_groupmemberattr member lnms config:set auth_ldap_groups. { group } .level 10 lnms config:set auth_ldap_userdn true Replace {id} with the unique ID provided by Jumpcloud. Replace {group} with the unique group name created in Jumpcloud. This field is case sensitive. Note: If you have multiple user groups to define individual access levels replace the auth_ldap_groups line with the following: auth/ldap lnms config:set auth_ldap_groups. { admin_group } .level 10 ] lnms config:set auth_ldap_groups.global_readonly_group.level 5 SELinux configuration On RHEL / CentOS / Fedora, in order for LibreNMS to reach LDAP, you need to allow LDAP requests in SELinux: setsebool -P httpd_can_connect_ldap 1 Radius Authentication Please note that a mysql user is created for each user the logs in successfully. Users are assigned the user role by default, unless radius sends a reply attribute with a role. You can change the default role(s) by setting auth/radius lnms config:set radius.default_roles '[\"csr\"]' The attribute Filter-ID is a standard Radius-Reply-Attribute (string) that can be assigned a specially formatted string to assign a single role to the user. The string to send in Filter-ID reply attribute must start with librenms_role_ followed by the role name. For example to set the admin role send librenms_role_admin . The following strings correspond to the built-in roles, but any defined role can be used: - librenms_role_normal - Sets the normal user level. - librenms_role_admin - Sets the administrator level. - librenms_role_global-read - Sets the global read level LibreNMS will ignore any other strings sent in Filter-ID and revert to default role that is set in your config. $config [ 'radius' ][ 'hostname' ] = 'localhost' ; $config [ 'radius' ][ 'port' ] = '1812' ; $config [ 'radius' ][ 'secret' ] = 'testing123' ; $config [ 'radius' ][ 'timeout' ] = 3 ; $config [ 'radius' ][ 'users_purge' ] = 14 ; // Purge users who haven't logged in for 14 days. $config [ 'radius' ][ 'default_level' ] = 1 ; // Set the default user level when automatically creating a user. Radius Huntgroup Freeradius has a function called Radius Huntgroup which allows to send different attributes based on NAS. This may be utilized if you already use Filter-ID in your environment and also want to use radius with LibreNMS. Old account cleanup Cleanup of old accounts is done by checking the authlog. You will need to set the number of days when old accounts will be purged AUTOMATICALLY by daily.sh. Please ensure that you set the $config['authlog_purge'] value to be greater than $config['radius']['users_purge'] otherwise old users won't be removed. HTTP Authentication Config option: http-auth LibreNMS will expect the user to have authenticated via your webservice already. At this stage it will need to assign a userlevel for that user which is done in one of two ways: A user exists in MySQL still where the usernames match up. A global guest user (which still needs to be added into MySQL: $config [ 'http_auth_guest' ] = \"guest\" ; This will then assign the userlevel for guest to all authenticated users. HTTP Authentication / AD Authorization Config option: ad-authorization This module is a combination of http-auth and active_directory LibreNMS will expect the user to have authenticated via your webservice already (e.g. using Kerberos Authentication in Apache) but will use Active Directory lookups to determine and assign the userlevel of a user. The userlevel will be calculated by using AD group membership information as the active_directory module does. The configuration is the same as for the active_directory module with two extra, optional options: auth_ad_binduser and auth_ad_bindpassword. These should be set to a AD user with read capabilities in your AD Domain in order to be able to perform searches. If these options are omitted, the module will attempt an anonymous bind (which then of course must be allowed by your Active Directory server(s)). There is also one extra option for controlling user information caching: auth_ldap_cache_ttl. This option allows to control how long user information (user_exists, userid, userlevel) are cached within the PHP Session. The default value is 300 seconds. To disable this caching (highly discourage) set this option to 0. $config [ 'auth_ad_binduser' ] = \"ad_binduser\" ; $config [ 'auth_ad_bindpassword' ] = \"ad_bindpassword\" ; $config [ 'auth_ldap_cache_ttl' ] = 300 ; HTTP Authentication / LDAP Authorization Config option: ldap-authorization This module is a combination of http-auth and ldap LibreNMS will expect the user to have authenticated via your webservice already (e.g. using Kerberos Authentication in Apache) but will use LDAP to determine and assign the userlevel of a user. The userlevel will be calculated by using LDAP group membership information as the ldap module does. The configuration is similar to the ldap module with one extra option: auth_ldap_cache_ttl. This option allows to control how long user information (user_exists, userid, userlevel) are cached within the PHP Session. The default value is 300 seconds. To disabled this caching (highly discourage) set this option to 0. Standard config $config [ 'auth_mechanism' ] = 'ldap-authorization' ; $config [ 'auth_ldap_server' ] = 'ldap.example.com' ; // Set server(s), space separated. Prefix with ldaps:// for ssl $config [ 'auth_ldap_suffix' ] = ',ou=People,dc=example,dc=com' ; // appended to usernames $config [ 'auth_ldap_groupbase' ] = 'ou=groups,dc=example,dc=com' ; // all groups must be inside this $config [ 'auth_ldap_groups' ][ 'admin' ][ 'roles' ] = [ 'admin' ]; // set admin group to admin role $config [ 'auth_ldap_groups' ][ 'pfy' ][ 'roles' ] = [ 'global-read' ]; // set pfy group to global read only role $config [ 'auth_ldap_groups' ][ 'support' ][ 'roles' ] = [ 'user' ]; // set support group as a normal user Additional options (usually not needed) $config [ 'auth_ldap_version' ] = 3 ; # v2 or v3 $config [ 'auth_ldap_port' ] = 389 ; // 389 or 636 for ssl $config [ 'auth_ldap_starttls' ] = True ; // Enable TLS on port 389 $config [ 'auth_ldap_prefix' ] = 'uid=' ; // prepended to usernames $config [ 'auth_ldap_group' ] = 'cn=groupname,ou=groups,dc=example,dc=com' ; // generic group with level 0 $config [ 'auth_ldap_groupmemberattr' ] = 'memberUid' ; // attribute to use to see if a user is a member of a group $config [ 'auth_ldap_groupmembertype' ] = 'username' ; // username type to find group members by, either username (default), fulldn or puredn $config [ 'auth_ldap_emailattr' ] = 'mail' ; // attribute for email address $config [ 'auth_ldap_attr.uid' ] = 'uid' ; // attribute to check username against $config [ 'auth_ldap_userlist_filter' ] = 'service=informatique' ; // Replace 'service=informatique' by your ldap filter to limit the number of responses if you have an ldap directory with thousand of users $config [ 'auth_ldap_cache_ttl' ] = 300 ; LDAP bind user (optional) If your ldap server does not allow anonymous bind, it is highly suggested to create a bind user, otherwise \"remember me\", alerting users, and the API will not work. $config [ 'auth_ldap_binduser' ] = 'ldapbind' ; // will use auth_ldap_prefix and auth_ldap_suffix #$config['auth_ldap_binddn'] = 'CN=John.Smith,CN=Users,DC=MyDomain,DC=com'; // overrides binduser $config [ 'auth_ldap_bindpassword' ] = 'password' ; View/embedded graphs without being logged into LibreNMS webui/graph ```bash lnms config:set allow_unauth_graphs_cidr ['127.0.0.1/32'] lnms config:set allow_unauth_graphs true ``` Single Sign-on The single sign-on mechanism is used to integrate with third party authentication providers that are managed outside of LibreNMS - such as ADFS, Shibboleth, EZProxy, BeyondCorp, and others. A large number of these methods use SAML the module has been written assuming the use of SAML, and therefore these instructions contain some SAML terminology, but it should be possible to use any software that works in a similar way. In order to make use of the single sign-on module, you need to have an Identity Provider up and running, and know how to configure your Relying Party to pass attributes to LibreNMS via header injection or environment variables. Setting these up is outside of the scope of this documentation. As this module deals with authentication, it is extremely careful about validating the configuration - if it finds that certain values in the configuration are not set, it will reject access rather than try and guess. Basic Configuration To get up and running, all you need to do is configure the following values: $config [ 'auth_mechanism' ] = \"sso\" ; $config [ 'sso' ][ 'mode' ] = \"env\" ; $config [ 'sso' ][ 'group_strategy' ] = \"static\" ; $config [ 'sso' ][ 'static_level' ] = 10 ; This, along with the defaults, sets up a basic Single Sign-on setup that: Reads values from environment variables Automatically creates users when they're first seen Automatically updates users with new values Gives everyone privilege level 10 This happens to mimic the behaviour of http-auth , so if this is the kind of setup you want, you're probably better of just going and using that mechanism. Security If there is a proxy involved (e.g. EZProxy, Azure AD Application Proxy, NGINX, mod_proxy) it's essential that you have some means in place to prevent headers being injected between the proxy and the end user, and also prevent end users from contacting LibreNMS directly. This should also apply to user connections to the proxy itself - the proxy must not be allowed to blindly pass through HTTP headers. mod security _ should be considered a minimum, with a full WAF being strongly recommended. This advice applies to the IDP too. The mechanism includes very basic protection, in the form of an IP whitelist with should contain the source addresses of your proxies: $config [ 'sso' ][ 'trusted_proxies' ] = [ '127.0.0.1/8' , '::1/128' , '192.0.2.0' , '2001:DB8::' ]; This configuration item should contain an array with a list of IP addresses or CIDR prefixes that are allowed to connect to LibreNMS and supply environment variables or headers. Advanced Configuration Options User Attribute If for some reason your relying party doesn't store the username in REMOTE_USER , you can override this choice. $config [ 'sso' ][ 'user_attr' ] = 'HTTP_UID' ; Note that the user lookup is a little special - normally headers are prefixed with HTTP_ , however this is not the case for remote user - it's a special case. If you're using something different you need to figure out of the HTTP_ prefix is required or not yourself. Automatic User Create/Update These are enabled by default: $config [ 'sso' ][ 'create_users' ] = true ; $config [ 'sso' ][ 'update_users' ] = true ; If these are not enabled, user logins will be (somewhat silently) rejected unless an administrator has created the account in advance. Note that in the case of SAML federations, unless release of the users true identity has been negotiated with the IDP, the username (probably ePTID) is not likely to be predicable. Personalisation If the attributes are being populated, you can instruct the mechanism to add additional information to the user's database entry: $config [ 'sso' ][ 'email_attr' ] = \"mail\" ; $config [ 'sso' ][ 'realname_attr' ] = \"displayName\" ; $config [ 'sso' ][ 'descr_attr' ] = \"unscoped-affiliation Group Strategies Static As used above, static gives every single user the same privilege level. If you're working with a small team, or don't need access control, this is probably suitable. Attribute $config [ 'sso' ][ 'group_strategy' ] = \"attribute\" ; $config [ 'sso' ][ 'level_attr' ] = \"entitlement\" ; If your Relying Party is capable of calculating the necessary privilege level, you can configure the module to read the privilege number straight from an attribute. sso_level_attr should contain the name of the attribute that the Relying Party exposes to LibreNMS - as long as sso_mode is correctly set, the mechanism should find the value. Group Map This is the most flexible (and complex) way of assigning privileges. $config [ 'sso' ][ 'group_strategy' ] = \"map\" ; $config [ 'sso' ][ 'group_attr' ] = \"member\" ; $config [ 'sso' ][ 'group_level_map' ] = [ 'librenms-admins' => 10 , 'librenms-readers' => 1 , 'librenms-billingcontacts' => 5 ]; $config [ 'sso' ][ 'group_delimiter' ] = ';' ; This mechanism expects to find a delimited list of groups within the attribute that sso_group_attr points to. This should be an associative array of group name keys, with privilege levels as values. The mechanism will scan the list and find the highest privilege level that the user is entitled to, and assign that value to the user. If there are no matches between the user's groups and the sso_group_level_map , the user will be assigned the privilege level specified in the sso_static_level variable, with a default of 0 (no access). This feature can be used to provide a default access level (such as read-only) to all authenticated users. Additionally, this format may be specific to Shibboleth; other relying party software may need changes to the mechanism (e.g. mod_auth_mellon may create pseudo arrays). There is an optional value for sites with large numbers of groups: $config [ 'sso' ][ 'group_filter' ] = \"/librenms-(.*)/i\" ; This filter causes the mechanism to only consider groups matching a regular expression. Logout Behaviour LibreNMS has no capability to log out a user authenticated via Single Sign-On - that responsibility falls to the Relying Party. If your Relying Party has a magic URL that needs to be called to end a session, you can configure LibreNMS to direct the user to it: # Example for Shibboleth $config [ 'auth_logout_handler' ] = '/Shibboleth.sso/Logout' ; # Example for oauth2-proxy $config [ 'auth_logout_handler' ] = '/oauth2/sign_out' ; This option functions independently of the Single Sign-on mechanism. Complete Configuration This configuration works on my deployment with a Shibboleth relying party, injecting environment variables, with the IDP supplying a list of groups. $config [ 'auth_mechanism' ] = 'sso' ; $config [ 'auth_logout_handler' ] = '/Shibboleth.sso/Logout' ; $config [ 'sso' ][ 'mode' ] = 'env' ; $config [ 'sso' ][ 'create_users' ] = true ; $config [ 'sso' ][ 'update_users' ] = true ; $config [ 'sso' ][ 'realname_attr' ] = 'displayName' ; $config [ 'sso' ][ 'email_attr' ] = 'mail' ; $config [ 'sso' ][ 'group_strategy' ] = 'map' ; $config [ 'sso' ][ 'group_attr' ] = 'member' ; $config [ 'sso' ][ 'group_filter' ] = '/(librenms-.*)/i' ; $config [ 'sso' ][ 'group_delimiter' ] = ';' ; $config [ 'sso' ][ 'group_level_map' ] = [ 'librenms-demo' => 11 , 'librenms-globaladmin' => 10 , 'librenms-globalread' => 5 , 'librenms-lowpriv' => 1 ];","title":"Authentication Options"},{"location":"Extensions/Authentication/#authentication-options","text":"LibreNMS supports multiple authentication modules along with Two Factor Auth . Here we will provide configuration details for these modules. Alternatively, you can use Socialite Providers which supports a wide variety of social/OAuth/SAML authentication methods.","title":"Authentication Options"},{"location":"Extensions/Authentication/#available-authentication-modules","text":"MySQL: mysql Active Directory: active_directory LDAP: ldap Radius: radius HTTP Auth: http-auth , ad_authorization , ldap_authorization Single Sign-on: sso \u26a0\ufe0f When enabling a new authentication module, the local users will no longer be available to log in.","title":"Available authentication modules"},{"location":"Extensions/Authentication/#enable-authentication-module","text":"To enable a particular authentication module you need to set this up in config.php. Please note that only ONE module can be enabled. LibreNMS doesn't support multiple authentication mechanisms at the same time. auth/general lnms config:set auth_mechanism mysql","title":"Enable authentication module"},{"location":"Extensions/Authentication/#user-levels-and-user-account-type","text":"1: Normal User : You will need to assign device / port permissions for users at this level. 5: Global Read : Read only Administrator. 10: Administrator : This is a global read/write admin account. 11: Demo Account : Provides full read/write with certain restrictions (i.e can't delete devices). Note Oxidized configs can often contain sensitive data. Because of that only Administrator account type can see configs.","title":"User levels and User account type"},{"location":"Extensions/Authentication/#note-for-selinux-users","text":"When using SELinux on the LibreNMS server, you need to allow Apache (httpd) to connect LDAP/Active Directory server, this is disabled by default. You can use SELinux Booleans to allow network access to LDAP resources with this command: setsebool -P httpd_can_connect_ldap = 1","title":"Note for SELinux users"},{"location":"Extensions/Authentication/#testing-authentication","text":"You can test authentication with this script: ./scripts/auth_test.php Enable debug output to troubleshoot issues","title":"Testing authentication"},{"location":"Extensions/Authentication/#mysql-authentication","text":"auth/general lnms config:set auth_mechanism mysql This is default option with LibreNMS so you should have already have the following configuration setup in your environment file (.env). DB_HOST=HOSTNAME DB_DATABASE=DBNAME DB_USERNAME=DBUSER DB_PASSWORD=\"DBPASS\"","title":"MySQL Authentication"},{"location":"Extensions/Authentication/#active-directory-authentication","text":"auth/general lnms config:set auth_mechanism active_directory Install php-ldap or php8.1-ldap , making sure to install the same version as PHP. If you have issues with secure LDAP try setting auth/ad lnms config:set auth_ad_check_certificates 0 this will ignore certificate errors.","title":"Active Directory Authentication"},{"location":"Extensions/Authentication/#require-actual-membership-of-the-configured-groups","text":"auth/ad lnms config:set auth_ad_require_groupmembership 1 If you set auth_ad_require_groupmembership to 1, the authenticated user has to be a member of the specific group. Otherwise all users can authenticate, and will be either level 0 or you may set auth_ad_global_read to 1 and all users will have read only access unless otherwise specified.","title":"Require actual membership of the configured groups"},{"location":"Extensions/Authentication/#old-account-cleanup","text":"Cleanup of old accounts is done by checking the authlog. You will need to set the number of days when old accounts will be purged AUTOMATICALLY by daily.sh. Please ensure that you set the authlog_purge value to be greater than active_directory.users_purge otherwise old users won't be removed.","title":"Old account cleanup"},{"location":"Extensions/Authentication/#sample-configuration","text":"auth/general lnms config:set auth_mechanism active_directory lnms config:set auth_ad_url ldaps://server.example.com lnms config:set auth_ad_domain lnms config:set auth_ad_base_dn dc = example,dc = com lnms config:set auth_ad_check_certificates true lnms config:set auth_ad_binduser examplebinduser lnms config:set auth_ad_bindpassword examplepassword lnms config:set auth_ad_timeout 5 lnms config:set auth_ad_debug false lnms config:set active_directory.users_purge 30 lnms config:set auth_ad_require_groupmembership true lnms config:set auth_ad_groups.ad-admingroup.level 10 lnms config:set auth_ad_groups.ad-usergroup.level 5 Replace ad-admingroup with your Active Directory admin-user group and ad-usergroup with your standard user group. It is highly suggested to create a bind user, otherwise \"remember me\", alerting users, and the API will not work.","title":"Sample configuration"},{"location":"Extensions/Authentication/#active-directory-redundancy","text":"You can set two Active Directory servers by editing the auth_ad_url setting like this example: auth/ad lnms config:set auth_ad_url \"ldaps://dc1.example.com ldaps://dc2.example.com\"","title":"Active Directory redundancy"},{"location":"Extensions/Authentication/#active-directory-ldap-filters","text":"You can add an LDAP filter to be ANDed with the builtin user filter ( (sAMAccountName=$username) ). The defaults are: auth/ad lnms config:set auth_ad_user_filter \"(objectclass=user)\" lnms config:set auth_ad_group_filter \"(objectclass=group)\" This yields (&(objectclass=user)(sAMAccountName=$username)) for the user filter and (&(objectclass=group)(sAMAccountName=$group)) for the group filter.","title":"Active Directory LDAP filters"},{"location":"Extensions/Authentication/#selinux-configuration","text":"On RHEL / CentOS / Fedora, in order for LibreNMS to reach Active Directory, you need to allow LDAP requests in SELinux: setsebool -P httpd_can_connect_ldap 1","title":"SELinux configuration"},{"location":"Extensions/Authentication/#ldap-authentication","text":"auth/general lnms config:set auth_mechanism ldap Install php_ldap or php7.0-ldap , making sure to install the same version as PHP.","title":"LDAP Authentication"},{"location":"Extensions/Authentication/#standard-config","text":"auth/ldap lnms config:set auth_ldap_server ldap.example.com lnms config:set auth_ldap_suffix ',ou=People,dc=example,dc=com' lnms config:set auth_ldap_groupbase 'ou=groups,dc=example,dc=com' lnms config:set auth_ldap_groups.admin.level 10 lnms config:set auth_ldap_groups.pfy.level 5 lnms config:set auth_ldap_groups.support.level 1","title":"Standard config"},{"location":"Extensions/Authentication/#additional-options-usually-not-needed","text":"auth/ldap lnms config:set auth_ldap_version 3 lnms config:set auth_ldap_port 389 lnms config:set auth_ldap_starttls true lnms config:set auth_ldap_prefix 'uid=' lnms config:set auth_ldap_group 'cn=groupname,ou=groups,dc=example,dc=com' lnms config:set auth_ldap_groupmemberattr memberUid lnms config:set auth_ldap_groupmembertype username lnms config:set auth_ldap_uid_attribute uidnumber lnms config:set auth_ldap_timeout 5 lnms config:set auth_ldap_emailattr mail lnms config:set auth_ldap_attr.uid uid lnms config:set auth_ldap_debug false lnms config:set auth_ldap_userdn true lnms config:set auth_ldap_userlist_filter service = informatique lnms config:set auth_ldap_wildcard_ou false lnms config:set auth_ldap_cacertfile /opt/librenms/ldap-ca-cert lnms config:set auth_ldap_ignorecert false","title":"Additional options (usually not needed)"},{"location":"Extensions/Authentication/#ldap-bind-user-optional","text":"If your ldap server does not allow anonymous bind, it is highly suggested to create a bind user, otherwise \"remember me\", alerting users, and the API will not work. auth/ldap lnms config:set auth_ldap_binduser ldapbind lnms config:set auth_ldap_binddn 'CN=John.Smith,CN=Users,DC=MyDomain,DC=com' lnms config:set auth_ldap_bindpassword password","title":"LDAP bind user (optional)"},{"location":"Extensions/Authentication/#ldap-server-redundancy","text":"You can set two LDAP servers by editing the auth_ldap_server like this example: auth/ldap lnms config:set auth_ldap_server ldaps://dir1.example.com ldaps://dir2.example.com An example config setup for use with Jumpcloud LDAP as a service is: auth/ldap lnms config:set auth_mechanism ldap lnms config:set auth_ldap_version 3 lnms config:set auth_ldap_server ldap.jumpcloud.com lnms config:set auth_ldap_port 389 lnms config:set auth_ldap_prefix 'uid=' ; lnms config:set auth_ldap_suffix ',ou=Users,o={id},dc=jumpcloud,dc=com' lnms config:set auth_ldap_groupbase 'ou=Users,o={id},dc=jumpcloud,dc=com' lnms config:set auth_ldap_groupmemberattr member lnms config:set auth_ldap_groups. { group } .level 10 lnms config:set auth_ldap_userdn true Replace {id} with the unique ID provided by Jumpcloud. Replace {group} with the unique group name created in Jumpcloud. This field is case sensitive. Note: If you have multiple user groups to define individual access levels replace the auth_ldap_groups line with the following: auth/ldap lnms config:set auth_ldap_groups. { admin_group } .level 10 ] lnms config:set auth_ldap_groups.global_readonly_group.level 5","title":"LDAP server redundancy"},{"location":"Extensions/Authentication/#selinux-configuration_1","text":"On RHEL / CentOS / Fedora, in order for LibreNMS to reach LDAP, you need to allow LDAP requests in SELinux: setsebool -P httpd_can_connect_ldap 1","title":"SELinux configuration"},{"location":"Extensions/Authentication/#radius-authentication","text":"Please note that a mysql user is created for each user the logs in successfully. Users are assigned the user role by default, unless radius sends a reply attribute with a role. You can change the default role(s) by setting auth/radius lnms config:set radius.default_roles '[\"csr\"]' The attribute Filter-ID is a standard Radius-Reply-Attribute (string) that can be assigned a specially formatted string to assign a single role to the user. The string to send in Filter-ID reply attribute must start with librenms_role_ followed by the role name. For example to set the admin role send librenms_role_admin . The following strings correspond to the built-in roles, but any defined role can be used: - librenms_role_normal - Sets the normal user level. - librenms_role_admin - Sets the administrator level. - librenms_role_global-read - Sets the global read level LibreNMS will ignore any other strings sent in Filter-ID and revert to default role that is set in your config. $config [ 'radius' ][ 'hostname' ] = 'localhost' ; $config [ 'radius' ][ 'port' ] = '1812' ; $config [ 'radius' ][ 'secret' ] = 'testing123' ; $config [ 'radius' ][ 'timeout' ] = 3 ; $config [ 'radius' ][ 'users_purge' ] = 14 ; // Purge users who haven't logged in for 14 days. $config [ 'radius' ][ 'default_level' ] = 1 ; // Set the default user level when automatically creating a user.","title":"Radius Authentication"},{"location":"Extensions/Authentication/#radius-huntgroup","text":"Freeradius has a function called Radius Huntgroup which allows to send different attributes based on NAS. This may be utilized if you already use Filter-ID in your environment and also want to use radius with LibreNMS.","title":"Radius Huntgroup"},{"location":"Extensions/Authentication/#old-account-cleanup_1","text":"Cleanup of old accounts is done by checking the authlog. You will need to set the number of days when old accounts will be purged AUTOMATICALLY by daily.sh. Please ensure that you set the $config['authlog_purge'] value to be greater than $config['radius']['users_purge'] otherwise old users won't be removed.","title":"Old account cleanup"},{"location":"Extensions/Authentication/#http-authentication","text":"Config option: http-auth LibreNMS will expect the user to have authenticated via your webservice already. At this stage it will need to assign a userlevel for that user which is done in one of two ways: A user exists in MySQL still where the usernames match up. A global guest user (which still needs to be added into MySQL: $config [ 'http_auth_guest' ] = \"guest\" ; This will then assign the userlevel for guest to all authenticated users.","title":"HTTP Authentication"},{"location":"Extensions/Authentication/#http-authentication-ad-authorization","text":"Config option: ad-authorization This module is a combination of http-auth and active_directory LibreNMS will expect the user to have authenticated via your webservice already (e.g. using Kerberos Authentication in Apache) but will use Active Directory lookups to determine and assign the userlevel of a user. The userlevel will be calculated by using AD group membership information as the active_directory module does. The configuration is the same as for the active_directory module with two extra, optional options: auth_ad_binduser and auth_ad_bindpassword. These should be set to a AD user with read capabilities in your AD Domain in order to be able to perform searches. If these options are omitted, the module will attempt an anonymous bind (which then of course must be allowed by your Active Directory server(s)). There is also one extra option for controlling user information caching: auth_ldap_cache_ttl. This option allows to control how long user information (user_exists, userid, userlevel) are cached within the PHP Session. The default value is 300 seconds. To disable this caching (highly discourage) set this option to 0. $config [ 'auth_ad_binduser' ] = \"ad_binduser\" ; $config [ 'auth_ad_bindpassword' ] = \"ad_bindpassword\" ; $config [ 'auth_ldap_cache_ttl' ] = 300 ;","title":"HTTP Authentication / AD Authorization"},{"location":"Extensions/Authentication/#http-authentication-ldap-authorization","text":"Config option: ldap-authorization This module is a combination of http-auth and ldap LibreNMS will expect the user to have authenticated via your webservice already (e.g. using Kerberos Authentication in Apache) but will use LDAP to determine and assign the userlevel of a user. The userlevel will be calculated by using LDAP group membership information as the ldap module does. The configuration is similar to the ldap module with one extra option: auth_ldap_cache_ttl. This option allows to control how long user information (user_exists, userid, userlevel) are cached within the PHP Session. The default value is 300 seconds. To disabled this caching (highly discourage) set this option to 0.","title":"HTTP Authentication / LDAP Authorization"},{"location":"Extensions/Authentication/#standard-config_1","text":"$config [ 'auth_mechanism' ] = 'ldap-authorization' ; $config [ 'auth_ldap_server' ] = 'ldap.example.com' ; // Set server(s), space separated. Prefix with ldaps:// for ssl $config [ 'auth_ldap_suffix' ] = ',ou=People,dc=example,dc=com' ; // appended to usernames $config [ 'auth_ldap_groupbase' ] = 'ou=groups,dc=example,dc=com' ; // all groups must be inside this $config [ 'auth_ldap_groups' ][ 'admin' ][ 'roles' ] = [ 'admin' ]; // set admin group to admin role $config [ 'auth_ldap_groups' ][ 'pfy' ][ 'roles' ] = [ 'global-read' ]; // set pfy group to global read only role $config [ 'auth_ldap_groups' ][ 'support' ][ 'roles' ] = [ 'user' ]; // set support group as a normal user","title":"Standard config"},{"location":"Extensions/Authentication/#additional-options-usually-not-needed_1","text":"$config [ 'auth_ldap_version' ] = 3 ; # v2 or v3 $config [ 'auth_ldap_port' ] = 389 ; // 389 or 636 for ssl $config [ 'auth_ldap_starttls' ] = True ; // Enable TLS on port 389 $config [ 'auth_ldap_prefix' ] = 'uid=' ; // prepended to usernames $config [ 'auth_ldap_group' ] = 'cn=groupname,ou=groups,dc=example,dc=com' ; // generic group with level 0 $config [ 'auth_ldap_groupmemberattr' ] = 'memberUid' ; // attribute to use to see if a user is a member of a group $config [ 'auth_ldap_groupmembertype' ] = 'username' ; // username type to find group members by, either username (default), fulldn or puredn $config [ 'auth_ldap_emailattr' ] = 'mail' ; // attribute for email address $config [ 'auth_ldap_attr.uid' ] = 'uid' ; // attribute to check username against $config [ 'auth_ldap_userlist_filter' ] = 'service=informatique' ; // Replace 'service=informatique' by your ldap filter to limit the number of responses if you have an ldap directory with thousand of users $config [ 'auth_ldap_cache_ttl' ] = 300 ;","title":"Additional options (usually not needed)"},{"location":"Extensions/Authentication/#ldap-bind-user-optional_1","text":"If your ldap server does not allow anonymous bind, it is highly suggested to create a bind user, otherwise \"remember me\", alerting users, and the API will not work. $config [ 'auth_ldap_binduser' ] = 'ldapbind' ; // will use auth_ldap_prefix and auth_ldap_suffix #$config['auth_ldap_binddn'] = 'CN=John.Smith,CN=Users,DC=MyDomain,DC=com'; // overrides binduser $config [ 'auth_ldap_bindpassword' ] = 'password' ;","title":"LDAP bind user (optional)"},{"location":"Extensions/Authentication/#viewembedded-graphs-without-being-logged-into-librenms","text":"webui/graph ```bash lnms config:set allow_unauth_graphs_cidr ['127.0.0.1/32'] lnms config:set allow_unauth_graphs true ```","title":"View/embedded graphs without being logged into LibreNMS"},{"location":"Extensions/Authentication/#single-sign-on","text":"The single sign-on mechanism is used to integrate with third party authentication providers that are managed outside of LibreNMS - such as ADFS, Shibboleth, EZProxy, BeyondCorp, and others. A large number of these methods use SAML the module has been written assuming the use of SAML, and therefore these instructions contain some SAML terminology, but it should be possible to use any software that works in a similar way. In order to make use of the single sign-on module, you need to have an Identity Provider up and running, and know how to configure your Relying Party to pass attributes to LibreNMS via header injection or environment variables. Setting these up is outside of the scope of this documentation. As this module deals with authentication, it is extremely careful about validating the configuration - if it finds that certain values in the configuration are not set, it will reject access rather than try and guess.","title":"Single Sign-on"},{"location":"Extensions/Authentication/#basic-configuration","text":"To get up and running, all you need to do is configure the following values: $config [ 'auth_mechanism' ] = \"sso\" ; $config [ 'sso' ][ 'mode' ] = \"env\" ; $config [ 'sso' ][ 'group_strategy' ] = \"static\" ; $config [ 'sso' ][ 'static_level' ] = 10 ; This, along with the defaults, sets up a basic Single Sign-on setup that: Reads values from environment variables Automatically creates users when they're first seen Automatically updates users with new values Gives everyone privilege level 10 This happens to mimic the behaviour of http-auth , so if this is the kind of setup you want, you're probably better of just going and using that mechanism.","title":"Basic Configuration"},{"location":"Extensions/Authentication/#security","text":"If there is a proxy involved (e.g. EZProxy, Azure AD Application Proxy, NGINX, mod_proxy) it's essential that you have some means in place to prevent headers being injected between the proxy and the end user, and also prevent end users from contacting LibreNMS directly. This should also apply to user connections to the proxy itself - the proxy must not be allowed to blindly pass through HTTP headers. mod security _ should be considered a minimum, with a full WAF being strongly recommended. This advice applies to the IDP too. The mechanism includes very basic protection, in the form of an IP whitelist with should contain the source addresses of your proxies: $config [ 'sso' ][ 'trusted_proxies' ] = [ '127.0.0.1/8' , '::1/128' , '192.0.2.0' , '2001:DB8::' ]; This configuration item should contain an array with a list of IP addresses or CIDR prefixes that are allowed to connect to LibreNMS and supply environment variables or headers.","title":"Security"},{"location":"Extensions/Authentication/#advanced-configuration-options","text":"","title":"Advanced Configuration Options"},{"location":"Extensions/Authentication/#user-attribute","text":"If for some reason your relying party doesn't store the username in REMOTE_USER , you can override this choice. $config [ 'sso' ][ 'user_attr' ] = 'HTTP_UID' ; Note that the user lookup is a little special - normally headers are prefixed with HTTP_ , however this is not the case for remote user - it's a special case. If you're using something different you need to figure out of the HTTP_ prefix is required or not yourself.","title":"User Attribute"},{"location":"Extensions/Authentication/#automatic-user-createupdate","text":"These are enabled by default: $config [ 'sso' ][ 'create_users' ] = true ; $config [ 'sso' ][ 'update_users' ] = true ; If these are not enabled, user logins will be (somewhat silently) rejected unless an administrator has created the account in advance. Note that in the case of SAML federations, unless release of the users true identity has been negotiated with the IDP, the username (probably ePTID) is not likely to be predicable.","title":"Automatic User Create/Update"},{"location":"Extensions/Authentication/#personalisation","text":"If the attributes are being populated, you can instruct the mechanism to add additional information to the user's database entry: $config [ 'sso' ][ 'email_attr' ] = \"mail\" ; $config [ 'sso' ][ 'realname_attr' ] = \"displayName\" ; $config [ 'sso' ][ 'descr_attr' ] = \"unscoped-affiliation","title":"Personalisation"},{"location":"Extensions/Authentication/#group-strategies","text":"","title":"Group Strategies"},{"location":"Extensions/Authentication/#static","text":"As used above, static gives every single user the same privilege level. If you're working with a small team, or don't need access control, this is probably suitable.","title":"Static"},{"location":"Extensions/Authentication/#attribute","text":"$config [ 'sso' ][ 'group_strategy' ] = \"attribute\" ; $config [ 'sso' ][ 'level_attr' ] = \"entitlement\" ; If your Relying Party is capable of calculating the necessary privilege level, you can configure the module to read the privilege number straight from an attribute. sso_level_attr should contain the name of the attribute that the Relying Party exposes to LibreNMS - as long as sso_mode is correctly set, the mechanism should find the value.","title":"Attribute"},{"location":"Extensions/Authentication/#group-map","text":"This is the most flexible (and complex) way of assigning privileges. $config [ 'sso' ][ 'group_strategy' ] = \"map\" ; $config [ 'sso' ][ 'group_attr' ] = \"member\" ; $config [ 'sso' ][ 'group_level_map' ] = [ 'librenms-admins' => 10 , 'librenms-readers' => 1 , 'librenms-billingcontacts' => 5 ]; $config [ 'sso' ][ 'group_delimiter' ] = ';' ; This mechanism expects to find a delimited list of groups within the attribute that sso_group_attr points to. This should be an associative array of group name keys, with privilege levels as values. The mechanism will scan the list and find the highest privilege level that the user is entitled to, and assign that value to the user. If there are no matches between the user's groups and the sso_group_level_map , the user will be assigned the privilege level specified in the sso_static_level variable, with a default of 0 (no access). This feature can be used to provide a default access level (such as read-only) to all authenticated users. Additionally, this format may be specific to Shibboleth; other relying party software may need changes to the mechanism (e.g. mod_auth_mellon may create pseudo arrays). There is an optional value for sites with large numbers of groups: $config [ 'sso' ][ 'group_filter' ] = \"/librenms-(.*)/i\" ; This filter causes the mechanism to only consider groups matching a regular expression.","title":"Group Map"},{"location":"Extensions/Authentication/#logout-behaviour","text":"LibreNMS has no capability to log out a user authenticated via Single Sign-On - that responsibility falls to the Relying Party. If your Relying Party has a magic URL that needs to be called to end a session, you can configure LibreNMS to direct the user to it: # Example for Shibboleth $config [ 'auth_logout_handler' ] = '/Shibboleth.sso/Logout' ; # Example for oauth2-proxy $config [ 'auth_logout_handler' ] = '/oauth2/sign_out' ; This option functions independently of the Single Sign-on mechanism.","title":"Logout Behaviour"},{"location":"Extensions/Authentication/#complete-configuration","text":"This configuration works on my deployment with a Shibboleth relying party, injecting environment variables, with the IDP supplying a list of groups. $config [ 'auth_mechanism' ] = 'sso' ; $config [ 'auth_logout_handler' ] = '/Shibboleth.sso/Logout' ; $config [ 'sso' ][ 'mode' ] = 'env' ; $config [ 'sso' ][ 'create_users' ] = true ; $config [ 'sso' ][ 'update_users' ] = true ; $config [ 'sso' ][ 'realname_attr' ] = 'displayName' ; $config [ 'sso' ][ 'email_attr' ] = 'mail' ; $config [ 'sso' ][ 'group_strategy' ] = 'map' ; $config [ 'sso' ][ 'group_attr' ] = 'member' ; $config [ 'sso' ][ 'group_filter' ] = '/(librenms-.*)/i' ; $config [ 'sso' ][ 'group_delimiter' ] = ';' ; $config [ 'sso' ][ 'group_level_map' ] = [ 'librenms-demo' => 11 , 'librenms-globaladmin' => 10 , 'librenms-globalread' => 5 , 'librenms-lowpriv' => 1 ];","title":"Complete Configuration"},{"location":"Extensions/Auto-Discovery/","text":"Auto Discovery Support Getting Started LibreNMS provides the ability to automatically add devices on your network, we can do this via a few methods which will be explained below and also indicate if they are enabled by default. All discovery methods run when discovery runs (every 6 hours by default and within 5 minutes for new devices). Please note that you need at least ONE device added before auto-discovery will work. The first thing to do though is add the required configuration options to config.php . SNMP Details To add devices automatically we need to know your snmp details, examples of SNMP v1, v2c and v3 are below: // v1 or v2c $config [ 'snmp' ][ 'community' ][] = \"my_custom_community\" ; $config [ 'snmp' ][ 'community' ][] = \"another_community\" ; // v3 $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authlevel' ] = 'authPriv' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authname' ] = 'my_username' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authpass' ] = 'my_password' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authalgo' ] = 'SHA' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'cryptopass' ] = 'my_crypto' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'cryptoalgo' ] = 'AES' ; These details will be attempted when adding devices, you can specify any mixture of these. Allowed Networks Your Networks To add devices, we need to know what are your subnets so we don't go blindly attempting to add devices not under your control. discovery/networks lnms config:set nets.+ '192.168.0.0/24' lnms config:set nets.+ '172.2.4.0/22' Exclusions If you have added a network as above but a single device exists within it that you can't auto add, then you can exclude this with the following: discovery/networks lnms config:set autodiscovery.nets-exclude.+ '192.168.0.1/32' Additional Options Discovering devices by IP By default we don't add devices by IP address, we look for a reverse dns name to be found and add with that. If this fails and you would like to still add devices automatically then you will need to set $config['discovery_by_ip'] = true; Short hostnames If your devices only return a short hostname such as lax-fa0-dc01 but the full name should be lax-fa0-dc01.example.com then you can set discovery/general lnms config:set mydomain example.com Allow Duplicate sysName By default we require unique sysNames when adding devices (this is returned over snmp by your devices). If you would like to allow devices to be added with duplicate sysNames then please set discovery/discovery_modules lnms config:set allow_duplicate_sysName true Discovery Methods Below are the methods for auto discovering devices. Each one can be enabled or disabled and may have additional configuration options. ARP Disabled by default. Adds devices that are listed in another device's arp table. This module depends on the arp-table module being enabled and returning data. To enable, switch on globally the discovery_modules.discovery-arp or per device within the Modules section. discovery/discovery_modules lnms config:set discovery_modules.discovery-arp true XDP Enabled by default. $config['autodiscovery']['xdp'] = false; to disable. This includes FDP, CDP and LLDP support based on the device type. The LLDP/xDP links with neighbours will always be discovered as soon as the discovery module is enabled. However, LibreNMS will only try to add the new devices discovered with LLDP/xDP if $config['autodiscovery']['xdp'] = true; . Devices may be excluded from xdp discovery by sysName and sysDescr. //Exclude devices by name $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysname_regexp' ][] = '/host1/' ; $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysname_regexp' ][] = '/^dev/' ; //Exclude devices by description $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysdesc_regexp' ][] = '/Vendor X/' ; $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysdesc_regexp' ][] = '/Vendor Y/' ; Devices may be excluded from cdp discovery by platform. //Exclude devices by platform(Cisco only) $config [ 'autodiscovery' ][ 'cdp_exclude' ][ 'platform_regexp' ][] = '/WS-C3750G/' ; These devices are excluded by default: $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysdesc_regexp' ][] = '/-K9W8/' ; // Cisco Lightweight Access Point $config [ 'autodiscovery' ][ 'cdp_exclude' ][ 'platform_regexp' ][] = '/^Cisco IP Phone/' ; //Cisco IP Phone OSPF Enabled by default. $config['autodiscovery']['ospf'] = false; to disable. BGP Enabled by default. $config['autodiscovery']['bgp'] = false; to disable. This module is invoked from bgp-peers discovery module. SNMP Scan Apart from the aforementioned Auto-Discovery options, LibreNMS is also able to proactively scan a network for SNMP-enabled devices using the configured version/credentials. SNMP Scan will scan nets by default and respects autodiscovery.nets-exclude . To run the SNMP-Scanner you need to execute the snmp-scan.py from within your LibreNMS installation directory. Here the script's help-page for reference: usage: snmp-scan.py [-h] [-t THREADS] [-g GROUP] [-l] [-v] [--ping-fallback] [--ping-only] [-P] [network ...] Scan network for snmp hosts and add them to LibreNMS. positional arguments: network CIDR noted IP-Range to scan. Can be specified multiple times This argument is only required if 'nets' config is not set Example: 192.168.0.0/24 Example: 192.168.0.0/31 will be treated as an RFC3021 p-t-p network with two addresses, 192.168.0.0 and 192.168.0.1 Example: 192.168.0.1/32 will be treated as a single host address optional arguments: -h, --help show this help message and exit -t THREADS How many IPs to scan at a time. More will increase the scan speed, but could overload your system. Default: 32 -g GROUP The poller group all scanned devices will be added to. Default: The first group listed in 'distributed_poller_group', or 0 if not specificed -l, --legend Print the legend. -v, --verbose Show debug output. Specifying multiple times increases the verbosity. --ping-fallback Add the device as an ICMP only device if it replies to ping but not SNMP. --ping-only Always add the device as an ICMP only device. -P, --ping Deprecated. Use --ping-fallback instead. Discovered devices Newly discovered devices will be added to the default_poller_group , this value defaults to 0 if unset. When using distributed polling, this value can be changed locally by setting $config['default_poller_group'] in config.php or globally by using lnms config:set .","title":"Auto-discovery Setup"},{"location":"Extensions/Auto-Discovery/#auto-discovery-support","text":"","title":"Auto Discovery Support"},{"location":"Extensions/Auto-Discovery/#getting-started","text":"LibreNMS provides the ability to automatically add devices on your network, we can do this via a few methods which will be explained below and also indicate if they are enabled by default. All discovery methods run when discovery runs (every 6 hours by default and within 5 minutes for new devices). Please note that you need at least ONE device added before auto-discovery will work. The first thing to do though is add the required configuration options to config.php .","title":"Getting Started"},{"location":"Extensions/Auto-Discovery/#snmp-details","text":"To add devices automatically we need to know your snmp details, examples of SNMP v1, v2c and v3 are below: // v1 or v2c $config [ 'snmp' ][ 'community' ][] = \"my_custom_community\" ; $config [ 'snmp' ][ 'community' ][] = \"another_community\" ; // v3 $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authlevel' ] = 'authPriv' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authname' ] = 'my_username' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authpass' ] = 'my_password' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'authalgo' ] = 'SHA' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'cryptopass' ] = 'my_crypto' ; $config [ 'snmp' ][ 'v3' ][ 0 ][ 'cryptoalgo' ] = 'AES' ; These details will be attempted when adding devices, you can specify any mixture of these.","title":"SNMP Details"},{"location":"Extensions/Auto-Discovery/#allowed-networks","text":"","title":"Allowed Networks"},{"location":"Extensions/Auto-Discovery/#your-networks","text":"To add devices, we need to know what are your subnets so we don't go blindly attempting to add devices not under your control. discovery/networks lnms config:set nets.+ '192.168.0.0/24' lnms config:set nets.+ '172.2.4.0/22'","title":"Your Networks"},{"location":"Extensions/Auto-Discovery/#exclusions","text":"If you have added a network as above but a single device exists within it that you can't auto add, then you can exclude this with the following: discovery/networks lnms config:set autodiscovery.nets-exclude.+ '192.168.0.1/32'","title":"Exclusions"},{"location":"Extensions/Auto-Discovery/#additional-options","text":"","title":"Additional Options"},{"location":"Extensions/Auto-Discovery/#discovering-devices-by-ip","text":"By default we don't add devices by IP address, we look for a reverse dns name to be found and add with that. If this fails and you would like to still add devices automatically then you will need to set $config['discovery_by_ip'] = true;","title":"Discovering devices by IP"},{"location":"Extensions/Auto-Discovery/#short-hostnames","text":"If your devices only return a short hostname such as lax-fa0-dc01 but the full name should be lax-fa0-dc01.example.com then you can set discovery/general lnms config:set mydomain example.com","title":"Short hostnames"},{"location":"Extensions/Auto-Discovery/#allow-duplicate-sysname","text":"By default we require unique sysNames when adding devices (this is returned over snmp by your devices). If you would like to allow devices to be added with duplicate sysNames then please set discovery/discovery_modules lnms config:set allow_duplicate_sysName true","title":"Allow Duplicate sysName"},{"location":"Extensions/Auto-Discovery/#discovery-methods","text":"Below are the methods for auto discovering devices. Each one can be enabled or disabled and may have additional configuration options.","title":"Discovery Methods"},{"location":"Extensions/Auto-Discovery/#arp","text":"Disabled by default. Adds devices that are listed in another device's arp table. This module depends on the arp-table module being enabled and returning data. To enable, switch on globally the discovery_modules.discovery-arp or per device within the Modules section. discovery/discovery_modules lnms config:set discovery_modules.discovery-arp true","title":"ARP"},{"location":"Extensions/Auto-Discovery/#xdp","text":"Enabled by default. $config['autodiscovery']['xdp'] = false; to disable. This includes FDP, CDP and LLDP support based on the device type. The LLDP/xDP links with neighbours will always be discovered as soon as the discovery module is enabled. However, LibreNMS will only try to add the new devices discovered with LLDP/xDP if $config['autodiscovery']['xdp'] = true; . Devices may be excluded from xdp discovery by sysName and sysDescr. //Exclude devices by name $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysname_regexp' ][] = '/host1/' ; $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysname_regexp' ][] = '/^dev/' ; //Exclude devices by description $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysdesc_regexp' ][] = '/Vendor X/' ; $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysdesc_regexp' ][] = '/Vendor Y/' ; Devices may be excluded from cdp discovery by platform. //Exclude devices by platform(Cisco only) $config [ 'autodiscovery' ][ 'cdp_exclude' ][ 'platform_regexp' ][] = '/WS-C3750G/' ; These devices are excluded by default: $config [ 'autodiscovery' ][ 'xdp_exclude' ][ 'sysdesc_regexp' ][] = '/-K9W8/' ; // Cisco Lightweight Access Point $config [ 'autodiscovery' ][ 'cdp_exclude' ][ 'platform_regexp' ][] = '/^Cisco IP Phone/' ; //Cisco IP Phone","title":"XDP"},{"location":"Extensions/Auto-Discovery/#ospf","text":"Enabled by default. $config['autodiscovery']['ospf'] = false; to disable.","title":"OSPF"},{"location":"Extensions/Auto-Discovery/#bgp","text":"Enabled by default. $config['autodiscovery']['bgp'] = false; to disable. This module is invoked from bgp-peers discovery module.","title":"BGP"},{"location":"Extensions/Auto-Discovery/#snmp-scan","text":"Apart from the aforementioned Auto-Discovery options, LibreNMS is also able to proactively scan a network for SNMP-enabled devices using the configured version/credentials. SNMP Scan will scan nets by default and respects autodiscovery.nets-exclude . To run the SNMP-Scanner you need to execute the snmp-scan.py from within your LibreNMS installation directory. Here the script's help-page for reference: usage: snmp-scan.py [-h] [-t THREADS] [-g GROUP] [-l] [-v] [--ping-fallback] [--ping-only] [-P] [network ...] Scan network for snmp hosts and add them to LibreNMS. positional arguments: network CIDR noted IP-Range to scan. Can be specified multiple times This argument is only required if 'nets' config is not set Example: 192.168.0.0/24 Example: 192.168.0.0/31 will be treated as an RFC3021 p-t-p network with two addresses, 192.168.0.0 and 192.168.0.1 Example: 192.168.0.1/32 will be treated as a single host address optional arguments: -h, --help show this help message and exit -t THREADS How many IPs to scan at a time. More will increase the scan speed, but could overload your system. Default: 32 -g GROUP The poller group all scanned devices will be added to. Default: The first group listed in 'distributed_poller_group', or 0 if not specificed -l, --legend Print the legend. -v, --verbose Show debug output. Specifying multiple times increases the verbosity. --ping-fallback Add the device as an ICMP only device if it replies to ping but not SNMP. --ping-only Always add the device as an ICMP only device. -P, --ping Deprecated. Use --ping-fallback instead.","title":"SNMP Scan"},{"location":"Extensions/Auto-Discovery/#discovered-devices","text":"Newly discovered devices will be added to the default_poller_group , this value defaults to 0 if unset. When using distributed polling, this value can be changed locally by setting $config['default_poller_group'] in config.php or globally by using lnms config:set .","title":"Discovered devices"},{"location":"Extensions/Availability-Map/","text":"Availability Map LibreNMS has the following page to show an availability map: Overview -> Maps -> Availability This map will show all devices on a single page, with each device having either a box or a coloured square representing its status. Widget There is an availability map widget that can be added to a dashboard to give a quick overview of the status of all devices on the network. Settings # Set the compact view mode for the availability map lnms config:set webui.availability_map_compact false # Size of the box for each device in the availability map (not compact) lnms config:set webui.availability_map_box_size 165 # Sort by status instead of hostname lnms config:set webui.availability_map_sort_status false # Show the device group drop-down on the availabiltiy map page lnms config:set webui.availability_map_use_device_groups true","title":"Availability Map"},{"location":"Extensions/Availability-Map/#availability-map","text":"LibreNMS has the following page to show an availability map: Overview -> Maps -> Availability This map will show all devices on a single page, with each device having either a box or a coloured square representing its status.","title":"Availability Map"},{"location":"Extensions/Availability-Map/#widget","text":"There is an availability map widget that can be added to a dashboard to give a quick overview of the status of all devices on the network.","title":"Widget"},{"location":"Extensions/Availability-Map/#settings","text":"# Set the compact view mode for the availability map lnms config:set webui.availability_map_compact false # Size of the box for each device in the availability map (not compact) lnms config:set webui.availability_map_box_size 165 # Sort by status instead of hostname lnms config:set webui.availability_map_sort_status false # Show the device group drop-down on the availabiltiy map page lnms config:set webui.availability_map_use_device_groups true","title":"Settings"},{"location":"Extensions/Billing-Module/","text":"Billing Module With the billing module you can create a bill, assign a quota to it and add ports to it. It then tracks the ports usage and shows you the usage in the bill, including any overage. Accounting by both total transferred data and 95th percentile is supported. To enable and use the billing module you need to perform the following steps: Edit config.php and add (or enable) the following line near the end of the config $config [ 'enable_billing' ] = 1 ; # Enable Billing Edit /etc/cron.d/librenms and add the following: */5 * * * * librenms /opt/librenms/poll-billing.php >> /dev/null 2 > & 1 01 * * * * librenms /opt/librenms/billing-calculate.php >> /dev/null 2 > & 1 Create billing graphs as required. Data Retention Billing data is stored in the MySQL database, and you may wish to purge the detailed stats for old data (per-month totals will always be kept). To enable this, add the following to config.php : $config [ 'billing_data_purge' ] = 12 ; // Number of months to retain Data for the last complete billing cycle will always be retained - only data older than this by the configured number of months will be removed. This task is performed in the daily cleanup tasks. 95th Percentile Calculation For 95th Percentile billing, the default behavior is to use the highest of the input or output 95th Percentile calculation. To instead use the combined total of inout + output to derive the 95th percentile, This can be changed on a per bill basis by setting 95th Calculation to \"Aggregate\". To change the default option to Aggregate, add the following the config.php : $config [ 'billing' ][ '95th_default_agg' ] = 1 ; // Set aggregate 95th as default This configuration setting is cosmetic and only changes the default selected option when adding a new bill.","title":"Billing Module"},{"location":"Extensions/Billing-Module/#billing-module","text":"With the billing module you can create a bill, assign a quota to it and add ports to it. It then tracks the ports usage and shows you the usage in the bill, including any overage. Accounting by both total transferred data and 95th percentile is supported. To enable and use the billing module you need to perform the following steps: Edit config.php and add (or enable) the following line near the end of the config $config [ 'enable_billing' ] = 1 ; # Enable Billing Edit /etc/cron.d/librenms and add the following: */5 * * * * librenms /opt/librenms/poll-billing.php >> /dev/null 2 > & 1 01 * * * * librenms /opt/librenms/billing-calculate.php >> /dev/null 2 > & 1 Create billing graphs as required.","title":"Billing Module"},{"location":"Extensions/Billing-Module/#data-retention","text":"Billing data is stored in the MySQL database, and you may wish to purge the detailed stats for old data (per-month totals will always be kept). To enable this, add the following to config.php : $config [ 'billing_data_purge' ] = 12 ; // Number of months to retain Data for the last complete billing cycle will always be retained - only data older than this by the configured number of months will be removed. This task is performed in the daily cleanup tasks.","title":"Data Retention"},{"location":"Extensions/Billing-Module/#95th-percentile-calculation","text":"For 95th Percentile billing, the default behavior is to use the highest of the input or output 95th Percentile calculation. To instead use the combined total of inout + output to derive the 95th percentile, This can be changed on a per bill basis by setting 95th Calculation to \"Aggregate\". To change the default option to Aggregate, add the following the config.php : $config [ 'billing' ][ '95th_default_agg' ] = 1 ; // Set aggregate 95th as default This configuration setting is cosmetic and only changes the default selected option when adding a new bill.","title":"95th Percentile Calculation"},{"location":"Extensions/Component/","text":"About The Component extension provides a generic database storage mechanism for discovery and poller modules. The Driver behind this extension was to provide the features of ports, in a generic manner to discovery/poller modules. It provides a status (Nagios convention), the ability to Disable (do not poll), or Ignore (do not Alert). Database Structure The database structure contains the component table: mysql > select * from component limit 1 ; + ----+-----------+------+------------+--------+----------+--------+-------+ | id | device_id | type | label | status | disabled | ignore | error | + ----+-----------+------+------------+--------+----------+--------+-------+ | 9 | 1 | TEST | TEST LABEL | 0 | 1 | 1 | | + ----+-----------+------+------------+--------+----------+--------+-------+ 1 row in set ( 0 . 00 sec ) These fields are described below: id - ID for each component, unique index device_id - device_id from the devices table type - name from the component_type table label - Display label for the component status - The status of the component, retrieved from the device disabled - Should this component be polled? ignore - Should this component be alerted on error - Error message if in Alert state The component_prefs table holds custom data in an Attribute/Value format: mysql > select * from component_prefs limit 1 ; + ----+-----------+-----------+-----------+ | id | component | attribute | value | + ----+-----------+-----------+-----------+ | 4 | 9 | TEST_ATTR | TEST_ATTR | + ----+-----------+-----------+-----------+ 2 rows in set ( 0 . 00 sec ) Reserved Fields When this data from both the component and component_prefs tables is returned in one single consolidated array, there is the potential for someone to attempt to set an attribute (in the component_prefs ) table that is used in the component table. Because of this all fields of the component table are reserved, they cannot be used as custom attributes, if you update these the module will attempt to write them to the component table, not the component_prefs table. Using Components Create an instance of the component class: $COMPONENT = new LibreNMS\\Component (); Retrieving Components Now you can retrieve an array of the available components: $ARRAY = $COMPONENT -> getComponents ( $DEVICE_ID , $OPTIONS ); getComponents takes 2 arguments: DEVICE_ID or null for all devices. OPTIONS - an array of various options. getComponents will return an array containing components in the following format: Array ( [ X ] => Array ( [ Y1 ] => Array ( [ device_id ] => 1 [ TEST_ATTR ] => TEST_ATTR [ type ] => TEST [ label ] => TEST LABEL [ status ] => 0 [ ignore ] => 1 [ disabled ] => 1 [ error ] => ), [ Y2 ] => Array ( [ device_id ] => 1 [ TEST_ATTR ] => TEST_ATTR [ type ] => TESTING [ label ] => TEST LABEL [ status ] => 0 [ ignore ] => 1 [ disabled ] => 0 [ error ] => ), ) ) Where X is the Device ID and Y1/Y2 is the Component ID. In the example above, TEST_ATTR is a custom field, the rest are reserved fields. Options Options can be supplied to getComponents to influence which and how components are returned. Filtering You can filter on any of the reserved fields. Filters are created in the following format: $options [ 'filter' ][ 'FIELD' ] = array ( 'OPERATOR' , 'CRITERIA' ); Where: FIELD - The reserved field to filter on OPERATOR - 'LIKE' or '=', are we checking if the FIELD equals or contains the CRITERIA. CRITERIA - The criteria to search on There are 2 filtering shortcuts: $DEVICE_ID is a synonym for: $OPTIONS [ 'filter' ][ 'device_id' ] = array ( '=' , $DEVICE_ID ); $OPTIONS['type'] = $TYPE is a synonym for: $OPTIONS [ 'filter' ][ 'type' ] = array ( '=' , $TYPE ); Sorting You can sort the records that are returned by specifying the following option: $OPTIONS [ 'sort' ][ FIELD ] = 'DIRECTION' ; Where Direction is one of: ASC - Ascending, from Low to High DESC - Descending, from High to Low Creating Components To create a new component, run the createComponent function. $ARRAY = $COMPONENT -> createComponent ( $DEVICE_ID , $TYPE ); createComponent takes 2 arguments: DEVICE_ID - The ID of the device to attach the component to. TYPE - The unique type for your module. This will return a new, empty array with a component ID and Type set, all other fields will be set to defaults. Array ( [ 1 ] => Array ( [ type ] => TESTING [ label ] => [ status ] => 1 [ ignore ] => 0 [ disabled ] => 0 [ error ] => ) ) Deleting Components When a component is no longer needed, it can be deleted. $COMPONENT -> deleteComponent ( $COMPONENT_ID ) This will return True on success or False on failure. Editing Components To edit a component, the procedure is: Get the Current Components Edit the array Write the components Edit the Array Once you have a component array from getComponents the first thing to do is extract the components for only the single device you are editing. This is required because the setComponentPrefs function only saves a single device at a time. $ARRAY = $COMPONENT -> getComponents ( $DEVICE_ID , $OPTIONS ); $ARRAY = $ARRAY [ $DEVICE_ID ]; Then simply edit this array to suit your needs. If you need to add a new Attribute/Value pair you can: $ARRAY [ COMPONENT_ID ][ 'New Attribute' ] = \"Value\" ; If you need to delete a previously set Attribute/Value pair you can: unset ( $ARRAY [ COMPONENT_ID ][ 'New Attribute' ]); If you need to edit a previously set Attribute/Value pair you can: $ARRAY [ COMPONENT_ID ][ 'Existing Attribute' ] = \"New Value\" ; Write the components To write component changes back to the database simply: $COMPONENT -> setComponentPrefs ( $DEVICE_ID , $ARRAY ) When writing the component array there are several caveats to be aware of, these are: $ARRAY must be in the format of a single device ID - $ARRAY[$COMPONENT_ID][Attribute] = 'Value'; NOT in the multi device format returned by getComponents - $ARRAY[$DEVICE_ID][$COMPONENT_ID][Attribute] = 'Value'; You cannot edit the Component ID or the Device ID reserved fields can not be removed if a change is found an entry will be written to the eventlog. API Component details are available via the API. Please see the API-Docs for details. Alerting It is intended that discovery/poller modules will detect the status of a component during the polling cycle. Status is logged using the Nagios convention for status codes, where: 0 = Ok, 1 = Warning, 2 = Critical If you are creating a poller module which can detect a fault condition simply set STATUS to something other than 0 and ERROR to a message that indicates the problem. To actually raise an alert, the user will need to create an alert rule. To assist with this several Alerting Macro's have been created: %macro.component_normal - A component that is not disabled or ignored and in a Normal state. %macro.component_warning - A component that is not disabled or ignored and NOT in a Warning state. %macro.component_critical - A component that is not disabled or ignored and NOT in a Critical state. To raise alerts for components, the following rules could be created: %macros.component_critical = \"1\" - To alert on all Critical components %macros.component_critical = \"1\" && %component.type = \"\" - To alert on all Critical components of a particular type. If there is a particular component you would like excluded from alerting, simply set the ignore field to 1. The data that is written to each alert when it is raised is in the following format: COMPONENT_TYPE - LABEL - ERROR Example Code To see an example of how the component module can used, please see the following modules: Cisco CBQoS includes/discovery/cisco-cbqos.inc.php includes/polling/cisco-cbqos.inc.php html/includes/graphs/device/cbqos_traffic.inc.php Cisco OTV includes/discovery/cisco-otv.inc.php includes/polling/cisco-otv.inc.php html/includes/graphs/device/cisco-otv-mac.inc.php html/pages/routing/cisco-otv.inc.php","title":"Component"},{"location":"Extensions/Component/#about","text":"The Component extension provides a generic database storage mechanism for discovery and poller modules. The Driver behind this extension was to provide the features of ports, in a generic manner to discovery/poller modules. It provides a status (Nagios convention), the ability to Disable (do not poll), or Ignore (do not Alert).","title":"About"},{"location":"Extensions/Component/#database-structure","text":"The database structure contains the component table: mysql > select * from component limit 1 ; + ----+-----------+------+------------+--------+----------+--------+-------+ | id | device_id | type | label | status | disabled | ignore | error | + ----+-----------+------+------------+--------+----------+--------+-------+ | 9 | 1 | TEST | TEST LABEL | 0 | 1 | 1 | | + ----+-----------+------+------------+--------+----------+--------+-------+ 1 row in set ( 0 . 00 sec ) These fields are described below: id - ID for each component, unique index device_id - device_id from the devices table type - name from the component_type table label - Display label for the component status - The status of the component, retrieved from the device disabled - Should this component be polled? ignore - Should this component be alerted on error - Error message if in Alert state The component_prefs table holds custom data in an Attribute/Value format: mysql > select * from component_prefs limit 1 ; + ----+-----------+-----------+-----------+ | id | component | attribute | value | + ----+-----------+-----------+-----------+ | 4 | 9 | TEST_ATTR | TEST_ATTR | + ----+-----------+-----------+-----------+ 2 rows in set ( 0 . 00 sec )","title":"Database Structure"},{"location":"Extensions/Component/#reserved-fields","text":"When this data from both the component and component_prefs tables is returned in one single consolidated array, there is the potential for someone to attempt to set an attribute (in the component_prefs ) table that is used in the component table. Because of this all fields of the component table are reserved, they cannot be used as custom attributes, if you update these the module will attempt to write them to the component table, not the component_prefs table.","title":"Reserved Fields"},{"location":"Extensions/Component/#using-components","text":"Create an instance of the component class: $COMPONENT = new LibreNMS\\Component ();","title":"Using Components"},{"location":"Extensions/Component/#retrieving-components","text":"Now you can retrieve an array of the available components: $ARRAY = $COMPONENT -> getComponents ( $DEVICE_ID , $OPTIONS ); getComponents takes 2 arguments: DEVICE_ID or null for all devices. OPTIONS - an array of various options. getComponents will return an array containing components in the following format: Array ( [ X ] => Array ( [ Y1 ] => Array ( [ device_id ] => 1 [ TEST_ATTR ] => TEST_ATTR [ type ] => TEST [ label ] => TEST LABEL [ status ] => 0 [ ignore ] => 1 [ disabled ] => 1 [ error ] => ), [ Y2 ] => Array ( [ device_id ] => 1 [ TEST_ATTR ] => TEST_ATTR [ type ] => TESTING [ label ] => TEST LABEL [ status ] => 0 [ ignore ] => 1 [ disabled ] => 0 [ error ] => ), ) ) Where X is the Device ID and Y1/Y2 is the Component ID. In the example above, TEST_ATTR is a custom field, the rest are reserved fields.","title":"Retrieving Components"},{"location":"Extensions/Component/#options","text":"Options can be supplied to getComponents to influence which and how components are returned.","title":"Options"},{"location":"Extensions/Component/#filtering","text":"You can filter on any of the reserved fields. Filters are created in the following format: $options [ 'filter' ][ 'FIELD' ] = array ( 'OPERATOR' , 'CRITERIA' ); Where: FIELD - The reserved field to filter on OPERATOR - 'LIKE' or '=', are we checking if the FIELD equals or contains the CRITERIA. CRITERIA - The criteria to search on There are 2 filtering shortcuts: $DEVICE_ID is a synonym for: $OPTIONS [ 'filter' ][ 'device_id' ] = array ( '=' , $DEVICE_ID ); $OPTIONS['type'] = $TYPE is a synonym for: $OPTIONS [ 'filter' ][ 'type' ] = array ( '=' , $TYPE );","title":"Filtering"},{"location":"Extensions/Component/#sorting","text":"You can sort the records that are returned by specifying the following option: $OPTIONS [ 'sort' ][ FIELD ] = 'DIRECTION' ; Where Direction is one of: ASC - Ascending, from Low to High DESC - Descending, from High to Low","title":"Sorting"},{"location":"Extensions/Component/#creating-components","text":"To create a new component, run the createComponent function. $ARRAY = $COMPONENT -> createComponent ( $DEVICE_ID , $TYPE ); createComponent takes 2 arguments: DEVICE_ID - The ID of the device to attach the component to. TYPE - The unique type for your module. This will return a new, empty array with a component ID and Type set, all other fields will be set to defaults. Array ( [ 1 ] => Array ( [ type ] => TESTING [ label ] => [ status ] => 1 [ ignore ] => 0 [ disabled ] => 0 [ error ] => ) )","title":"Creating Components"},{"location":"Extensions/Component/#deleting-components","text":"When a component is no longer needed, it can be deleted. $COMPONENT -> deleteComponent ( $COMPONENT_ID ) This will return True on success or False on failure.","title":"Deleting Components"},{"location":"Extensions/Component/#editing-components","text":"To edit a component, the procedure is: Get the Current Components Edit the array Write the components","title":"Editing Components"},{"location":"Extensions/Component/#edit-the-array","text":"Once you have a component array from getComponents the first thing to do is extract the components for only the single device you are editing. This is required because the setComponentPrefs function only saves a single device at a time. $ARRAY = $COMPONENT -> getComponents ( $DEVICE_ID , $OPTIONS ); $ARRAY = $ARRAY [ $DEVICE_ID ]; Then simply edit this array to suit your needs. If you need to add a new Attribute/Value pair you can: $ARRAY [ COMPONENT_ID ][ 'New Attribute' ] = \"Value\" ; If you need to delete a previously set Attribute/Value pair you can: unset ( $ARRAY [ COMPONENT_ID ][ 'New Attribute' ]); If you need to edit a previously set Attribute/Value pair you can: $ARRAY [ COMPONENT_ID ][ 'Existing Attribute' ] = \"New Value\" ;","title":"Edit the Array"},{"location":"Extensions/Component/#write-the-components","text":"To write component changes back to the database simply: $COMPONENT -> setComponentPrefs ( $DEVICE_ID , $ARRAY ) When writing the component array there are several caveats to be aware of, these are: $ARRAY must be in the format of a single device ID - $ARRAY[$COMPONENT_ID][Attribute] = 'Value'; NOT in the multi device format returned by getComponents - $ARRAY[$DEVICE_ID][$COMPONENT_ID][Attribute] = 'Value'; You cannot edit the Component ID or the Device ID reserved fields can not be removed if a change is found an entry will be written to the eventlog.","title":"Write the components"},{"location":"Extensions/Component/#api","text":"Component details are available via the API. Please see the API-Docs for details.","title":"API"},{"location":"Extensions/Component/#alerting","text":"It is intended that discovery/poller modules will detect the status of a component during the polling cycle. Status is logged using the Nagios convention for status codes, where: 0 = Ok, 1 = Warning, 2 = Critical If you are creating a poller module which can detect a fault condition simply set STATUS to something other than 0 and ERROR to a message that indicates the problem. To actually raise an alert, the user will need to create an alert rule. To assist with this several Alerting Macro's have been created: %macro.component_normal - A component that is not disabled or ignored and in a Normal state. %macro.component_warning - A component that is not disabled or ignored and NOT in a Warning state. %macro.component_critical - A component that is not disabled or ignored and NOT in a Critical state. To raise alerts for components, the following rules could be created: %macros.component_critical = \"1\" - To alert on all Critical components %macros.component_critical = \"1\" && %component.type = \"\" - To alert on all Critical components of a particular type. If there is a particular component you would like excluded from alerting, simply set the ignore field to 1. The data that is written to each alert when it is raised is in the following format: COMPONENT_TYPE - LABEL - ERROR","title":"Alerting"},{"location":"Extensions/Component/#example-code","text":"To see an example of how the component module can used, please see the following modules: Cisco CBQoS includes/discovery/cisco-cbqos.inc.php includes/polling/cisco-cbqos.inc.php html/includes/graphs/device/cbqos_traffic.inc.php Cisco OTV includes/discovery/cisco-otv.inc.php includes/polling/cisco-otv.inc.php html/includes/graphs/device/cisco-otv-mac.inc.php html/pages/routing/cisco-otv.inc.php","title":"Example Code"},{"location":"Extensions/Custom-Map/","text":"Custom Map LibreNMS has the ability to create custom maps to give a quick overview of parts of the network including up/down status of devices and link utilisation. These are also referred to as weather maps. Viewer Once some maps have been created, they will be visible to any users who have read access to all devices on a given map. Custom maps are available through the Overview -> Maps -> Custom Maps menu. Some key points about the viewer are: Nodes will change colour if they are down or disabled Links are only associated with a single network interface Link utilisation can only be shown if the link speed is known Link speed is decoded from SNMP if possible (Upload/Download) and defaults to the physical speed if SNMP data is not available, or cannot be decoded Links will change colour as follows: Black if the link is down, or the max speed is unknown Green at 0% utilisation, with a gradual change to Yellow at 50% utilisation, with a gradual change to Orange at 75% utilisation, with a gradual change to Red at 100% utilisation, with a gradual change to Purple at 150% utilisation and above Viewer URL options You can manually add the following parameters to a URL to alter the display of a custom map. The following URL options are available: bare=yes : Removes the control bar from the top of the page. screenshot=yes : Removes all labels from the nodes and links e.g. If you want bare and screenshot enabled, https:// nmsserver /maps/custom/2 becomes https:// nmsserver /maps/custom/2?bare=yes&screenshot=yes Editor To access the custom map editor, a user must be an admin. The editor is accessed through the Overview -> Maps -> Custom Map Editor menu. Once you are in the editor, you will be given a drop-down list of all the custom maps so you can choose one to edit, or select \"Create New Map\" to create a new map. Map Settings When you create a new map, you will be presented with a page to set some global map settings. These are: Name : The name for the map Width : The width of the map in pixels Height : The height of the map in pixels Node Alignment : When devices are added to the map, this will align the devices to an invisible grid this many pixels wide, which can help to make the maps look better. This can be set to 0 to disable. Background : An image (PNG/JPG) up to 2MB can be uploaded as a background. These settings can be changed at any stage by clicking on the \"Edit Map Settings\" button in the top-left of the editor. Nodes Once you have a map, you can start by adding \"nodes\" to the map. A node represents a device, or an external point in the network (e.g. the internet) To add a node, you click on the \"Add Node\" button in the control bar, then click on the map area where you want to add the node. You will then be aked for the following information: Label : The text to display on this point in the network Device : If this node represents a device, you can select the device from the drop-down. This will overwrite the label, which you can then change if you want to. Style : You can select the style of the node. If a device has been selected you can choose the LibreNMS icon by choosing \"Device Image\". You can also choose \"Icon\" to select an image for the device. Icon : If you choose \"Icon\" in the style box, you can select from a list of images to represent this node There are also options to choose the size and colour of the node and the font. Once you have finished choosing the options for the node, you can press Save to add it to the map. NOTE: This does not save anything to the database immediately. You need to click on the \"Save Map\" button in the top-right to save your changes to the database. You can edit a node at any time by selecting it on the map and clicking on the \"Edit Node\" button in the control bar. You can also modify the default settings for all new nodes by clicking on the \"Edit Node Default\" button at the top of the page. Edges Once you have 2 or more nodes, you can add links between the nodes. These are called edges in the editor. To add a link, click on the \"Add Edge\" button in the control bar, then click on one of the nodes you want to link and drag the cursor to the second node that you want to link. You will then be prompted for the following information: From : The node that the link runs from (it will default to first node you selected) To : The node that the link runs to (it will default to the second node you selected) Port : If the From or To node is linked to a device, you can select an interface from one of the devices and the custom map will show traffic utilisation for the selected interface. Reverse Port Direction : If the selected port displays data in the wrong direction for the link, you can reverse it by toggling this option. Line Style : You can try different line styles, especially if you are running multiple links between the same 2 nodes Show percent usage : Choose whether to have text on the lines showing the link utilisation as a percentage Recenter Line : If you tick this box, the centre point of the line will be moved back to half way between the 2 nodes when you click on the save button. Once you have finished choosing the options for the node, you can press Save to add it to the map. NOTE: This does not save anything to the database immediately. You need to click on the \"Save Map\" button in the top-right to save your changes to the database. Once you press save, you it will create 3 objects on the screen, 2 arrows and a round node in the middle. Having the 3 objects allows you to move the mid point of the line off centre, and also allows us to display bandwidth information for both directions of the link. You can edit an edge at any time by selecting it on the map and clicking on the \"Edit Edge\" button in the control bar. You can also modify the default settings for all new edges by clicking on the \"Edit Edge Default\" button at the top of the page. Re-Render When you drag items around the map, some of the lines will bend. This will cause a \"Re-Render Map\" button to appear at the top-right of the page. This button can be clicked on to cause all lines to be re-drawn the way they will be shown in the viewer. Save Map Once you are happy with a set of changes that you have made, you can click on the \"Save Map\" button in the top-right of the page to commit changes to the database. This will cause anyone viewing the map to see the new version the next time their page refreshes. Adding Images You can add your own images to use on the custom map by copying files into the html/images/custommap/icons/ directory. Any files with a .svg, .png or .jpg extension will be shown in the image selection drop-down in the custom map editor.","title":"Custom Map"},{"location":"Extensions/Custom-Map/#custom-map","text":"LibreNMS has the ability to create custom maps to give a quick overview of parts of the network including up/down status of devices and link utilisation. These are also referred to as weather maps.","title":"Custom Map"},{"location":"Extensions/Custom-Map/#viewer","text":"Once some maps have been created, they will be visible to any users who have read access to all devices on a given map. Custom maps are available through the Overview -> Maps -> Custom Maps menu. Some key points about the viewer are: Nodes will change colour if they are down or disabled Links are only associated with a single network interface Link utilisation can only be shown if the link speed is known Link speed is decoded from SNMP if possible (Upload/Download) and defaults to the physical speed if SNMP data is not available, or cannot be decoded Links will change colour as follows: Black if the link is down, or the max speed is unknown Green at 0% utilisation, with a gradual change to Yellow at 50% utilisation, with a gradual change to Orange at 75% utilisation, with a gradual change to Red at 100% utilisation, with a gradual change to Purple at 150% utilisation and above","title":"Viewer"},{"location":"Extensions/Custom-Map/#viewer-url-options","text":"You can manually add the following parameters to a URL to alter the display of a custom map. The following URL options are available: bare=yes : Removes the control bar from the top of the page. screenshot=yes : Removes all labels from the nodes and links e.g. If you want bare and screenshot enabled, https:// nmsserver /maps/custom/2 becomes https:// nmsserver /maps/custom/2?bare=yes&screenshot=yes","title":"Viewer URL options"},{"location":"Extensions/Custom-Map/#editor","text":"To access the custom map editor, a user must be an admin. The editor is accessed through the Overview -> Maps -> Custom Map Editor menu. Once you are in the editor, you will be given a drop-down list of all the custom maps so you can choose one to edit, or select \"Create New Map\" to create a new map.","title":"Editor"},{"location":"Extensions/Custom-Map/#map-settings","text":"When you create a new map, you will be presented with a page to set some global map settings. These are: Name : The name for the map Width : The width of the map in pixels Height : The height of the map in pixels Node Alignment : When devices are added to the map, this will align the devices to an invisible grid this many pixels wide, which can help to make the maps look better. This can be set to 0 to disable. Background : An image (PNG/JPG) up to 2MB can be uploaded as a background. These settings can be changed at any stage by clicking on the \"Edit Map Settings\" button in the top-left of the editor.","title":"Map Settings"},{"location":"Extensions/Custom-Map/#nodes","text":"Once you have a map, you can start by adding \"nodes\" to the map. A node represents a device, or an external point in the network (e.g. the internet) To add a node, you click on the \"Add Node\" button in the control bar, then click on the map area where you want to add the node. You will then be aked for the following information: Label : The text to display on this point in the network Device : If this node represents a device, you can select the device from the drop-down. This will overwrite the label, which you can then change if you want to. Style : You can select the style of the node. If a device has been selected you can choose the LibreNMS icon by choosing \"Device Image\". You can also choose \"Icon\" to select an image for the device. Icon : If you choose \"Icon\" in the style box, you can select from a list of images to represent this node There are also options to choose the size and colour of the node and the font. Once you have finished choosing the options for the node, you can press Save to add it to the map. NOTE: This does not save anything to the database immediately. You need to click on the \"Save Map\" button in the top-right to save your changes to the database. You can edit a node at any time by selecting it on the map and clicking on the \"Edit Node\" button in the control bar. You can also modify the default settings for all new nodes by clicking on the \"Edit Node Default\" button at the top of the page.","title":"Nodes"},{"location":"Extensions/Custom-Map/#edges","text":"Once you have 2 or more nodes, you can add links between the nodes. These are called edges in the editor. To add a link, click on the \"Add Edge\" button in the control bar, then click on one of the nodes you want to link and drag the cursor to the second node that you want to link. You will then be prompted for the following information: From : The node that the link runs from (it will default to first node you selected) To : The node that the link runs to (it will default to the second node you selected) Port : If the From or To node is linked to a device, you can select an interface from one of the devices and the custom map will show traffic utilisation for the selected interface. Reverse Port Direction : If the selected port displays data in the wrong direction for the link, you can reverse it by toggling this option. Line Style : You can try different line styles, especially if you are running multiple links between the same 2 nodes Show percent usage : Choose whether to have text on the lines showing the link utilisation as a percentage Recenter Line : If you tick this box, the centre point of the line will be moved back to half way between the 2 nodes when you click on the save button. Once you have finished choosing the options for the node, you can press Save to add it to the map. NOTE: This does not save anything to the database immediately. You need to click on the \"Save Map\" button in the top-right to save your changes to the database. Once you press save, you it will create 3 objects on the screen, 2 arrows and a round node in the middle. Having the 3 objects allows you to move the mid point of the line off centre, and also allows us to display bandwidth information for both directions of the link. You can edit an edge at any time by selecting it on the map and clicking on the \"Edit Edge\" button in the control bar. You can also modify the default settings for all new edges by clicking on the \"Edit Edge Default\" button at the top of the page.","title":"Edges"},{"location":"Extensions/Custom-Map/#re-render","text":"When you drag items around the map, some of the lines will bend. This will cause a \"Re-Render Map\" button to appear at the top-right of the page. This button can be clicked on to cause all lines to be re-drawn the way they will be shown in the viewer.","title":"Re-Render"},{"location":"Extensions/Custom-Map/#save-map","text":"Once you are happy with a set of changes that you have made, you can click on the \"Save Map\" button in the top-right of the page to commit changes to the database. This will cause anyone viewing the map to see the new version the next time their page refreshes.","title":"Save Map"},{"location":"Extensions/Custom-Map/#adding-images","text":"You can add your own images to use on the custom map by copying files into the html/images/custommap/icons/ directory. Any files with a .svg, .png or .jpg extension will be shown in the image selection drop-down in the custom map editor.","title":"Adding Images"},{"location":"Extensions/Customizing-the-Web-UI/","text":"Customizing the Web UI Custom menu entry Create the file resources/views/menu/custom.blade.php Example contents: Custom Menu Custom device menu action You can add custom external links in the menu on the device page. This feature allows you to easily link applications to related systems, as shown in the example of Open-audIT. The url value is parsed by the Laravel Blade templating engine. You can access device variables such as $device->hostname , $device->sysName and use full PHP. settings/webui/device lnms config:set html.device.links.+ '{\"url\": \"http://atssrv/open-audit/index/devices/{{ $device->sysName }}\", \"title\": \"Open-AudIT\"}' Field Description url Url blade template resulting in valid url. Required. title Title text displayed in the menu. Required. icon Font Awesome icon class. Default: fa-external-link external Open link in new window. Default: true action Show as action on device list. Default: false Launching Windows programs from the LibreNMS device menu You can launch windows programs from links in LibreNMS, but it does take some registry entries on the client device. Save the following as winbox.reg, edit for your winbox.exe path and double click to add to your registry. Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\\winbox] @=\"URL:Winbox Protocol\" \"URL Protocol\"=\"\" [HKEY_CLASSES_ROOT\\winbox\\shell] [HKEY_CLASSES_ROOT\\winbox\\shell\\open] [HKEY_CLASSES_ROOT\\winbox\\shell\\open\\command] @=\"C:\\Windows\\System32\\WindowsPowerShell 1.0\\powershell.exe -Command \"$val='%l'; $val = $val.TrimEnd('/');if ($val.StartsWith('winbox://' { $val = $val.SubString(9) }; & 'C:\\Program Files\\winbox64.exe' \"$val\"\"\" Now we can use that in the device menu entry to open winbox. settings/webui/device lnms config:set html.device.links.+ '{\"url\": \"winbox://{{ $device->hostname }}\", \"title\": \"Winbox\"}' Setting the primary device menu action You can change the icon that is clickable in the device without having to open the dropdown menu. The primary button is edit device by default. settings/webui/device lnms config:set html.device.primary_link web Value Description edit Edit device web Connect to the device via https/http ssh launch ssh:// protocol to the device, make sure you have a handler registered telnet launch telnet:// protocol to the device capture Link to the device capture page custom1 Custom Link 1 custom2 Custom Link 2 custom3 Custom Link 3 custom4 Custom Link 4 custom5 Custom Link 5 custom6 Custom Link 6 custom7 Custom Link 7 custom8 Custom Link 8 !!! Custom http, ssh, telnet ports Custom ports can be set through the device setting misc tab and will be appended to the Uri. Empty value will not append anything and automatically default to the standard. - custom ssh port set to 2222 will result in ssh://10.0.0.0:2222 - custom telnet port set to 2323 will result in telnet://10.0.0.0:2323","title":"Customizing the Web UI"},{"location":"Extensions/Customizing-the-Web-UI/#customizing-the-web-ui","text":"","title":"Customizing the Web UI"},{"location":"Extensions/Customizing-the-Web-UI/#custom-menu-entry","text":"Create the file resources/views/menu/custom.blade.php Example contents: Custom Menu ","title":"Custom menu entry"},{"location":"Extensions/Customizing-the-Web-UI/#custom-device-menu-action","text":"You can add custom external links in the menu on the device page. This feature allows you to easily link applications to related systems, as shown in the example of Open-audIT. The url value is parsed by the Laravel Blade templating engine. You can access device variables such as $device->hostname , $device->sysName and use full PHP. settings/webui/device lnms config:set html.device.links.+ '{\"url\": \"http://atssrv/open-audit/index/devices/{{ $device->sysName }}\", \"title\": \"Open-AudIT\"}' Field Description url Url blade template resulting in valid url. Required. title Title text displayed in the menu. Required. icon Font Awesome icon class. Default: fa-external-link external Open link in new window. Default: true action Show as action on device list. Default: false","title":"Custom device menu action"},{"location":"Extensions/Customizing-the-Web-UI/#launching-windows-programs-from-the-librenms-device-menu","text":"You can launch windows programs from links in LibreNMS, but it does take some registry entries on the client device. Save the following as winbox.reg, edit for your winbox.exe path and double click to add to your registry. Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\\winbox] @=\"URL:Winbox Protocol\" \"URL Protocol\"=\"\" [HKEY_CLASSES_ROOT\\winbox\\shell] [HKEY_CLASSES_ROOT\\winbox\\shell\\open] [HKEY_CLASSES_ROOT\\winbox\\shell\\open\\command] @=\"C:\\Windows\\System32\\WindowsPowerShell 1.0\\powershell.exe -Command \"$val='%l'; $val = $val.TrimEnd('/');if ($val.StartsWith('winbox://' { $val = $val.SubString(9) }; & 'C:\\Program Files\\winbox64.exe' \"$val\"\"\" Now we can use that in the device menu entry to open winbox. settings/webui/device lnms config:set html.device.links.+ '{\"url\": \"winbox://{{ $device->hostname }}\", \"title\": \"Winbox\"}'","title":"Launching Windows programs from the LibreNMS device menu"},{"location":"Extensions/Customizing-the-Web-UI/#setting-the-primary-device-menu-action","text":"You can change the icon that is clickable in the device without having to open the dropdown menu. The primary button is edit device by default. settings/webui/device lnms config:set html.device.primary_link web Value Description edit Edit device web Connect to the device via https/http ssh launch ssh:// protocol to the device, make sure you have a handler registered telnet launch telnet:// protocol to the device capture Link to the device capture page custom1 Custom Link 1 custom2 Custom Link 2 custom3 Custom Link 3 custom4 Custom Link 4 custom5 Custom Link 5 custom6 Custom Link 6 custom7 Custom Link 7 custom8 Custom Link 8 !!! Custom http, ssh, telnet ports Custom ports can be set through the device setting misc tab and will be appended to the Uri. Empty value will not append anything and automatically default to the standard. - custom ssh port set to 2222 will result in ssh://10.0.0.0:2222 - custom telnet port set to 2323 will result in telnet://10.0.0.0:2323","title":"Setting the primary device menu action"},{"location":"Extensions/Dashboards/","text":"Dashboards Create customised dashboards in LibreNMS per user. You can share dashboards with other users. You can also make a custom dashboard and default it for all users in LibreNMS. Example Dashboard Widgets LibreNMS has a whole list of Widgets to select from. Alerts Widget: Displays all alert notifications. Availability Map: Displays all devices with colored tiles, green up, yellow for warning (device has been restarted in last 24 hours), red for down. You can also list all services and ignored/disabled devices in this widget. Components Status: List all components Ok state, Warning state, Critical state. Device Summary horizontal: List device totals, up, down, ignored, disabled. Same for ports and services. Device Summary vertical: List device totals, up, down, ignored, disabled. Same for ports and services. Eventlog: Displays all events with your devices and LibreNMS. External Image: can be used to show external images on your dashboard. Or images from inside LibreNMS. Globe Map: Will display map of the globe. Graph: Can be used to display graphs from devices. Graylog: Displays all Graylog's syslog entries. Notes: use for html tags, embed links and external web pages. Or just notes in general. Server Stats: Will display gauges for CPU, Memory, Storage usage. Note the device type has to be listed as \"Server\". Syslog: Displays all syslog entries. Top Devices: By Traffic, or Uptime, or Response time, or Poller Duration, or Processor load, or Memory Usage, or Storage Usage. Top Interfaces: Lists top interfaces by traffic utilization. World Map: displays all your devices locations. From syslocation or from override sysLocation. List of Widgets: Dashboard Permissions Private: Sets the dashboard to only the user that created the dashboard can view and edit. Shared Read: Sets the dashboard to allow other users to view the dashboard, but cant make changes to the dashboard. Shared: Allows all users to view the dashboard and make changes. Setting a global default dashboard Step 1: Set the dashboard to either shared read or shared, depending on what you want the users access to change. Step 2: Then go to Settings -> WebUI settings -> Dashboard Settings and set the global default dashboard. Setting embedded webpage Using the Notes Widget. < iframe src = \"your_url\" frameBorder = \"0\" width = \"100%\" height = \"100%\" > < p > Your browser does not support iframes. p > iframe > Note you may need to play with the width and height and also size your widget properly. src=\"url\" needs to be URL to webpage you are linking to. Also some web pages may not support html embedded or iframe. How to create ports graph In the dashboard, you want to create an interface graph select the widget called 'Graph' then select \"Port\" -> \"Bits\" Note: you can map the port by description or the alias or by port id. You will need to know this in order to map the port to the graph. Dimension parameter replacement for Generic-image widget When using the Generic-image widget you can provide the width and height of the widget with your request. This will ensure that the image will fit nicely with the dimensions if the Generic-image widget. You can add @AUTO_HEIGHT@ and @AUTO_WIDTH@ to the Image URL as parameters. Examples: http://librenms.example.com/graph.php?id=333%2C444&type=multiport_bits_separate&legend=no&absolute=1&from=-14200&width=@AUTO_WIDTH@&height=@AUTO_HEIGHT@ http://example.com/myimage.php?size=@AUTO_WIDTH@x@AUTO_HEIGHT@","title":"Dashboards"},{"location":"Extensions/Dashboards/#dashboards","text":"Create customised dashboards in LibreNMS per user. You can share dashboards with other users. You can also make a custom dashboard and default it for all users in LibreNMS. Example Dashboard","title":"Dashboards"},{"location":"Extensions/Dashboards/#widgets","text":"LibreNMS has a whole list of Widgets to select from. Alerts Widget: Displays all alert notifications. Availability Map: Displays all devices with colored tiles, green up, yellow for warning (device has been restarted in last 24 hours), red for down. You can also list all services and ignored/disabled devices in this widget. Components Status: List all components Ok state, Warning state, Critical state. Device Summary horizontal: List device totals, up, down, ignored, disabled. Same for ports and services. Device Summary vertical: List device totals, up, down, ignored, disabled. Same for ports and services. Eventlog: Displays all events with your devices and LibreNMS. External Image: can be used to show external images on your dashboard. Or images from inside LibreNMS. Globe Map: Will display map of the globe. Graph: Can be used to display graphs from devices. Graylog: Displays all Graylog's syslog entries. Notes: use for html tags, embed links and external web pages. Or just notes in general. Server Stats: Will display gauges for CPU, Memory, Storage usage. Note the device type has to be listed as \"Server\". Syslog: Displays all syslog entries. Top Devices: By Traffic, or Uptime, or Response time, or Poller Duration, or Processor load, or Memory Usage, or Storage Usage. Top Interfaces: Lists top interfaces by traffic utilization. World Map: displays all your devices locations. From syslocation or from override sysLocation. List of Widgets:","title":"Widgets"},{"location":"Extensions/Dashboards/#dashboard-permissions","text":"Private: Sets the dashboard to only the user that created the dashboard can view and edit. Shared Read: Sets the dashboard to allow other users to view the dashboard, but cant make changes to the dashboard. Shared: Allows all users to view the dashboard and make changes.","title":"Dashboard Permissions"},{"location":"Extensions/Dashboards/#setting-a-global-default-dashboard","text":"Step 1: Set the dashboard to either shared read or shared, depending on what you want the users access to change. Step 2: Then go to Settings -> WebUI settings -> Dashboard Settings and set the global default dashboard.","title":"Setting a global default dashboard"},{"location":"Extensions/Dashboards/#setting-embedded-webpage","text":"Using the Notes Widget. < iframe src = \"your_url\" frameBorder = \"0\" width = \"100%\" height = \"100%\" > < p > Your browser does not support iframes. p > iframe > Note you may need to play with the width and height and also size your widget properly. src=\"url\" needs to be URL to webpage you are linking to. Also some web pages may not support html embedded or iframe.","title":"Setting embedded webpage"},{"location":"Extensions/Dashboards/#how-to-create-ports-graph","text":"In the dashboard, you want to create an interface graph select the widget called 'Graph' then select \"Port\" -> \"Bits\" Note: you can map the port by description or the alias or by port id. You will need to know this in order to map the port to the graph.","title":"How to create ports graph"},{"location":"Extensions/Dashboards/#dimension-parameter-replacement-for-generic-image-widget","text":"When using the Generic-image widget you can provide the width and height of the widget with your request. This will ensure that the image will fit nicely with the dimensions if the Generic-image widget. You can add @AUTO_HEIGHT@ and @AUTO_WIDTH@ to the Image URL as parameters. Examples: http://librenms.example.com/graph.php?id=333%2C444&type=multiport_bits_separate&legend=no&absolute=1&from=-14200&width=@AUTO_WIDTH@&height=@AUTO_HEIGHT@ http://example.com/myimage.php?size=@AUTO_WIDTH@x@AUTO_HEIGHT@","title":"Dimension parameter replacement for Generic-image widget"},{"location":"Extensions/Dell-OpenManage/","text":"Dell OpenManage Support For Dell OpenManage support you will need to install Dell OpenManage (yeah - really :)) (minimum 5.1) onto the device you want to monitor. Ensure that net-snmp is using srvadmin, you should see something similar to: master agentx view all included .1 access notConfigGroup \"\" any noauth exact all none none smuxpeer .1.3.6.1.4.1.674.10892.1 Restart net-snmp: service snmpd restart Ensure that srvadmin is started, this is usually done by executing: /opt/dell/srvadmin/sbin/srvadmin-services.sh start Once this has been done, add the device to LibreNMS as normal and you will start to receive Temperatures and Fan speed data. Windows Download OpenManage from Dell's support page Link and install OpenManage on your windows server. Make sure you have SNMP setup and running on your windows server.","title":"Dell OpenManage"},{"location":"Extensions/Dell-OpenManage/#dell-openmanage-support","text":"For Dell OpenManage support you will need to install Dell OpenManage (yeah - really :)) (minimum 5.1) onto the device you want to monitor. Ensure that net-snmp is using srvadmin, you should see something similar to: master agentx view all included .1 access notConfigGroup \"\" any noauth exact all none none smuxpeer .1.3.6.1.4.1.674.10892.1 Restart net-snmp: service snmpd restart Ensure that srvadmin is started, this is usually done by executing: /opt/dell/srvadmin/sbin/srvadmin-services.sh start Once this has been done, add the device to LibreNMS as normal and you will start to receive Temperatures and Fan speed data.","title":"Dell OpenManage Support"},{"location":"Extensions/Dell-OpenManage/#windows","text":"Download OpenManage from Dell's support page Link and install OpenManage on your windows server. Make sure you have SNMP setup and running on your windows server.","title":"Windows"},{"location":"Extensions/Dependency-Map/","text":"Dependency Map LibreNMS has the ability to show you a dynamic network map based on device dependencies that have been configure. These maps are accessed through the following menu options: Overview -> Maps -> Device Dependency Overview -> Maps -> Device Groups Dependencies Settings The map display can be configured by altering the VisJS-Config.md","title":"Dependency Map"},{"location":"Extensions/Dependency-Map/#dependency-map","text":"LibreNMS has the ability to show you a dynamic network map based on device dependencies that have been configure. These maps are accessed through the following menu options: Overview -> Maps -> Device Dependency Overview -> Maps -> Device Groups Dependencies","title":"Dependency Map"},{"location":"Extensions/Dependency-Map/#settings","text":"The map display can be configured by altering the VisJS-Config.md","title":"Settings"},{"location":"Extensions/Device-Groups/","text":"Grouping Devices LibreNMS supports grouping your devices together in much the same way as you can configure alerts. This document will hopefully help you get started. Dynamic Groups Rule Editor The rule is based on the MySQL structure your data is in. Such as tablename.columnname . If you already know the entity you want, you can browse around inside MySQL using show tables and desc . As a working example and a common question, let's assume you want to group devices by hostname. If your hostname format is dcX.[devicetype].example.com. You would use the field devices.hostname . If you want to group them by device type, you would add a rule for routers of devices.hostname endswith rtr.example.com . If you want to group them by DC, you could use the rule devices.hostname regex dc1\\..*\\.example\\.com (Don't forget to escape periods in the regex) Static Groups You can create static groups (and convert dynamic groups to static) to put specific devices in a group. Just select static as the type and select the devices you want in the group. You can now select this group from the Devices -> All Devices link in the navigation at the top. You can also use the group to map alert rules to by creating an alert mapping Overview -> Alerts -> Rule Mapping .","title":"Grouping Devices"},{"location":"Extensions/Device-Groups/#grouping-devices","text":"LibreNMS supports grouping your devices together in much the same way as you can configure alerts. This document will hopefully help you get started.","title":"Grouping Devices"},{"location":"Extensions/Device-Groups/#dynamic-groups","text":"","title":"Dynamic Groups"},{"location":"Extensions/Device-Groups/#rule-editor","text":"The rule is based on the MySQL structure your data is in. Such as tablename.columnname . If you already know the entity you want, you can browse around inside MySQL using show tables and desc . As a working example and a common question, let's assume you want to group devices by hostname. If your hostname format is dcX.[devicetype].example.com. You would use the field devices.hostname . If you want to group them by device type, you would add a rule for routers of devices.hostname endswith rtr.example.com . If you want to group them by DC, you could use the rule devices.hostname regex dc1\\..*\\.example\\.com (Don't forget to escape periods in the regex)","title":"Rule Editor"},{"location":"Extensions/Device-Groups/#static-groups","text":"You can create static groups (and convert dynamic groups to static) to put specific devices in a group. Just select static as the type and select the devices you want in the group. You can now select this group from the Devices -> All Devices link in the navigation at the top. You can also use the group to map alert rules to by creating an alert mapping Overview -> Alerts -> Rule Mapping .","title":"Static Groups"},{"location":"Extensions/Dispatcher-Service/","text":"Dispatcher Service Status: Release Candidate The LibreNMS dispatcher service ( librenms-service.py ) is a new method of running the poller service at set times. It does not replace the php scripts, just the cron entries running them. External Requirements A recent version of Python The LibreNMS service requires Python 3 and some features require behaviour only found in Python3.4+. Python modules PyMySQL is recommended as it requires no C compiler to install. MySQLclient can also be used, but does require compilation. python-dotenv .env loader redis-py 4.0+ and Redis 5.0+ server (if using distributed polling) psutil These can be obtained from your OS package manager, or from PyPI with the below commands. pip3 install -r requirements.txt Redis (distributed polling) If you want to use distributed polling, you'll need a Redis instance to coordinate the nodes. It's recommended that you do not share the Redis database with any other system - by default, Redis supports up to 16 databases (numbered 0-15). You can also use Redis on a single host if you want It's strongly recommended that you deploy a resilient cluster of redis systems, and use redis-sentinel. You should not rely on the password for the security of your system. See https://redis.io/topics/security Memcached (distributed polling) LibreNMS can still use memcached as a locking mechanism when using distributed polling. So you can configure memcached for this purpose unless you have updates disabled. See Locking Mechanisms at https://docs.librenms.org/Extensions/Distributed-Poller/ MySQL You should already have this, but the pollers do need access to the SQL database. The LibreNMS service runs faster and more aggressively than the standard poller, so keep an eye on the number of open connections and other important health metrics. Configuration Connection settings are required in .env . The .env file is generated after composer install and APP_KEY and NODE_ID are set. Remember that the APP_KEY value must be the same on all your pollers. #APP_KEY= #Required, generated by composer install #NODE_ID= #Required, generated by composer install DB_HOST=localhost DB_DATABASE=librenms DB_USERNAME=librenms DB_PASSWORD= Distributed Polling Configuration Once you have your Redis database set up, configure it in the .env file on each node. Configure the redis cache driver for distributed locking. There are a number of options - most of them are optional if your redis instance is standalone and unauthenticated (neither recommended). ## ## Standalone ## REDIS_HOST=127.0.0.1 REDIS_PORT=6379 REDIS_DB=0 REDIS_TIMEOUT=60 # If requirepass is set in redis set everything above as well as: (recommended) REDIS_PASSWORD=PasswordGoesHere # If ACL's are in use, set everything above as well as: (highly recommended) REDIS_USERNAME=UsernameGoesHere ## ## Sentinel ## REDIS_SENTINEL=redis-001.example.org:26379,redis-002.example.org:26379,redis-003.example.org:26379 REDIS_SENTINEL_SERVICE=mymaster # If requirepass is set in sentinel, set everything above as well as: (recommended) REDIS_SENTINEL_PASSWORD=SentinelPasswordGoesHere # If ACL's are in use, set everything above as well as: (highly recommended) REDIS_SENTINEL_USERNAME=SentinelUsernameGoesHere For more information on ACL's, see https://redis.io/docs/management/security/acl/ Note that if you use Sentinel, you may still need REDIS_PASSWORD , REDIS_USERNAME , REDIS_DB and REDIS_TIMEOUT - Sentinel just provides the address of the instance currently accepting writes and manages failover. It's possible (and recommended) to have authentication both on Sentinel and the managed Redis instances. Basic Configuration Additional configuration settings can be set in your config. The defaults are shown here - it's recommended that you at least tune the number of workers. poller/distributed lnms config:set service_poller_workers 24 lnms config:set service_services_workers 8 lnms config:set service_discovery_workers 16 Optional Settings poller/distributed lnms config:set service_poller_frequency 300 lnms config:set service_services_frequency 300 lnms config:set service_discovery_frequency 21600 lnms config:set service_billing_frequency 300 lnms config:set service_billing_calculate_frequency 60 lnms config:set service_poller_down_retry 60 lnms config:set service_loglevel INFO lnms config:set service_update_frequency 86400 There are also some SQL options, but these should be inherited from your LibreNMS web UI configuration. Logs are sent to the system logging service (usually journald or rsyslog ) - see https://docs.python.org/3/library/logging.html#logging-levels for the options available. $config [ 'distributed_poller' ] = true ; # Set to true to enable distributed polling $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); # Uniquely identifies the poller instance $config [ 'distributed_poller_group' ] = 0 ; # Which group to poll Tuning the number of workers See https://your_librenms_install/poller You want to keep Consumed Worker Seconds comfortably below Maximum Worker Seconds. The closer the values are to each other, the flatter the CPU graph of the poller machine. Meaning that you are utilizing your CPU resources well. As long as Consumed WS stays below Maximum WS and Devices Pending is 0, you should be ok. If Consumed WS is below Maximum WS and Devices Pending is > 0, your hardware is not up to the task. Maximum WS equals the number of workers multiplied with the number of seconds in the polling period. (default 300) Fast Ping The fast ping scheduler is disabled by default. You can enable it by setting the following: $config [ 'service_ping_enabled' ] = true ; Watchdog The watchdog scheduler is disabled by default. You can enable it by setting the following: $config [ 'service_watchdog_enabled' ] = true ; The watchdog scheduler will check that the poller log file has been written to within the last poll period. If there is no change to the log file since, the watchdog will restart the polling service. The poller log file is set by $config['log_file'] and defaults to ./logs/librenms.log Cron Scripts Once the LibreNMS service is installed, the cron scripts used by LibreNMS to start alerting, polling, discovery and maintenance tasks are no longer required and must be disabled either by removing or commenting them out. The service handles these tasks when enabled. The only cron task enabled after switching to the dispatcher service should be the following: * * * * * librenms cd /opt/librenms/ && php artisan schedule:run >> /dev/null 2>&1 Service Installation A systemd unit file is provided - You must adapt ExecStart and WorkingDirectory if you did not install librenms in /opt/librenms The sysv and upstart init scripts could also be used with a little modification. systemd service A systemd unit file can be found in misc/librenms.service . To install run: cp /opt/librenms/misc/librenms.service /etc/systemd/system/librenms.service && systemctl enable --now librenms.service systemd service with watchdog This service file is an alternative to the above service file. It uses the systemd WatchdogSec= option to restart the service if it does not receive a keep-alive from the running process. A systemd unit file can be found in misc/librenms-watchdog.service . To install run: cp /opt/librenms/misc/librenms-watchdog.service /etc/systemd/system/librenms.service && systemctl enable --now librenms.service This requires: python3-systemd (or python-systemd on older systems) or https://pypi.org/project/systemd-python/ If you run this systemd service without python3-systemd it will restart every 30 seconds. OS-Specific Instructions RHEL/CentOS To get the LibreNMS service running under python3.4+ on RHEL-derivatives with minimal fuss, you can use the software collections build: First, enable SCL's on your system: CentOS 7 # yum install centos-release-scl RHEL 7 # subscription-manager repos --enable rhel-server-rhscl-7-rpms Then install and configure the runtime and service: # yum install gcc rh-python36 rh-python36-python-devel epel-release # yum --enablerepo=remi install redis # vi /opt/librenms/config.php # vi /etc/redis.conf # systemctl enable --now redis.service # scl enable rh-python36 bash # change directory to librenms (default /opt/librenms) # pip3 install -r requirements.txt # cp /opt/librenms/misc/librenms.service.scl /etc/systemd/system/librenms.service # systemctl enable --now librenms.service If you want to use another version of python 3, change rh-python36 in the unit file and the commands above to match the name of the replacement scl. Debian/Ubuntu Debian 11 (Bullseye) Warning: Bullseye provide PHP 7.4 that is too old to run LibreNMS. Debian 12 (Bookworm) Warning: Bookworm is not available as stable yet (as 2022 november). Install dependancies apt install python3 python3-mysqldb python3-dotenv Add the python3-systemd package for service with watchdog.","title":"Dispatcher Service (RC)"},{"location":"Extensions/Dispatcher-Service/#dispatcher-service","text":"Status: Release Candidate The LibreNMS dispatcher service ( librenms-service.py ) is a new method of running the poller service at set times. It does not replace the php scripts, just the cron entries running them.","title":"Dispatcher Service"},{"location":"Extensions/Dispatcher-Service/#external-requirements","text":"","title":"External Requirements"},{"location":"Extensions/Dispatcher-Service/#a-recent-version-of-python","text":"The LibreNMS service requires Python 3 and some features require behaviour only found in Python3.4+.","title":"A recent version of Python"},{"location":"Extensions/Dispatcher-Service/#python-modules","text":"PyMySQL is recommended as it requires no C compiler to install. MySQLclient can also be used, but does require compilation. python-dotenv .env loader redis-py 4.0+ and Redis 5.0+ server (if using distributed polling) psutil These can be obtained from your OS package manager, or from PyPI with the below commands. pip3 install -r requirements.txt","title":"Python modules"},{"location":"Extensions/Dispatcher-Service/#redis-distributed-polling","text":"If you want to use distributed polling, you'll need a Redis instance to coordinate the nodes. It's recommended that you do not share the Redis database with any other system - by default, Redis supports up to 16 databases (numbered 0-15). You can also use Redis on a single host if you want It's strongly recommended that you deploy a resilient cluster of redis systems, and use redis-sentinel. You should not rely on the password for the security of your system. See https://redis.io/topics/security","title":"Redis (distributed polling)"},{"location":"Extensions/Dispatcher-Service/#memcached-distributed-polling","text":"LibreNMS can still use memcached as a locking mechanism when using distributed polling. So you can configure memcached for this purpose unless you have updates disabled. See Locking Mechanisms at https://docs.librenms.org/Extensions/Distributed-Poller/","title":"Memcached (distributed polling)"},{"location":"Extensions/Dispatcher-Service/#mysql","text":"You should already have this, but the pollers do need access to the SQL database. The LibreNMS service runs faster and more aggressively than the standard poller, so keep an eye on the number of open connections and other important health metrics.","title":"MySQL"},{"location":"Extensions/Dispatcher-Service/#configuration","text":"Connection settings are required in .env . The .env file is generated after composer install and APP_KEY and NODE_ID are set. Remember that the APP_KEY value must be the same on all your pollers. #APP_KEY= #Required, generated by composer install #NODE_ID= #Required, generated by composer install DB_HOST=localhost DB_DATABASE=librenms DB_USERNAME=librenms DB_PASSWORD=","title":"Configuration"},{"location":"Extensions/Dispatcher-Service/#distributed-polling-configuration","text":"Once you have your Redis database set up, configure it in the .env file on each node. Configure the redis cache driver for distributed locking. There are a number of options - most of them are optional if your redis instance is standalone and unauthenticated (neither recommended). ## ## Standalone ## REDIS_HOST=127.0.0.1 REDIS_PORT=6379 REDIS_DB=0 REDIS_TIMEOUT=60 # If requirepass is set in redis set everything above as well as: (recommended) REDIS_PASSWORD=PasswordGoesHere # If ACL's are in use, set everything above as well as: (highly recommended) REDIS_USERNAME=UsernameGoesHere ## ## Sentinel ## REDIS_SENTINEL=redis-001.example.org:26379,redis-002.example.org:26379,redis-003.example.org:26379 REDIS_SENTINEL_SERVICE=mymaster # If requirepass is set in sentinel, set everything above as well as: (recommended) REDIS_SENTINEL_PASSWORD=SentinelPasswordGoesHere # If ACL's are in use, set everything above as well as: (highly recommended) REDIS_SENTINEL_USERNAME=SentinelUsernameGoesHere For more information on ACL's, see https://redis.io/docs/management/security/acl/ Note that if you use Sentinel, you may still need REDIS_PASSWORD , REDIS_USERNAME , REDIS_DB and REDIS_TIMEOUT - Sentinel just provides the address of the instance currently accepting writes and manages failover. It's possible (and recommended) to have authentication both on Sentinel and the managed Redis instances.","title":"Distributed Polling Configuration"},{"location":"Extensions/Dispatcher-Service/#basic-configuration","text":"Additional configuration settings can be set in your config. The defaults are shown here - it's recommended that you at least tune the number of workers. poller/distributed lnms config:set service_poller_workers 24 lnms config:set service_services_workers 8 lnms config:set service_discovery_workers 16 Optional Settings poller/distributed lnms config:set service_poller_frequency 300 lnms config:set service_services_frequency 300 lnms config:set service_discovery_frequency 21600 lnms config:set service_billing_frequency 300 lnms config:set service_billing_calculate_frequency 60 lnms config:set service_poller_down_retry 60 lnms config:set service_loglevel INFO lnms config:set service_update_frequency 86400 There are also some SQL options, but these should be inherited from your LibreNMS web UI configuration. Logs are sent to the system logging service (usually journald or rsyslog ) - see https://docs.python.org/3/library/logging.html#logging-levels for the options available. $config [ 'distributed_poller' ] = true ; # Set to true to enable distributed polling $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); # Uniquely identifies the poller instance $config [ 'distributed_poller_group' ] = 0 ; # Which group to poll","title":"Basic Configuration"},{"location":"Extensions/Dispatcher-Service/#tuning-the-number-of-workers","text":"See https://your_librenms_install/poller You want to keep Consumed Worker Seconds comfortably below Maximum Worker Seconds. The closer the values are to each other, the flatter the CPU graph of the poller machine. Meaning that you are utilizing your CPU resources well. As long as Consumed WS stays below Maximum WS and Devices Pending is 0, you should be ok. If Consumed WS is below Maximum WS and Devices Pending is > 0, your hardware is not up to the task. Maximum WS equals the number of workers multiplied with the number of seconds in the polling period. (default 300)","title":"Tuning the number of workers"},{"location":"Extensions/Dispatcher-Service/#fast-ping","text":"The fast ping scheduler is disabled by default. You can enable it by setting the following: $config [ 'service_ping_enabled' ] = true ;","title":"Fast Ping"},{"location":"Extensions/Dispatcher-Service/#watchdog","text":"The watchdog scheduler is disabled by default. You can enable it by setting the following: $config [ 'service_watchdog_enabled' ] = true ; The watchdog scheduler will check that the poller log file has been written to within the last poll period. If there is no change to the log file since, the watchdog will restart the polling service. The poller log file is set by $config['log_file'] and defaults to ./logs/librenms.log","title":"Watchdog"},{"location":"Extensions/Dispatcher-Service/#cron-scripts","text":"Once the LibreNMS service is installed, the cron scripts used by LibreNMS to start alerting, polling, discovery and maintenance tasks are no longer required and must be disabled either by removing or commenting them out. The service handles these tasks when enabled. The only cron task enabled after switching to the dispatcher service should be the following: * * * * * librenms cd /opt/librenms/ && php artisan schedule:run >> /dev/null 2>&1","title":"Cron Scripts"},{"location":"Extensions/Dispatcher-Service/#service-installation","text":"A systemd unit file is provided - You must adapt ExecStart and WorkingDirectory if you did not install librenms in /opt/librenms The sysv and upstart init scripts could also be used with a little modification.","title":"Service Installation"},{"location":"Extensions/Dispatcher-Service/#systemd-service","text":"A systemd unit file can be found in misc/librenms.service . To install run: cp /opt/librenms/misc/librenms.service /etc/systemd/system/librenms.service && systemctl enable --now librenms.service","title":"systemd service"},{"location":"Extensions/Dispatcher-Service/#systemd-service-with-watchdog","text":"This service file is an alternative to the above service file. It uses the systemd WatchdogSec= option to restart the service if it does not receive a keep-alive from the running process. A systemd unit file can be found in misc/librenms-watchdog.service . To install run: cp /opt/librenms/misc/librenms-watchdog.service /etc/systemd/system/librenms.service && systemctl enable --now librenms.service This requires: python3-systemd (or python-systemd on older systems) or https://pypi.org/project/systemd-python/ If you run this systemd service without python3-systemd it will restart every 30 seconds.","title":"systemd service with watchdog"},{"location":"Extensions/Dispatcher-Service/#os-specific-instructions","text":"","title":"OS-Specific Instructions"},{"location":"Extensions/Dispatcher-Service/#rhelcentos","text":"To get the LibreNMS service running under python3.4+ on RHEL-derivatives with minimal fuss, you can use the software collections build: First, enable SCL's on your system:","title":"RHEL/CentOS"},{"location":"Extensions/Dispatcher-Service/#centos-7","text":"# yum install centos-release-scl","title":"CentOS 7"},{"location":"Extensions/Dispatcher-Service/#rhel-7","text":"# subscription-manager repos --enable rhel-server-rhscl-7-rpms Then install and configure the runtime and service: # yum install gcc rh-python36 rh-python36-python-devel epel-release # yum --enablerepo=remi install redis # vi /opt/librenms/config.php # vi /etc/redis.conf # systemctl enable --now redis.service # scl enable rh-python36 bash # change directory to librenms (default /opt/librenms) # pip3 install -r requirements.txt # cp /opt/librenms/misc/librenms.service.scl /etc/systemd/system/librenms.service # systemctl enable --now librenms.service If you want to use another version of python 3, change rh-python36 in the unit file and the commands above to match the name of the replacement scl.","title":"RHEL 7"},{"location":"Extensions/Dispatcher-Service/#debianubuntu","text":"","title":"Debian/Ubuntu"},{"location":"Extensions/Dispatcher-Service/#debian-11-bullseye","text":"Warning: Bullseye provide PHP 7.4 that is too old to run LibreNMS.","title":"Debian 11 (Bullseye)"},{"location":"Extensions/Dispatcher-Service/#debian-12-bookworm","text":"Warning: Bookworm is not available as stable yet (as 2022 november). Install dependancies apt install python3 python3-mysqldb python3-dotenv Add the python3-systemd package for service with watchdog.","title":"Debian 12 (Bookworm)"},{"location":"Extensions/Distributed-Poller/","text":"Distributed Poller A normal install contains all parts of LibreNMS: Poller/Discovery/etc workers RRD (Time series data store) * Database * Webserver (Web UI/API) * * may only be installed on one server (however, some can be clustered) Distributed Polling allows the workers to be spread across additional servers for horizontal scaling. Distributed polling is not intended for remote polling. Devices can be grouped together into a poller_group to pin these devices to a single or a group of designated pollers. All pollers need to write to the same set of RRD files, preferably via RRDcached. It is also a requirement that at least one locking service is in place to which all pollers can connect. There are currently three locking mechanisms available memcached redis (preferred) sql locks (default) All of the above locking mechanisms are natively supported in LibreNMS. If none are specified, it will default to using SQL. Requirements for distributed polling These requirements are above the normal requirements for a full LibreNMS install. rrdtool version 1.4 or above At least one locking mechanism configured a rrdcached install By default, all hosts are shared and have the poller_group = 0 . To pin a device to a poller, set it to a value greater than 0 and set the same value in the poller's config with distributed_poller_group . One can also specify a comma separated string of poller groups in distributed_poller_group . The poller will then poll devices from any of the groups listed. If new devices get added from the poller they will be assigned to the first poller group in the list unless the group is specified when adding the device. The following is a standard config, combined with a locking mechanism below: poller/distributed lnms config:set distributed_poller true lnms config:set distributed_poller_group 0 If you want to customise the hostname for the poller then you will need to set this in config.php : $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); Locking mechanisms Pick one of the following setups, do not use all of them at the same time. Using REDIS In your .env file you will need to specify a redis server, port and the driver. REDIS_HOST=HOSTNAME or IP REDIS_PORT=6379 CACHE_DRIVER=redis Using Memcached Preferably you should set the memcached server settings via the web UI. Under Settings > Global Settings > Distributed poller, you fill out the memcached host and port, and then in your .env file you will need to add: CACHE_DRIVER=memcached If you want to use memcached, you will also need to install an additional Python 3 python-memcached package. Example Setup Below is an example setup based on a real deployment which at the time of writing covers over 2,500 devices and 50,000 ports. The setup is running within an OpenStack environment with some commodity hardware for remote pollers. Here's a diagram of how you can scale LibreNMS out: Architecture How you set the distribution up is entirely up to you. You can choose to host the majority of the required services on a single virtual machine or server and then a poller to actually query the devices being monitored, all the way through to having a dedicated server for each of the individual roles. Below are notes on what you need to consider both from the software layer, but also connectivity. Web / API Layer This is typically Apache but we have setup guides for both Nginx and Lighttpd which should work perfectly fine. There is nothing unique about the role this service is providing except that if you are adding devices from this layer then the web service will need to be able to connect to the end device via SNMP and perform an ICMP test. It is advisable to run RRDCached within this setup so that you don't need to share the rrd folder via a remote file share such as NFS. The web service can then generate rrd graphs via RRDCached. If RRDCached isn't an option then you can mount the rrd directory to read the RRD files directly. Database Server MySQL / MariaDB - At the moment these are the only database servers that are supported. The pollers, web and API layers should all be able to access the database server directly. RRD Storage Central storage should be provided so all RRD files can be read from and written to in one location. As suggested above, it's recommended that RRD Cached is configured and used. For this example, we are running RRDCached to allow all pollers and web/api servers to read/write to the rrd files with the rrd directory also exported by NFS for simple access and maintenance. Pollers Pollers can be installed and run from anywhere, the only requirements are: They can access the Memcache instance They can create RRD files via some method such as a shared filesystem or RRDTool >=1.5.5 They can access the MySQL server You can either assign pollers into groups and set a poller group against certain devices, this will mean that those devices will only be processed by certain pollers (default poller group is 0) or you can assign all pollers to the default poller group for them to process any and all devices. This will provide the ability to have a single poller behind a NAT firewall monitor internal devices and report back to your central system. You will then be able to monitor those devices from the Web UI as normal. Another benefit to this is that you can provide N+x pollers, i.e if you know that you require three pollers to process all devices within 300 seconds then adding a 4th poller will mean that should any one single poller fail then the remaining three will complete polling in time. You could also use this to take a poller out of service for maintenance, i.e OS updates and software updates. It is extremely advisable to either run a central recursive dns server such as pdns-recursor and have all of your pollers use this or install a recursive dns server on each poller - the volume of DNS requests on large installs can be significant and will slow polling down enough to cause issues with a large number of devices. A last note to make sure of, is that all pollers writing to the same DB need to have the same APP_KEY value set in the .env file. Discovery Depending on your setup will depend on how you configure your discovery processes. Cron based polling It's not necessary to run discovery services on all pollers. In fact, you should only run one discovery process per poller group. Designate a single poller to run discovery (or a separate server if required). If you run billing, you can do this in one of two ways: Run poll-billing.php and calculate-billing.php on a single poller which will create billing information for all bills. Please note this poller must have snmp access to all of your devices which have ports within a bill. The other option is to enable $config['distributed_billing'] = true; in config.php. Then run poll-billing.php on a single poller per group. You can run calculate-billing.php on any poller but only one poller overall. Dispatcher service When using the dispatcher service, discovery can run on all nodes. Configuration Settings in config.php should be copied to all servers as they only apply locally. One way around this is to set settings in the database via the web ui or ./lnms config:set Config sample The following config is taken from a live setup which consists of a Web server, DB server, RRDCached server and 3 pollers. Web Server: Running Apache and an install of LibreNMS in /opt/librenms poller/distributed lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" Database Server: Running Memcache and MariaDB Memcache Ubuntu (/etc/memcached.conf) -d -m 64 -p 11211 -u memcache -l ip.ip.ip.ip RRDCached Server: Running RRDCached RRDCached Ubuntu (/etc/default/rrdcached) OPTS=\"-l 0:42217\" OPTS=\"$OPTS -j /var/lib/rrdcached/journal/ -F\" OPTS=\"$OPTS -b /opt/librenms/rrd -B\" OPTS=\"$OPTS -w 1800 -z 900\" Ubuntu (/etc/default/rrdcached) - RRDCached 1.5.5 and above. BASE_OPTIONS=\"-l 0:42217\" BASE_OPTIONS=\"$BASE_OPTIONS -R -j /var/lib/rrdcached/journal/ -F\" BASE_OPTIONS=\"$BASE_OPTIONS -b /opt/librenms/rrd -B\" BASE_OPTIONS=\"$BASE_OPTIONS -w 1800 -z 900\" Poller 1: Running an install of LibreNMS in /opt/librenms config.php $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); $config [ 'distributed_poller_group' ] = '0' ; $config [ 'distributed_billing' ] = true ; poller/distributed lnms config:set distributed_poller_memcached_host \"example.com\" lnms config:set distributed_poller_memcached_port 11211 lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" /etc/cron.d/librenms Runs discovery and polling for group 0, daily.sh to deal with notifications and DB cleanup and alerts. 33 */6 * * * librenms /opt/librenms/cronic /opt/librenms/discovery-wrapper.py 1 */5 * * * * librenms /opt/librenms/discovery.php -h new >> /dev/null 2>&1 */5 * * * * librenms /opt/librenms/cronic /opt/librenms/poller-wrapper.py 16 15 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1 * * * * * librenms /opt/librenms/alerts.php >> /dev/null 2>&1 Poller 2: Running an install of LibreNMS in /opt/librenms config.php $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); $config [ 'distributed_poller_group' ] = '0' ; $config [ 'distributed_billing' ] = true ; poller/distributed lnms config:set distributed_poller_memcached_host \"example.com\" lnms config:set distributed_poller_memcached_port 11211 lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" /etc/cron.d/librenms Runs billing as well as polling for group 0. */5 * * * * librenms /opt/librenms/poller-wrapper.py 16 >> /opt/librenms/logs/wrapper.log */5 * * * * librenms /opt/librenms/poll-billing.php >> /dev/null 2>&1 01 * * * * librenms /opt/librenms/billing-calculate.php >> /dev/null 2>&1 15 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1 Poller 3: Running an install of LibreNMS in /opt/librenms config.php $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); $config [ 'distributed_poller_group' ] = '2,3' ; $config [ 'distributed_billing' ] = true ; poller/distributed lnms config:set distributed_poller_memcached_host \"example.com\" lnms config:set distributed_poller_memcached_port 11211 lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" /etc/cron.d/librenms Runs discovery and polling for groups 2 and 3. 33 */6 * * * librenms /opt/librenms/cronic /opt/librenms/discovery-wrapper.py 1 */5 * * * * librenms /opt/librenms/discovery.php -h new >> /dev/null 2>&1 */5 * * * * librenms /opt/librenms/poll-billing.php >> /dev/null 2>&1 */5 * * * * librenms /opt/librenms/cronic /opt/librenms/poller-wrapper.py 16 15 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1","title":"Scaling LibreNMS"},{"location":"Extensions/Distributed-Poller/#distributed-poller","text":"A normal install contains all parts of LibreNMS: Poller/Discovery/etc workers RRD (Time series data store) * Database * Webserver (Web UI/API) * * may only be installed on one server (however, some can be clustered) Distributed Polling allows the workers to be spread across additional servers for horizontal scaling. Distributed polling is not intended for remote polling. Devices can be grouped together into a poller_group to pin these devices to a single or a group of designated pollers. All pollers need to write to the same set of RRD files, preferably via RRDcached. It is also a requirement that at least one locking service is in place to which all pollers can connect. There are currently three locking mechanisms available memcached redis (preferred) sql locks (default) All of the above locking mechanisms are natively supported in LibreNMS. If none are specified, it will default to using SQL.","title":"Distributed Poller"},{"location":"Extensions/Distributed-Poller/#requirements-for-distributed-polling","text":"These requirements are above the normal requirements for a full LibreNMS install. rrdtool version 1.4 or above At least one locking mechanism configured a rrdcached install By default, all hosts are shared and have the poller_group = 0 . To pin a device to a poller, set it to a value greater than 0 and set the same value in the poller's config with distributed_poller_group . One can also specify a comma separated string of poller groups in distributed_poller_group . The poller will then poll devices from any of the groups listed. If new devices get added from the poller they will be assigned to the first poller group in the list unless the group is specified when adding the device. The following is a standard config, combined with a locking mechanism below: poller/distributed lnms config:set distributed_poller true lnms config:set distributed_poller_group 0 If you want to customise the hostname for the poller then you will need to set this in config.php : $config [ 'distributed_poller_name' ] = php_uname ( 'n' );","title":"Requirements for distributed polling"},{"location":"Extensions/Distributed-Poller/#locking-mechanisms","text":"Pick one of the following setups, do not use all of them at the same time.","title":"Locking mechanisms"},{"location":"Extensions/Distributed-Poller/#using-redis","text":"In your .env file you will need to specify a redis server, port and the driver. REDIS_HOST=HOSTNAME or IP REDIS_PORT=6379 CACHE_DRIVER=redis","title":"Using REDIS"},{"location":"Extensions/Distributed-Poller/#using-memcached","text":"Preferably you should set the memcached server settings via the web UI. Under Settings > Global Settings > Distributed poller, you fill out the memcached host and port, and then in your .env file you will need to add: CACHE_DRIVER=memcached If you want to use memcached, you will also need to install an additional Python 3 python-memcached package.","title":"Using Memcached"},{"location":"Extensions/Distributed-Poller/#example-setup","text":"Below is an example setup based on a real deployment which at the time of writing covers over 2,500 devices and 50,000 ports. The setup is running within an OpenStack environment with some commodity hardware for remote pollers. Here's a diagram of how you can scale LibreNMS out:","title":"Example Setup"},{"location":"Extensions/Distributed-Poller/#architecture","text":"How you set the distribution up is entirely up to you. You can choose to host the majority of the required services on a single virtual machine or server and then a poller to actually query the devices being monitored, all the way through to having a dedicated server for each of the individual roles. Below are notes on what you need to consider both from the software layer, but also connectivity.","title":"Architecture"},{"location":"Extensions/Distributed-Poller/#web-api-layer","text":"This is typically Apache but we have setup guides for both Nginx and Lighttpd which should work perfectly fine. There is nothing unique about the role this service is providing except that if you are adding devices from this layer then the web service will need to be able to connect to the end device via SNMP and perform an ICMP test. It is advisable to run RRDCached within this setup so that you don't need to share the rrd folder via a remote file share such as NFS. The web service can then generate rrd graphs via RRDCached. If RRDCached isn't an option then you can mount the rrd directory to read the RRD files directly.","title":"Web / API Layer"},{"location":"Extensions/Distributed-Poller/#database-server","text":"MySQL / MariaDB - At the moment these are the only database servers that are supported. The pollers, web and API layers should all be able to access the database server directly.","title":"Database Server"},{"location":"Extensions/Distributed-Poller/#rrd-storage","text":"Central storage should be provided so all RRD files can be read from and written to in one location. As suggested above, it's recommended that RRD Cached is configured and used. For this example, we are running RRDCached to allow all pollers and web/api servers to read/write to the rrd files with the rrd directory also exported by NFS for simple access and maintenance.","title":"RRD Storage"},{"location":"Extensions/Distributed-Poller/#pollers","text":"Pollers can be installed and run from anywhere, the only requirements are: They can access the Memcache instance They can create RRD files via some method such as a shared filesystem or RRDTool >=1.5.5 They can access the MySQL server You can either assign pollers into groups and set a poller group against certain devices, this will mean that those devices will only be processed by certain pollers (default poller group is 0) or you can assign all pollers to the default poller group for them to process any and all devices. This will provide the ability to have a single poller behind a NAT firewall monitor internal devices and report back to your central system. You will then be able to monitor those devices from the Web UI as normal. Another benefit to this is that you can provide N+x pollers, i.e if you know that you require three pollers to process all devices within 300 seconds then adding a 4th poller will mean that should any one single poller fail then the remaining three will complete polling in time. You could also use this to take a poller out of service for maintenance, i.e OS updates and software updates. It is extremely advisable to either run a central recursive dns server such as pdns-recursor and have all of your pollers use this or install a recursive dns server on each poller - the volume of DNS requests on large installs can be significant and will slow polling down enough to cause issues with a large number of devices. A last note to make sure of, is that all pollers writing to the same DB need to have the same APP_KEY value set in the .env file.","title":"Pollers"},{"location":"Extensions/Distributed-Poller/#discovery","text":"Depending on your setup will depend on how you configure your discovery processes. Cron based polling It's not necessary to run discovery services on all pollers. In fact, you should only run one discovery process per poller group. Designate a single poller to run discovery (or a separate server if required). If you run billing, you can do this in one of two ways: Run poll-billing.php and calculate-billing.php on a single poller which will create billing information for all bills. Please note this poller must have snmp access to all of your devices which have ports within a bill. The other option is to enable $config['distributed_billing'] = true; in config.php. Then run poll-billing.php on a single poller per group. You can run calculate-billing.php on any poller but only one poller overall. Dispatcher service When using the dispatcher service, discovery can run on all nodes.","title":"Discovery"},{"location":"Extensions/Distributed-Poller/#configuration","text":"Settings in config.php should be copied to all servers as they only apply locally. One way around this is to set settings in the database via the web ui or ./lnms config:set","title":"Configuration"},{"location":"Extensions/Distributed-Poller/#config-sample","text":"The following config is taken from a live setup which consists of a Web server, DB server, RRDCached server and 3 pollers. Web Server: Running Apache and an install of LibreNMS in /opt/librenms poller/distributed lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" Database Server: Running Memcache and MariaDB Memcache Ubuntu (/etc/memcached.conf) -d -m 64 -p 11211 -u memcache -l ip.ip.ip.ip RRDCached Server: Running RRDCached RRDCached Ubuntu (/etc/default/rrdcached) OPTS=\"-l 0:42217\" OPTS=\"$OPTS -j /var/lib/rrdcached/journal/ -F\" OPTS=\"$OPTS -b /opt/librenms/rrd -B\" OPTS=\"$OPTS -w 1800 -z 900\" Ubuntu (/etc/default/rrdcached) - RRDCached 1.5.5 and above. BASE_OPTIONS=\"-l 0:42217\" BASE_OPTIONS=\"$BASE_OPTIONS -R -j /var/lib/rrdcached/journal/ -F\" BASE_OPTIONS=\"$BASE_OPTIONS -b /opt/librenms/rrd -B\" BASE_OPTIONS=\"$BASE_OPTIONS -w 1800 -z 900\" Poller 1: Running an install of LibreNMS in /opt/librenms config.php $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); $config [ 'distributed_poller_group' ] = '0' ; $config [ 'distributed_billing' ] = true ; poller/distributed lnms config:set distributed_poller_memcached_host \"example.com\" lnms config:set distributed_poller_memcached_port 11211 lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" /etc/cron.d/librenms Runs discovery and polling for group 0, daily.sh to deal with notifications and DB cleanup and alerts. 33 */6 * * * librenms /opt/librenms/cronic /opt/librenms/discovery-wrapper.py 1 */5 * * * * librenms /opt/librenms/discovery.php -h new >> /dev/null 2>&1 */5 * * * * librenms /opt/librenms/cronic /opt/librenms/poller-wrapper.py 16 15 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1 * * * * * librenms /opt/librenms/alerts.php >> /dev/null 2>&1 Poller 2: Running an install of LibreNMS in /opt/librenms config.php $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); $config [ 'distributed_poller_group' ] = '0' ; $config [ 'distributed_billing' ] = true ; poller/distributed lnms config:set distributed_poller_memcached_host \"example.com\" lnms config:set distributed_poller_memcached_port 11211 lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" /etc/cron.d/librenms Runs billing as well as polling for group 0. */5 * * * * librenms /opt/librenms/poller-wrapper.py 16 >> /opt/librenms/logs/wrapper.log */5 * * * * librenms /opt/librenms/poll-billing.php >> /dev/null 2>&1 01 * * * * librenms /opt/librenms/billing-calculate.php >> /dev/null 2>&1 15 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1 Poller 3: Running an install of LibreNMS in /opt/librenms config.php $config [ 'distributed_poller_name' ] = php_uname ( 'n' ); $config [ 'distributed_poller_group' ] = '2,3' ; $config [ 'distributed_billing' ] = true ; poller/distributed lnms config:set distributed_poller_memcached_host \"example.com\" lnms config:set distributed_poller_memcached_port 11211 lnms config:set distributed_poller true poller/rrdtool lnms config:set rrdcached \"example.com:42217\" /etc/cron.d/librenms Runs discovery and polling for groups 2 and 3. 33 */6 * * * librenms /opt/librenms/cronic /opt/librenms/discovery-wrapper.py 1 */5 * * * * librenms /opt/librenms/discovery.php -h new >> /dev/null 2>&1 */5 * * * * librenms /opt/librenms/poll-billing.php >> /dev/null 2>&1 */5 * * * * librenms /opt/librenms/cronic /opt/librenms/poller-wrapper.py 16 15 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1","title":"Config sample"},{"location":"Extensions/Fast-Ping-Check/","text":"Fast up/down checking Normally, LibreNMS sends an ICMP ping to the device before polling to check if it is up or down. This check is tied to the poller frequency, which is normally 5 minutes. This means it may take up to 5 minutes to find out if a device is down. Some users may want to know if devices stop responding to ping more quickly than that. LibreNMS offers a ping.php script to run ping checks as quickly as possible without increasing snmp load on your devices by switching to 1 minute polling. WARNING : If you do not have an alert rule that alerts on device status, enabling this will be a waste of resources. You can find one in the Alert Rules Collection . Setting the ping check to 1 minute 1: If you are using RRDCached , stop the service. - This will flush all pending writes so that the rrdstep.php script can change the steps. 2: Change the ping_rrd_step setting in config.php poller/rrdtool lnms config:set ping_rrd_step 60 3: Update the rrd files to change the step (step is hardcoded at file creation in rrd files) ./scripts/rrdstep.php -h all 4: Add the following line to /etc/cron.d/librenms to allow 1 minute ping checks * * * * * librenms /opt/librenms/ping.php >> /dev/null 2>&1 5: If applicable: Start the RRDCached service NOTE : If you are using distributed pollers you can restrict a poller to a group by appending -g to the cron entry. Alternatively, you should only run ping.php on a single node. Sub minute ping check Cron only has a resolution of one minute, so for sub-minute ping checks we need to adapt both ping and alerts entries. We add two entries per function, but add a delay before one of these entries. Remember, you need to remove the original ping.php and alerts.php entries in crontab before proceeding! 1: Set ping_rrd_step poller/rrdtool lnms config:set ping_rrd_step 30 2: Update the rrd files ./scripts/rrdstep.php -h all 3: Update cron (removing any other ping.php or alert.php entries) * * * * * librenms /opt/librenms/ping.php >> /dev/null 2>&1 * * * * * librenms sleep 30 && /opt/librenms/ping.php >> /dev/null 2>&1 * * * * * librenms sleep 15 && /opt/librenms/alerts.php >> /dev/null 2>&1 * * * * * librenms sleep 45 && /opt/librenms/alerts.php >> /dev/null 2>&1 Device dependencies The ping.php script respects device dependencies, but the main poller does not (for technical reasons). However, using this script does not disable the icmp check in the poller and a child may be reported as down before the parent. Settings ping.php uses much the same settings as the poller fping with one exception: retries is used instead of count. ping.php does not measure loss and avg response time, only up/down, so once a device responds it stops pinging it. poller/ping lnms config:set fping_options.retries 2 lnms config:set fping_options.timeout 500 lnms config:set fping_options.interval 500","title":"Fast Ping Checking"},{"location":"Extensions/Fast-Ping-Check/#fast-updown-checking","text":"Normally, LibreNMS sends an ICMP ping to the device before polling to check if it is up or down. This check is tied to the poller frequency, which is normally 5 minutes. This means it may take up to 5 minutes to find out if a device is down. Some users may want to know if devices stop responding to ping more quickly than that. LibreNMS offers a ping.php script to run ping checks as quickly as possible without increasing snmp load on your devices by switching to 1 minute polling. WARNING : If you do not have an alert rule that alerts on device status, enabling this will be a waste of resources. You can find one in the Alert Rules Collection .","title":"Fast up/down checking"},{"location":"Extensions/Fast-Ping-Check/#setting-the-ping-check-to-1-minute","text":"1: If you are using RRDCached , stop the service. - This will flush all pending writes so that the rrdstep.php script can change the steps. 2: Change the ping_rrd_step setting in config.php poller/rrdtool lnms config:set ping_rrd_step 60 3: Update the rrd files to change the step (step is hardcoded at file creation in rrd files) ./scripts/rrdstep.php -h all 4: Add the following line to /etc/cron.d/librenms to allow 1 minute ping checks * * * * * librenms /opt/librenms/ping.php >> /dev/null 2>&1 5: If applicable: Start the RRDCached service NOTE : If you are using distributed pollers you can restrict a poller to a group by appending -g to the cron entry. Alternatively, you should only run ping.php on a single node.","title":"Setting the ping check to 1 minute"},{"location":"Extensions/Fast-Ping-Check/#sub-minute-ping-check","text":"Cron only has a resolution of one minute, so for sub-minute ping checks we need to adapt both ping and alerts entries. We add two entries per function, but add a delay before one of these entries. Remember, you need to remove the original ping.php and alerts.php entries in crontab before proceeding! 1: Set ping_rrd_step poller/rrdtool lnms config:set ping_rrd_step 30 2: Update the rrd files ./scripts/rrdstep.php -h all 3: Update cron (removing any other ping.php or alert.php entries) * * * * * librenms /opt/librenms/ping.php >> /dev/null 2>&1 * * * * * librenms sleep 30 && /opt/librenms/ping.php >> /dev/null 2>&1 * * * * * librenms sleep 15 && /opt/librenms/alerts.php >> /dev/null 2>&1 * * * * * librenms sleep 45 && /opt/librenms/alerts.php >> /dev/null 2>&1","title":"Sub minute ping check"},{"location":"Extensions/Fast-Ping-Check/#device-dependencies","text":"The ping.php script respects device dependencies, but the main poller does not (for technical reasons). However, using this script does not disable the icmp check in the poller and a child may be reported as down before the parent.","title":"Device dependencies"},{"location":"Extensions/Fast-Ping-Check/#settings","text":"ping.php uses much the same settings as the poller fping with one exception: retries is used instead of count. ping.php does not measure loss and avg response time, only up/down, so once a device responds it stops pinging it. poller/ping lnms config:set fping_options.retries 2 lnms config:set fping_options.timeout 500 lnms config:set fping_options.interval 500","title":"Settings"},{"location":"Extensions/Galera-Cluster/","text":"MariaDB Galera Cluster This is currently being tested, use at your own risk. LibreNMS can be used with a MariaDB Galera Cluster. This is a Multi Master cluster, meaning each node in the cluster can read and write to the database. They all have the same ability. LibreNMS will randomly choose a working node to read and write requests to. For more information see https://laravel.com/docs/database#read-and-write-connections Getting Started It is best practice to have a minimum of 3 nodes in the cluster, A odd number of nodes is recommended in the event nodes have a disagreement on data, they will have a tie breaker. It's recommended that all servers be similar in hardware performance, cluster performance can be affected by the slowest server in the cluster. Backup the database before starting, and backing up the database regularly is still recommended even in a working cluster environment. Install and Configure Galera Install Galera4 and MariaDB Server These can be obtained from your OS package manager. For example in Ubuntu. sudo apt-get install mariadb-server mariadb-client galera-4 Create Galera Config Create a new file /etc/mysql/conf.d/galera.conf on each node [mysqld] binlog_format=ROW default-storage-engine=innodb innodb_autoinc_lock_mode=2 bind-address=0.0.0.0 # Galera Provider Configuration wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # Galera Cluster Configuration wsrep_cluster_name=\"librenms_cluster\" wsrep_cluster_address=\"gcomm://192.168.1.35,192.168.1.36,192.168.1.37,192.168.1.38,192.168.1.39\" # Galera Synchronization Configuration wsrep_sst_method=rsync # Galera Node Configuration wsrep_node_address=\"192.168.1.35\" wsrep_node_name=\"librenms1.35\" Change the following values for your environment. * wsrep_cluster_address - All the IP address's of your nodes. * wsrep_cluster_name - Name of cluster, should be the same for all nodes * wsrep_node_address - IP address of this node. * wsrep_node_name - Name of this node. Edit LibreNMS .env LibreNMS supports up to 9 galera nodes, you define these nodes in the .env file. For each node we have the ability to define if this librenms installation/poller is able to write, read or both to that node. The galera nodes you define here can be the same or differnt for each librenms poller. If you have a poller you only want to write/read to one galera node, you would simply add one DB_HOST, and omit all the rest. This allows you to precisely control what galera nodes a librenms poller is reading and or writing too. DB_HOST is always set to read/write. DB_HOST must be set, however, it does not have to be the same on each poller, it can be different as long as it's part of the same galera cluster. If the node that is set to DB_HOST is down, things like lnms db command no longer work, as they only use DB_HOST and don't failover to other nodes. Set DB_CONNECTION=mysql_cluster to enable DB_STICKY can be used if you are pulling out of sync data form the database in a read request. For more information see https://laravel.com/docs/database#the-sticky-option The below example setting up 5 nodes DB_HOST=192.168.1.35 DB_HOST_R2=192.168.1.36 DB_HOST_R3=192.168.1.37 DB_HOST_R4=192.168.1.38 DB_HOST_R5=192.168.1.39 DB_HOST_W2=192.168.1.36 DB_HOST_W3=192.168.1.37 DB_STICKY=true DB_CONNECTION=mysql_cluster DB_DATABASE=librenms DB_USERNAME=librenms DB_PASSWORD=password The above .env on a librenms installation/poller would communicate to each galera node as follows. 192.168.1.35 - Read/Write 192.168.1.36 - Read/Write 192.168.1.37 - Read/Write 192.168.1.38 - Read Only 192.168.1.39 - Read Only Starting Galera Cluster for the first time. 1) Shutdown MariaDB server on ALL nodes. sudo systemctl stop mariadb-server 2) On the server with your existing database or any mariadb server if you are starting without existing data, run the following command sudo galera_new_cluster 3) Start the rest of the nodes normally. sudo systemctl start mariadb-server Galera Cluster Status To see some stats on how the Galera cluster is preforming run the following. lnms db In the database run following mysql query SHOW GLOBAL STATUS LIKE 'wsrep_%' ; Variable Name Value Notes ----------------------------------- ---------------------------------------------------------------- --------------------------------------------------------- wsrep_cluster_size 2 Current number of nodes in Cluster wsrep_cluster_state_uuid e71582f3-cf14-11eb-bcf6-a23029e16405 Last Transaction UUID, Should be the same for each node wsrep_connected On On = Connected with other nodes wsrep_local_state_comment Synced Synced with other nodes Restarting the Entire Cluster In a cluster environment, steps should be taken to ensure that ALL nodes are not offline at the same time. Failed nodes can recover without issue as long as one node remains online. In the event that ALL nodes are offline, the following should be done to ensure you are starting the cluster with the most up-to-date database. To do this login to each node and running the following sudo cat /var/lib/data/grastate.dat # GALERA saved state version: 2.1 uuid: e71582f3-cf14-11eb-bcf6-a23029e16405 seqno: -1 safe_to_bootstrap: 1 If the safe_to_bootstrap = 1, then Galera determined that this node has the most up-to-date database and can be safeley used to start the cluster. Once you have found a node that can be used for starting the cluster, follow the steps in starting for the first time.","title":"Galera Database Cluster"},{"location":"Extensions/Galera-Cluster/#mariadb-galera-cluster","text":"This is currently being tested, use at your own risk. LibreNMS can be used with a MariaDB Galera Cluster. This is a Multi Master cluster, meaning each node in the cluster can read and write to the database. They all have the same ability. LibreNMS will randomly choose a working node to read and write requests to. For more information see https://laravel.com/docs/database#read-and-write-connections","title":"MariaDB Galera Cluster"},{"location":"Extensions/Galera-Cluster/#getting-started","text":"It is best practice to have a minimum of 3 nodes in the cluster, A odd number of nodes is recommended in the event nodes have a disagreement on data, they will have a tie breaker. It's recommended that all servers be similar in hardware performance, cluster performance can be affected by the slowest server in the cluster. Backup the database before starting, and backing up the database regularly is still recommended even in a working cluster environment.","title":"Getting Started"},{"location":"Extensions/Galera-Cluster/#install-and-configure-galera","text":"","title":"Install and Configure Galera"},{"location":"Extensions/Galera-Cluster/#install-galera4-and-mariadb-server","text":"These can be obtained from your OS package manager. For example in Ubuntu. sudo apt-get install mariadb-server mariadb-client galera-4","title":"Install Galera4 and MariaDB Server"},{"location":"Extensions/Galera-Cluster/#create-galera-config","text":"Create a new file /etc/mysql/conf.d/galera.conf on each node [mysqld] binlog_format=ROW default-storage-engine=innodb innodb_autoinc_lock_mode=2 bind-address=0.0.0.0 # Galera Provider Configuration wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # Galera Cluster Configuration wsrep_cluster_name=\"librenms_cluster\" wsrep_cluster_address=\"gcomm://192.168.1.35,192.168.1.36,192.168.1.37,192.168.1.38,192.168.1.39\" # Galera Synchronization Configuration wsrep_sst_method=rsync # Galera Node Configuration wsrep_node_address=\"192.168.1.35\" wsrep_node_name=\"librenms1.35\" Change the following values for your environment. * wsrep_cluster_address - All the IP address's of your nodes. * wsrep_cluster_name - Name of cluster, should be the same for all nodes * wsrep_node_address - IP address of this node. * wsrep_node_name - Name of this node.","title":"Create Galera Config"},{"location":"Extensions/Galera-Cluster/#edit-librenms-env","text":"LibreNMS supports up to 9 galera nodes, you define these nodes in the .env file. For each node we have the ability to define if this librenms installation/poller is able to write, read or both to that node. The galera nodes you define here can be the same or differnt for each librenms poller. If you have a poller you only want to write/read to one galera node, you would simply add one DB_HOST, and omit all the rest. This allows you to precisely control what galera nodes a librenms poller is reading and or writing too. DB_HOST is always set to read/write. DB_HOST must be set, however, it does not have to be the same on each poller, it can be different as long as it's part of the same galera cluster. If the node that is set to DB_HOST is down, things like lnms db command no longer work, as they only use DB_HOST and don't failover to other nodes. Set DB_CONNECTION=mysql_cluster to enable DB_STICKY can be used if you are pulling out of sync data form the database in a read request. For more information see https://laravel.com/docs/database#the-sticky-option The below example setting up 5 nodes DB_HOST=192.168.1.35 DB_HOST_R2=192.168.1.36 DB_HOST_R3=192.168.1.37 DB_HOST_R4=192.168.1.38 DB_HOST_R5=192.168.1.39 DB_HOST_W2=192.168.1.36 DB_HOST_W3=192.168.1.37 DB_STICKY=true DB_CONNECTION=mysql_cluster DB_DATABASE=librenms DB_USERNAME=librenms DB_PASSWORD=password The above .env on a librenms installation/poller would communicate to each galera node as follows. 192.168.1.35 - Read/Write 192.168.1.36 - Read/Write 192.168.1.37 - Read/Write 192.168.1.38 - Read Only 192.168.1.39 - Read Only","title":"Edit LibreNMS .env"},{"location":"Extensions/Galera-Cluster/#starting-galera-cluster-for-the-first-time","text":"1) Shutdown MariaDB server on ALL nodes. sudo systemctl stop mariadb-server 2) On the server with your existing database or any mariadb server if you are starting without existing data, run the following command sudo galera_new_cluster 3) Start the rest of the nodes normally. sudo systemctl start mariadb-server","title":"Starting Galera Cluster for the first time."},{"location":"Extensions/Galera-Cluster/#galera-cluster-status","text":"To see some stats on how the Galera cluster is preforming run the following. lnms db In the database run following mysql query SHOW GLOBAL STATUS LIKE 'wsrep_%' ; Variable Name Value Notes ----------------------------------- ---------------------------------------------------------------- --------------------------------------------------------- wsrep_cluster_size 2 Current number of nodes in Cluster wsrep_cluster_state_uuid e71582f3-cf14-11eb-bcf6-a23029e16405 Last Transaction UUID, Should be the same for each node wsrep_connected On On = Connected with other nodes wsrep_local_state_comment Synced Synced with other nodes","title":"Galera Cluster Status"},{"location":"Extensions/Galera-Cluster/#restarting-the-entire-cluster","text":"In a cluster environment, steps should be taken to ensure that ALL nodes are not offline at the same time. Failed nodes can recover without issue as long as one node remains online. In the event that ALL nodes are offline, the following should be done to ensure you are starting the cluster with the most up-to-date database. To do this login to each node and running the following sudo cat /var/lib/data/grastate.dat # GALERA saved state version: 2.1 uuid: e71582f3-cf14-11eb-bcf6-a23029e16405 seqno: -1 safe_to_bootstrap: 1 If the safe_to_bootstrap = 1, then Galera determined that this node has the most up-to-date database and can be safeley used to start the cluster. Once you have found a node that can be used for starting the cluster, follow the steps in starting for the first time.","title":"Restarting the Entire Cluster"},{"location":"Extensions/Gateone/","text":"GateOne integration We have simple integration for GateOne , you will be redirected to your Gateone command line frontend to access your equipment. (Currently this only works with SSH) GateOne itself isn't included within LibreNMS, you will need to install this separately either on the same infrastructure as LibreNMS or as a totally standalone appliance. The installation is beyond the scope of this document. Config is simple, include the following in your config.php : $config [ 'gateone' ][ 'server' ] = 'http:// , have special meanings or effects. Before a command is executed, the IRC-Bot ensures that the MySQL-Socket is working, that $this->user points to the right user and that the user is authenticated. Below you will find a table with related functions and attributes. You can chain-load any built-in command by calling $this->_command(\"My Parameters\") . You cannot chain-load external commands. To enable your command, edit your config.php and add something like this: ... $config [ 'irc_external' ][] = \"mycommand\" ; ... See: Example Functions and Attributes ... that are accessible from within an extension Functions Function( (Type) $Variable [= Default] [,...] ) Returns Description $this->getChan( ) String Returns channel of current event. $this->getData( (boolean) $Block = false ) String/Boolean Returns a line from the IRC-Buffer if it's not matched against any other command . If $Block is true , wait until a suitable line is returned. $this->getUser( ) String Returns nick of current user. Not to confuse with $this->user ! $this->get_user( ) Array See $this->user in Attributes. $this->irc_raw( (string) $Protocol ) Boolean Sends raw IRC-Protocol. $this->isAuthd( ) Boolean true if the user is authenticated. $this->joinChan( (string) $Channel ) Boolean Joins given $Channel . $this->log( (string) $Message ) Boolean Logs given $Message into STDOUT . $this->read( (string) $Buffer ) String/Boolean Returns a line from given $Buffer or false if there's nothing suitable inside the Buffer. Please use $this->getData() for handler-safe data retrieval. $this->respond( (string) $Message ) Boolean Responds to the request auto-detecting channel or private message. Attributes Attribute Type Description $params String Contains all arguments that are passed to the .command . $this->chan Array Channels that are configured. $this->commands Array Contains accessible commands . $this->config Array Contains $config from config.php . $this->data String Contains raw IRC-Protocol. $this->debug Boolean Debug-Flag. $this->external Array Contains loaded extra commands . $this->nick String Bot's nick on the IRC. $this->pass String IRC-Server's passphrase. $this->port Int IRC-Server's port-number. $this->server String IRC-Server's hostname. $this->ssl Boolean SSL-Flag. $this->tick Int Interval to check buffers in microseconds. $this->user Array Array containing details about the user that sent the request . Example includes/ircbot/join-ng.inc.php if ( $this -> user [ 'level' ] != 10 ) { return $this -> respond ( \"Sorry only admins can make me join.\" ); } if ( $this -> getChan () == \"#noc\" ) { $this -> respond ( \"Joining $params \" ); $this -> joinChan ( $params ); } else { $this -> respond ( \"Sorry, only people from #noc can make join.\" ); } config.php ... $config [ 'irc_external' ][] = \"join-ng\" ; ...","title":"IRC Bot Extensions"},{"location":"Extensions/IRC-Bot-Extensions/#irc-bot-extensions","text":"Okay this is a very quick walk-through in writing your own commands for the IRC-Bot. First of all, create a file in includes/ircbot , the file-name should be in this format: command.inc.php . When editing the file, do not open nor close PHP-tags. Any variable you assign will be discarded as soon as your command returns. Some variables, specially all listed under $this-> , have special meanings or effects. Before a command is executed, the IRC-Bot ensures that the MySQL-Socket is working, that $this->user points to the right user and that the user is authenticated. Below you will find a table with related functions and attributes. You can chain-load any built-in command by calling $this->_command(\"My Parameters\") . You cannot chain-load external commands. To enable your command, edit your config.php and add something like this: ... $config [ 'irc_external' ][] = \"mycommand\" ; ... See: Example","title":"IRC Bot Extensions"},{"location":"Extensions/IRC-Bot-Extensions/#functions-and-attributes","text":"... that are accessible from within an extension","title":"Functions and Attributes"},{"location":"Extensions/IRC-Bot-Extensions/#functions","text":"Function( (Type) $Variable [= Default] [,...] ) Returns Description $this->getChan( ) String Returns channel of current event. $this->getData( (boolean) $Block = false ) String/Boolean Returns a line from the IRC-Buffer if it's not matched against any other command . If $Block is true , wait until a suitable line is returned. $this->getUser( ) String Returns nick of current user. Not to confuse with $this->user ! $this->get_user( ) Array See $this->user in Attributes. $this->irc_raw( (string) $Protocol ) Boolean Sends raw IRC-Protocol. $this->isAuthd( ) Boolean true if the user is authenticated. $this->joinChan( (string) $Channel ) Boolean Joins given $Channel . $this->log( (string) $Message ) Boolean Logs given $Message into STDOUT . $this->read( (string) $Buffer ) String/Boolean Returns a line from given $Buffer or false if there's nothing suitable inside the Buffer. Please use $this->getData() for handler-safe data retrieval. $this->respond( (string) $Message ) Boolean Responds to the request auto-detecting channel or private message.","title":"Functions"},{"location":"Extensions/IRC-Bot-Extensions/#attributes","text":"Attribute Type Description $params String Contains all arguments that are passed to the .command . $this->chan Array Channels that are configured. $this->commands Array Contains accessible commands . $this->config Array Contains $config from config.php . $this->data String Contains raw IRC-Protocol. $this->debug Boolean Debug-Flag. $this->external Array Contains loaded extra commands . $this->nick String Bot's nick on the IRC. $this->pass String IRC-Server's passphrase. $this->port Int IRC-Server's port-number. $this->server String IRC-Server's hostname. $this->ssl Boolean SSL-Flag. $this->tick Int Interval to check buffers in microseconds. $this->user Array Array containing details about the user that sent the request .","title":"Attributes"},{"location":"Extensions/IRC-Bot-Extensions/#example","text":"includes/ircbot/join-ng.inc.php if ( $this -> user [ 'level' ] != 10 ) { return $this -> respond ( \"Sorry only admins can make me join.\" ); } if ( $this -> getChan () == \"#noc\" ) { $this -> respond ( \"Joining $params \" ); $this -> joinChan ( $params ); } else { $this -> respond ( \"Sorry, only people from #noc can make join.\" ); } config.php ... $config [ 'irc_external' ][] = \"join-ng\" ; ...","title":"Example"},{"location":"Extensions/IRC-Bot/","text":"IRC Bot LibreNMS has an easy to use IRC-Interface for basic tasks like viewing last log-entry, current device/port status and such. By default the IRC-Bot will not start when executed and will return an error until at least $config['irc_host'] and $config['irc_port'] has been specified inside config.php . (To start the IRC-Bot run ./irc.php ) If no channel has been specified with $config['irc_chan'] , ##librenms will be used. The default Nick for the bot is LibreNMS . The Bot will reply the same way it's being called. If you send it the commands via Query, it will respond in the Query. If you send the commands via a Channel, then it will respond in the Channel. Configuration & Defaults Option Default-Value Notes $config['irc_alert'] false Optional; Enables Alerting-Socket. EXPERIMENTAL $config['irc_alert_chan'] false Optional; Multiple channels can be defined as Array or delimited with , . EXPERIMENTAL $config['irc_alert_utf8'] false Optional; Enables use of strikethrough in alerts via UTF-8 encoded characters. Might cause trouble for some clients. $config['irc_alert_short'] false Optional; Send a one line alert summary instead of multi-line detailed alert. $config['irc_authtime'] 3 Optional; Defines how long in Hours an auth-session is valid. $config['irc_chan'] ##librenms Optional; Multiple channels can be defined as Array or delimited with , . Passwords are defined after a space-character . $config['irc_debug'] false Optional; Enables debug output (Wall of text) $config['irc_external'] Optional; Array or , delimited string with commands to include from includes/ircbot/*.inc.php $config['irc_host'] Required; Domain or IP to connect. If it's an IPv6 Address, embed it in [] . (Example: [::1] ) $config['irc_maxretry'] 5 Optional; How many connection attempts should be made before giving up $config['irc_nick'] LibreNMS Optional; $config['irc_pass'] Optional; This sends the IRC-PASS Sequence to IRC-Servers that require Password on Connect $config['irc_port'] 6667 Required; To enable SSL append a + before the Port. (Example: +6697 ) $config['irc_ctcp'] false Optional; Enable/disable ctcp-replies from the bot (currently VERSION, PING and TIME). $config['irc_ctcp_version'] LibreNMS IRCbot. https://www.librenms.org/ Optional; Reply-string to CTCP VERSION requests $config['irc_auth'] Optional; Array of hostmasks that are automatically authenticated. IRC-Commands Command Description .auth If : Request an Auth-Token. If : Authenticate session. .device Prints basic information about given hostname . .down List hostnames that are down, if any. .help List available commands. .join Joins if user has admin-level. .listdevices Lists the hostnames of all known devices. .log [] Prints N lines or last line of the eventlog. .port Prints Port-related information from ifname on given hostname . .quit Disconnect from IRC and exit. .reload Reload configuration. .status Prints status information for given type . Type can be devices , services , ports . Shorthands are: dev , srv , prt .version Prints $this->config['project_name_version'] . ( /!\\ All commands are case- insensitive but their arguments are case- sensitive ) Examples Server examples Unencrypted Connection to irc.libera.chat : ... $config [ 'irc_host' ] = \"irc.libera.chat\" ; $config [ 'irc_port' ] = 6667 ; ... SSL-Encrypted Connection to irc.libera.chat : ... $config [ 'irc_host' ] = \"irc.libera.chat\" ; $config [ 'irc_port' ] = \"+6697\" ; ... SSL-Encrypted Connection to irc.localdomain with Server-Password and odd port: ... $config [ 'irc_host' ] = \"irc.localdomain\" ; $config [ 'irc_port' ] = \"+12345\" ; $config [ 'irc_pass' ] = \"Super Secret Passphrase123\" ; ... Channel notations Channels can be defined using Array-Notation like: ... $config [ 'irc_chan' ][] = \"#librenms\" ; $config [ 'irc_chan' ][] = \"#otherchan\" ; $config [ 'irc_chan' ][] = \"#noc\" ; ... Or using a single string using , as delimiter between various channels: ... $config [ 'irc_chan' ] = \"#librenms,#otherchan,#noc\" ; ... Hostmask authentication ... $config [ 'irc_auth' ][ 'admin' ][] = \"*!root@nms.host.invalid\" ; $config [ 'irc_auth' ][ 'admin' ][] = \"*!*peter@peters.computer.invalid\" ; $config [ 'irc_auth' ][ ' john ][] = \"john!doe@login.server.invalid\" ; ... Any client matching one of the first two hostmasks will automatically be authenticated as the \"admin\" user in LibreNMS, and clients matching the last line will be authenticated as the user \"john\" in LibreNMS, without using .auth and a waiting for a valid token. Extensions?! The bot is coded in a unified way. This makes writing extensions by far less painful. Simply add your command to the $config['irc_external'] directive and create a file called includes/ircbot/command.inc.php containing your code. The string behind the call of .command is passed as $params . The user who requested something is accessible via $this->user . Send your reply/ies via $this->respond($string) . A more detailed documentation of the functions and variables available for extensions can be found at IRC-Bot Extensions ; Confused? Here an Echo-Example: File: config.php ... $config [ 'irc_external' ][] = \"echo\" ; ... File: includes/ircbot/echo.inc.php //Prefix everything with `You said: '...'` and return what was sent. if ( $this -> user [ 'name' ] != \"root\" ) { return $this -> respond ( \"You said: '\" . $params . \"'\" ); } else { return $this -> respond ( \"root shouldn't be online so late!\" ); } Systemd start up script Basic systemd start up script to be placed in /etc/systemd/system/ to start irc service at boot. librenms-irc.service script is located at /opt/librenms/misc/ Once copied to /etc/systemd/system/ you must run the following commands: a) chmod 664 /etc/systemd/system/librenms-irc.service b) systemctl daemon-reload c) systemctl enable librenms-irc.service d) systemctl start librenms-irc.service It can be stopped or started just like any other systemd script such as systemctl start librenms-irc.service","title":"IRC Bot"},{"location":"Extensions/IRC-Bot/#irc-bot","text":"LibreNMS has an easy to use IRC-Interface for basic tasks like viewing last log-entry, current device/port status and such. By default the IRC-Bot will not start when executed and will return an error until at least $config['irc_host'] and $config['irc_port'] has been specified inside config.php . (To start the IRC-Bot run ./irc.php ) If no channel has been specified with $config['irc_chan'] , ##librenms will be used. The default Nick for the bot is LibreNMS . The Bot will reply the same way it's being called. If you send it the commands via Query, it will respond in the Query. If you send the commands via a Channel, then it will respond in the Channel.","title":"IRC Bot"},{"location":"Extensions/IRC-Bot/#configuration-defaults","text":"Option Default-Value Notes $config['irc_alert'] false Optional; Enables Alerting-Socket. EXPERIMENTAL $config['irc_alert_chan'] false Optional; Multiple channels can be defined as Array or delimited with , . EXPERIMENTAL $config['irc_alert_utf8'] false Optional; Enables use of strikethrough in alerts via UTF-8 encoded characters. Might cause trouble for some clients. $config['irc_alert_short'] false Optional; Send a one line alert summary instead of multi-line detailed alert. $config['irc_authtime'] 3 Optional; Defines how long in Hours an auth-session is valid. $config['irc_chan'] ##librenms Optional; Multiple channels can be defined as Array or delimited with , . Passwords are defined after a space-character . $config['irc_debug'] false Optional; Enables debug output (Wall of text) $config['irc_external'] Optional; Array or , delimited string with commands to include from includes/ircbot/*.inc.php $config['irc_host'] Required; Domain or IP to connect. If it's an IPv6 Address, embed it in [] . (Example: [::1] ) $config['irc_maxretry'] 5 Optional; How many connection attempts should be made before giving up $config['irc_nick'] LibreNMS Optional; $config['irc_pass'] Optional; This sends the IRC-PASS Sequence to IRC-Servers that require Password on Connect $config['irc_port'] 6667 Required; To enable SSL append a + before the Port. (Example: +6697 ) $config['irc_ctcp'] false Optional; Enable/disable ctcp-replies from the bot (currently VERSION, PING and TIME). $config['irc_ctcp_version'] LibreNMS IRCbot. https://www.librenms.org/ Optional; Reply-string to CTCP VERSION requests $config['irc_auth'] Optional; Array of hostmasks that are automatically authenticated.","title":"Configuration & Defaults"},{"location":"Extensions/IRC-Bot/#irc-commands","text":"Command Description .auth If : Request an Auth-Token. If : Authenticate session. .device Prints basic information about given hostname . .down List hostnames that are down, if any. .help List available commands. .join Joins if user has admin-level. .listdevices Lists the hostnames of all known devices. .log [] Prints N lines or last line of the eventlog. .port Prints Port-related information from ifname on given hostname . .quit Disconnect from IRC and exit. .reload Reload configuration. .status Prints status information for given type . Type can be devices , services , ports . Shorthands are: dev , srv , prt .version Prints $this->config['project_name_version'] . ( /!\\ All commands are case- insensitive but their arguments are case- sensitive )","title":"IRC-Commands"},{"location":"Extensions/IRC-Bot/#examples","text":"","title":"Examples"},{"location":"Extensions/IRC-Bot/#server-examples","text":"Unencrypted Connection to irc.libera.chat : ... $config [ 'irc_host' ] = \"irc.libera.chat\" ; $config [ 'irc_port' ] = 6667 ; ... SSL-Encrypted Connection to irc.libera.chat : ... $config [ 'irc_host' ] = \"irc.libera.chat\" ; $config [ 'irc_port' ] = \"+6697\" ; ... SSL-Encrypted Connection to irc.localdomain with Server-Password and odd port: ... $config [ 'irc_host' ] = \"irc.localdomain\" ; $config [ 'irc_port' ] = \"+12345\" ; $config [ 'irc_pass' ] = \"Super Secret Passphrase123\" ; ...","title":"Server examples"},{"location":"Extensions/IRC-Bot/#channel-notations","text":"Channels can be defined using Array-Notation like: ... $config [ 'irc_chan' ][] = \"#librenms\" ; $config [ 'irc_chan' ][] = \"#otherchan\" ; $config [ 'irc_chan' ][] = \"#noc\" ; ... Or using a single string using , as delimiter between various channels: ... $config [ 'irc_chan' ] = \"#librenms,#otherchan,#noc\" ; ...","title":"Channel notations"},{"location":"Extensions/IRC-Bot/#hostmask-authentication","text":"... $config [ 'irc_auth' ][ 'admin' ][] = \"*!root@nms.host.invalid\" ; $config [ 'irc_auth' ][ 'admin' ][] = \"*!*peter@peters.computer.invalid\" ; $config [ 'irc_auth' ][ ' john ][] = \"john!doe@login.server.invalid\" ; ... Any client matching one of the first two hostmasks will automatically be authenticated as the \"admin\" user in LibreNMS, and clients matching the last line will be authenticated as the user \"john\" in LibreNMS, without using .auth and a waiting for a valid token.","title":"Hostmask authentication"},{"location":"Extensions/IRC-Bot/#extensions","text":"The bot is coded in a unified way. This makes writing extensions by far less painful. Simply add your command to the $config['irc_external'] directive and create a file called includes/ircbot/command.inc.php containing your code. The string behind the call of .command is passed as $params . The user who requested something is accessible via $this->user . Send your reply/ies via $this->respond($string) . A more detailed documentation of the functions and variables available for extensions can be found at IRC-Bot Extensions ; Confused? Here an Echo-Example: File: config.php ... $config [ 'irc_external' ][] = \"echo\" ; ... File: includes/ircbot/echo.inc.php //Prefix everything with `You said: '...'` and return what was sent. if ( $this -> user [ 'name' ] != \"root\" ) { return $this -> respond ( \"You said: '\" . $params . \"'\" ); } else { return $this -> respond ( \"root shouldn't be online so late!\" ); }","title":"Extensions?!"},{"location":"Extensions/IRC-Bot/#systemd-start-up-script","text":"Basic systemd start up script to be placed in /etc/systemd/system/ to start irc service at boot. librenms-irc.service script is located at /opt/librenms/misc/ Once copied to /etc/systemd/system/ you must run the following commands: a) chmod 664 /etc/systemd/system/librenms-irc.service b) systemctl daemon-reload c) systemctl enable librenms-irc.service d) systemctl start librenms-irc.service It can be stopped or started just like any other systemd script such as systemctl start librenms-irc.service","title":"Systemd start up script"},{"location":"Extensions/Interface-Description-Parsing/","text":"Interface Description Parsing Librenms can interpret, display and group certain additional information on ports. This is done based on the format that the port description is written although it's possible to customise the parser to be specific for your setup. Keywords See examples for formats. Keywords Cust - Customer Transit - Transit link Peering - Peering link Core - Infrastructure link (non-customer) Info-keywords () contains a note {} contains your circuit id [] contains the service type or speed Examples Cisco IOS / NXOS / IOSXR: interface Gi0/1 descr Transit: Example Provider (AS65000) interface Gi0/2 descr Peering: Peering Exchange interface Gi0/3 descr Core: core.router01 FastEthernet0/0 (Telco X CCID023141) interface Gi0/4 descr Cust: Example Customer [10Mbit] (T1 Telco Y CCID129031) {EXAMP0001} Unix / Linux: This requires an additional script to be setup # eth3: Cust: Example Customer [10Mbit] (T1 Telco Y CCID129031) {EXAMP0001} # eth0: Transit: Example Provider (AS65000) # eth1: Core: core.router01 FastEthernet0/0 (Telco X CCID023141) # eth2: Peering: Peering Exchange Customisation The following config options can be set to enable more custom types: webui/port-descr lnms config:set customers_descr.+ 'cust' lnms config:set transit_descr.+ 'transit' lnms config:set peering_descr.+ 'peering' \";' lnms config:set core_descr.+ 'core' lnms config:set custom_descr.+ 'something_made_up' Custom interface parser It's also possible to write your own parser, the existing one is: includes/port-descr-parser.inc.php Once you've created your own then you can enable it with: $config [ 'port_descr_parser' ] = \"includes/custom/my-port-descr-parser.inc.php\" ; Setup For Unix / Linux based systems, you need to run an additional script to support the parsing of interface information. Add ifAlias from /opt/librenms/scripts/ or download it from here to the Server and make it executable chmod +x /path/to/ifAlias Add to snmpd.conf something like: pass .1.3.6.1.2.1.31.1.1.1.18 /path/to/ifAlias Add aliasses with iproute2 package like: ip link set eth0.427 alias 'Cust: CustomerA' in /etc/network/interfaces or /etc/network/interfaces.d/* with a comment like: # eth0.427: Cust CustomerA Restart snmpd - systemctl restart snmpd There are no changes to be made or additions to install for the polling librenms. Now you can set up your keywords in your aliases.","title":"Interface Description Parsing"},{"location":"Extensions/Interface-Description-Parsing/#interface-description-parsing","text":"Librenms can interpret, display and group certain additional information on ports. This is done based on the format that the port description is written although it's possible to customise the parser to be specific for your setup.","title":"Interface Description Parsing"},{"location":"Extensions/Interface-Description-Parsing/#keywords","text":"See examples for formats. Keywords Cust - Customer Transit - Transit link Peering - Peering link Core - Infrastructure link (non-customer) Info-keywords () contains a note {} contains your circuit id [] contains the service type or speed","title":"Keywords"},{"location":"Extensions/Interface-Description-Parsing/#examples","text":"Cisco IOS / NXOS / IOSXR: interface Gi0/1 descr Transit: Example Provider (AS65000) interface Gi0/2 descr Peering: Peering Exchange interface Gi0/3 descr Core: core.router01 FastEthernet0/0 (Telco X CCID023141) interface Gi0/4 descr Cust: Example Customer [10Mbit] (T1 Telco Y CCID129031) {EXAMP0001} Unix / Linux: This requires an additional script to be setup # eth3: Cust: Example Customer [10Mbit] (T1 Telco Y CCID129031) {EXAMP0001} # eth0: Transit: Example Provider (AS65000) # eth1: Core: core.router01 FastEthernet0/0 (Telco X CCID023141) # eth2: Peering: Peering Exchange","title":"Examples"},{"location":"Extensions/Interface-Description-Parsing/#customisation","text":"The following config options can be set to enable more custom types: webui/port-descr lnms config:set customers_descr.+ 'cust' lnms config:set transit_descr.+ 'transit' lnms config:set peering_descr.+ 'peering' \";' lnms config:set core_descr.+ 'core' lnms config:set custom_descr.+ 'something_made_up'","title":"Customisation"},{"location":"Extensions/Interface-Description-Parsing/#custom-interface-parser","text":"It's also possible to write your own parser, the existing one is: includes/port-descr-parser.inc.php Once you've created your own then you can enable it with: $config [ 'port_descr_parser' ] = \"includes/custom/my-port-descr-parser.inc.php\" ;","title":"Custom interface parser"},{"location":"Extensions/Interface-Description-Parsing/#setup","text":"For Unix / Linux based systems, you need to run an additional script to support the parsing of interface information. Add ifAlias from /opt/librenms/scripts/ or download it from here to the Server and make it executable chmod +x /path/to/ifAlias Add to snmpd.conf something like: pass .1.3.6.1.2.1.31.1.1.1.18 /path/to/ifAlias Add aliasses with iproute2 package like: ip link set eth0.427 alias 'Cust: CustomerA' in /etc/network/interfaces or /etc/network/interfaces.d/* with a comment like: # eth0.427: Cust CustomerA Restart snmpd - systemctl restart snmpd There are no changes to be made or additions to install for the polling librenms. Now you can set up your keywords in your aliases.","title":"Setup"},{"location":"Extensions/Metric-Storage/","text":"Metric storage By default we ship all metrics to RRD files, either directly or via RRDCached . On top of this you can ship metrics to Graphite, InfluxDB (v1 or v2 API), OpenTSDB or Prometheus. At present you can't use these backends to display graphs within LibreNMS and will need to use something like Grafana . For further information on configuring LibreNMS to ship data to one of the other backends then please see the documentation below. Graphite InfluxDB InfluxDBv2 OpenTSDB Prometheus","title":"Intro"},{"location":"Extensions/Metric-Storage/#metric-storage","text":"By default we ship all metrics to RRD files, either directly or via RRDCached . On top of this you can ship metrics to Graphite, InfluxDB (v1 or v2 API), OpenTSDB or Prometheus. At present you can't use these backends to display graphs within LibreNMS and will need to use something like Grafana . For further information on configuring LibreNMS to ship data to one of the other backends then please see the documentation below. Graphite InfluxDB InfluxDBv2 OpenTSDB Prometheus","title":"Metric storage"},{"location":"Extensions/NFSen/","text":"NFSen The installation of NFSen is out of scope for this document / LibreNMS Configuration The following is the configuration that can be used: external/nfsen lnms config:set nfsen_enable true lnms config:set nfsen_split_char '_' lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/live/' lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat' lnms config:set nfsen_base.+ '/var/nfsen/' lnms config:set nfsen_suffix '_yourdomain_com' Set lnms config:set nfsen_enable true to enable NFSen support. nfsen_rrds This value tells us where your NFSen rrd files live. This can also be an array to specify more directories like: external/nfsen lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/sitea/' lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/siteb/' Although for most setups, it will look like below, with the profiles-stat/live directory being where it stores the general RRDs for data sources. external/nfsen lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/live' If you wish to render info for configure channels for a device, you need add the various profile-stat directories your system uses, which for most systems will be as below. external/nfsen lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat' When adding sources to nfsen.conf, it is important to use the hostname that matches what is configured in LibreNMS, because the rrd files NfSen creates is named after the source name (ident), and it doesn't allow you to use an IP address instead. However, in LibreNMS, if your device is added by an IP address, add your source with any name of your choice, and create a symbolic link to the rrd file. cd /var/nfsen/profiles-stat/sitea/ ln -s mychannel.rrd librenmsdeviceIP.rrd external/nfsen lnms config:set nfsen_split_char '_' This value tells us what to replace the full stops . in the devices hostname with. external/nfsen lnms config:set nfsen_suffix '_yourdomain_com' The above is a very important bit as device names in NfSen are limited to 21 characters. This means full domain names for devices can be very problematic to squeeze in, so therefor this chunk is usually removed. On a similar note, NfSen profiles for channels should be created with the same name. Stats Defaults and Settings Below are the default settings used with nfdump for stats. For more defaulted information on that, please see nfdump(1). The default location for nfdump is /usr/bin/nfdump . If nfdump is located elsewhere, set it with external/binaries ```bash lnms config:set nfdump /usr/local/bin/nfdump ``` external/nfsen lnms config:set nfsen_last_max 153600 lnms config:set nfsen_top_max 500 lnms config:set nfsen_top_N '[10, 20, 50, 100, 200, 500]' lnms config:set nfsen_top_default 20 lnms config:set nfsen_stat_default srcip lnms config:set nfsen_order_default packets lnms config:set nfsen_last_default 900 lnms config:set nfsen_lasts \"{'300':'5 minutes', '600':'10 minutes', '900':'15 minutes', '1800':'30 minutes', '3600':'1 hour', '9600':'3 hours', '38400':'12 hours', '76800':'24 hours', '115200':'36 hours', '153600':'48 hours'}\" external/nfsen lnms config:set nfsen_last_max 153600 The above is the max value in seconds one may pull stats for. The higher this is, the more CPU and disk intensive the search will be. Numbers larger than this will be set to this. external/nfsen lnms config:set nfsen_top_max 500 The above is max number of items to be displayed. Numbers larger than this will be set to this. external/nfsen lnms config:set nfsen_top_N '[10, 20, 50, 100, 200, 500]' The above is a array containing a list for the drop down menu how many top items should be returned. external/nfsen lnms config:set nfsen_top_default 20 The above sets default top number to use from the drop down. external/nfsen lnms config:set nfsen_stat_default srcip The above sets default stat type to use from the drop down. record Flow Records ip Any IP Address srcip SRC IP Address dstip DST IP Address port Any Port srcport SRC Port dstport DST Port srctos SRC TOS dsttos DST TOS tos TOS as AS srcas SRC AS dstas DST AS external/nfsen lnms config:set nfsen_order_default packets The above sets default order type to use from the drop down. Any of the following below are currently supported. flows Number of total flows for the time period. packet Number of total packets for the time period. bytes Number of total bytes for the time period. pps Packets Per Second bps Bytes Per Second bpp Bytes Per Packet external/nfsen lnms config:set nfsen_last_default 900 The above is the last default to use from the drop down. external/nfsen lnms config:set nfsen_lasts \"{'300':'5 minutes', '600':'10 minutes', '900':'15 minutes', '1800':'30 minutes', '3600':'1 hour', '9600':'3 hours', '38400':'12 hours', '76800':'24 hours', '115200':'36 hours', '153600':'48 hours'}\" The above associative array contains time intervals for how far back to go. The keys are the length in seconds and the value is just a description to display.","title":"NFSen"},{"location":"Extensions/NFSen/#nfsen","text":"The installation of NFSen is out of scope for this document / LibreNMS","title":"NFSen"},{"location":"Extensions/NFSen/#configuration","text":"The following is the configuration that can be used: external/nfsen lnms config:set nfsen_enable true lnms config:set nfsen_split_char '_' lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/live/' lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat' lnms config:set nfsen_base.+ '/var/nfsen/' lnms config:set nfsen_suffix '_yourdomain_com' Set lnms config:set nfsen_enable true to enable NFSen support. nfsen_rrds This value tells us where your NFSen rrd files live. This can also be an array to specify more directories like: external/nfsen lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/sitea/' lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/siteb/' Although for most setups, it will look like below, with the profiles-stat/live directory being where it stores the general RRDs for data sources. external/nfsen lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat/live' If you wish to render info for configure channels for a device, you need add the various profile-stat directories your system uses, which for most systems will be as below. external/nfsen lnms config:set nfsen_rrds.+ '/var/nfsen/profiles-stat' When adding sources to nfsen.conf, it is important to use the hostname that matches what is configured in LibreNMS, because the rrd files NfSen creates is named after the source name (ident), and it doesn't allow you to use an IP address instead. However, in LibreNMS, if your device is added by an IP address, add your source with any name of your choice, and create a symbolic link to the rrd file. cd /var/nfsen/profiles-stat/sitea/ ln -s mychannel.rrd librenmsdeviceIP.rrd external/nfsen lnms config:set nfsen_split_char '_' This value tells us what to replace the full stops . in the devices hostname with. external/nfsen lnms config:set nfsen_suffix '_yourdomain_com' The above is a very important bit as device names in NfSen are limited to 21 characters. This means full domain names for devices can be very problematic to squeeze in, so therefor this chunk is usually removed. On a similar note, NfSen profiles for channels should be created with the same name.","title":"Configuration"},{"location":"Extensions/NFSen/#stats-defaults-and-settings","text":"Below are the default settings used with nfdump for stats. For more defaulted information on that, please see nfdump(1). The default location for nfdump is /usr/bin/nfdump . If nfdump is located elsewhere, set it with external/binaries ```bash lnms config:set nfdump /usr/local/bin/nfdump ``` external/nfsen lnms config:set nfsen_last_max 153600 lnms config:set nfsen_top_max 500 lnms config:set nfsen_top_N '[10, 20, 50, 100, 200, 500]' lnms config:set nfsen_top_default 20 lnms config:set nfsen_stat_default srcip lnms config:set nfsen_order_default packets lnms config:set nfsen_last_default 900 lnms config:set nfsen_lasts \"{'300':'5 minutes', '600':'10 minutes', '900':'15 minutes', '1800':'30 minutes', '3600':'1 hour', '9600':'3 hours', '38400':'12 hours', '76800':'24 hours', '115200':'36 hours', '153600':'48 hours'}\" external/nfsen lnms config:set nfsen_last_max 153600 The above is the max value in seconds one may pull stats for. The higher this is, the more CPU and disk intensive the search will be. Numbers larger than this will be set to this. external/nfsen lnms config:set nfsen_top_max 500 The above is max number of items to be displayed. Numbers larger than this will be set to this. external/nfsen lnms config:set nfsen_top_N '[10, 20, 50, 100, 200, 500]' The above is a array containing a list for the drop down menu how many top items should be returned. external/nfsen lnms config:set nfsen_top_default 20 The above sets default top number to use from the drop down. external/nfsen lnms config:set nfsen_stat_default srcip The above sets default stat type to use from the drop down. record Flow Records ip Any IP Address srcip SRC IP Address dstip DST IP Address port Any Port srcport SRC Port dstport DST Port srctos SRC TOS dsttos DST TOS tos TOS as AS srcas SRC AS dstas DST AS external/nfsen lnms config:set nfsen_order_default packets The above sets default order type to use from the drop down. Any of the following below are currently supported. flows Number of total flows for the time period. packet Number of total packets for the time period. bytes Number of total bytes for the time period. pps Packets Per Second bps Bytes Per Second bpp Bytes Per Packet external/nfsen lnms config:set nfsen_last_default 900 The above is the last default to use from the drop down. external/nfsen lnms config:set nfsen_lasts \"{'300':'5 minutes', '600':'10 minutes', '900':'15 minutes', '1800':'30 minutes', '3600':'1 hour', '9600':'3 hours', '38400':'12 hours', '76800':'24 hours', '115200':'36 hours', '153600':'48 hours'}\" The above associative array contains time intervals for how far back to go. The keys are the length in seconds and the value is just a description to display.","title":"Stats Defaults and Settings"},{"location":"Extensions/Network-Map/","text":"Network Map LibreNMS has the ability to show you a dynamic network map based on data collected from devices. These maps are accessed through the following menu options: Overview -> Maps -> Network Overview -> Maps -> Device Group Maps The Neighbours -> Map tab when viewing a single device (the Neighbours tab will only show if a device has xDP neighbours) These network maps can be based on: xDP Discovery MAC addresses (ARP entries matching interface IP and MAC) By default, both are are included but you can enable / disable either one using the following config option: lnms config:set 'network_map_items' \"('mac','xdp')\" Either remove mac or xdp depending on which you want. XDP is based on FDP, CDP and LLDP support based on the device type. It is worth noting that the global map could lead to a large network map that is slow to render and interact with. The network map on the device neighbour page, or building device groups and using the device group maps will be more usable on large networks. Settings The map display can be configured by altering the VisJS-Config.md","title":"Network Map"},{"location":"Extensions/Network-Map/#network-map","text":"LibreNMS has the ability to show you a dynamic network map based on data collected from devices. These maps are accessed through the following menu options: Overview -> Maps -> Network Overview -> Maps -> Device Group Maps The Neighbours -> Map tab when viewing a single device (the Neighbours tab will only show if a device has xDP neighbours) These network maps can be based on: xDP Discovery MAC addresses (ARP entries matching interface IP and MAC) By default, both are are included but you can enable / disable either one using the following config option: lnms config:set 'network_map_items' \"('mac','xdp')\" Either remove mac or xdp depending on which you want. XDP is based on FDP, CDP and LLDP support based on the device type. It is worth noting that the global map could lead to a large network map that is slow to render and interact with. The network map on the device neighbour page, or building device groups and using the device group maps will be more usable on large networks.","title":"Network Map"},{"location":"Extensions/Network-Map/#settings","text":"The map display can be configured by altering the VisJS-Config.md","title":"Settings"},{"location":"Extensions/OAuth-SAML/","text":"OAuth and SAML Support Introduction LibreNMS has support for Laravel Socialite to try and simplify the use of OAuth 1 or 2 providers such as using GitHub, Microsoft, Twitter + many more and SAML. Socialite Providers supports more than 100+ 3rd parties so you will most likely find support for the SAML or OAuth provider you need without too much trouble. Please do note however, these providers are not maintained by LibreNMS so we cannot add support for new ones and we can only provide you basic help with general configuration. See the Socialite Providers website for more information on adding a new OAuth provider. Below we will guide you on how to install SAML or some of these OAth providers, you should be able to use these as a guide on how to install any others you may need but please, please, ensure you read the Socialite Providers documentation carefully . GitHub Provider Microsoft Provider Okta Provider SAML2 Requirements LibreNMS version 22.3.0 or later. Please ensure you set APP_URL within your .env file so that callback URLs work correctly with the identify provider. Note Once you have configured your OAuth or SAML2 provider, please ensure you check the Post configuration settings section at the end. GitHub and Microsoft Examples Install plugin Note First we need to install the plugin itself. The plugin name can be slightly different so be sure to check the Socialite Providers documentation and look for this line, composer require socialiteproviders/github which will give you the name you need for the command, i.e: socialiteproviders/github . GitHub Microsoft Okta lnms plugin:add socialiteproviders/github lnms plugin:add socialiteproviders/microsoft lnms plugin:add socialiteproviders/okta Find the provider name Next we need to find the provider name and writing it down Note It's almost always the name of the provider in lowercase but can be different so check the Socialite Providers documentation and look for this line, github => [ which will give you the name you need for the above command: github . GitHub Microsoft Okta For GitHub we can find the line: 'github' => [ 'client_id' => env ( 'GITHUB_CLIENT_ID' ), 'client_secret' => env ( 'GITHUB_CLIENT_SECRET' ), 'redirect' => env ( 'GITHUB_REDIRECT_URI' ) ], So our provider name is github , write this down. For Microsoft we can find the line: 'microsoft' => [ 'client_id' => env ( 'MICROSOFT_CLIENT_ID' ), 'client_secret' => env ( 'MICROSOFT_CLIENT_SECRET' ), 'redirect' => env ( 'MICROSOFT_REDIRECT_URI' ) ], So our provider name is microsoft , write this down. For Okta we can find the line: 'okta' => [ 'base_url' => env ( 'OKTA_BASE_URL' ), 'client_id' => env ( 'OKTA_CLIENT_ID' ), 'client_secret' => env ( 'OKTA_CLIENT_SECRET' ), 'redirect' => env ( 'OKTA_REDIRECT_URI' ) ], So our provider name is okta , write this down. Register OAuth application Register a new application Now we need some values from the OAuth provider itself, in most cases you need to register a new \"OAuth application\" at the providers site. This will vary from provider to provider but the process itself should be similar to the examples below. Note The callback URL is always: https:// your-librenms-url /auth/ provider /callback It doesn't need to be a public available site, but it almost always needs to support TLS (https)! GitHub Microsoft Okta For our example with GitHub we go to GitHub Developer Settings and press \"Register a new application\": Fill out the form accordingly (with your own values): For our example with Microsoft we go to \"Azure Active Directory\" > \"App registrations\" and press \"New registration\" Fill out the form accordingly using your own values): Copy the value of the Application (client) ID and Directory (tenant) ID and save them, you will need them in the next step. For our example with Okta, we go to Applications>Create App Integration , Select OIDC - OpenID Connect , then Web Application . Fill in the Name, Logo, and Assignments based on your preferred settings. Leave the Sign-In Redirect URI field, this is where you will edit this later: Note your Okta domain or login url. Sometimes this can be a vanity url like login.company.com , or sometimes just company.okta.com . Click save. Generate a new client secret GitHub Microsoft Okta Press 'Generate a new client secret' to get a new client secret. Copy the Client ID and Client secret In the example above it is: Client ID : 7a41f1d8215640ca6b00 Client secret : ea03957288edd0e590be202b239e4f0ff26b8047 Select Certificates & secrets under Manage. Select the 'New client secret' button. Enter a value in Description and select one of the options for Expires and select 'Add'. Copy the client secret Value (not Secret ID!) before you leave this page. You will need it in the next step. This step is done for you when creating the app. All you have to do is copy down the client secret. You will need it in the next step. Saving configuration Now we need to set the configuration options for your provider within LibreNMS itself. Please replace the values in the examples below with the values you collected earlier: The format of the configuration string is auth.socialite.configs.*provider name*.*value* GitHub Microsoft Okta settings/auth/socialite lnms config:set auth.socialite.configs.github.client_id 7a41f1d8215640ca6b00 lnms config:set auth.socialite.configs.github.client_secret ea03957288edd0e590be202b239e4f0ff26b8047 settings/auth/socialite lnms config:set auth.socialite.configs.microsoft.client_id 7983ac13-c955-40e9-9b85-5ba27be52a52 lnms config:set auth.socialite.configs.microsoft.client_secret J9P7Q~K2F5C.L243sqzbGj.cOOcjTBgAPak_l lnms config:set auth.socialite.configs.microsoft.tenant a15edc05-152d-4eb4-973c-14f1fdc57d8b settings/auth/socialite lnms config:set auth.socialite.configs.okta.client_id 0oa1c08tti8D7xgXb697 lnms config:set auth.socialite.configs.okta.client_secret sWew90IKqKDmURj1XLsCPjXjre0U3zmJuFR6SzsG lnms config:set auth.socialite.configs.okta.base_url \"https://\" Add provider event listener The final step is to now add an event listener. Note It's important to copy exactly the right value here, It should begin with a \\ and end before the ::class.'@handle' GitHub Microsoft Okta Find the section looking like: protected $listen = [ \\SocialiteProviders\\Manager\\SocialiteWasCalled :: class => [ // ... other providers \\SocialiteProviders\\GitHub\\GitHubExtendSocialite :: class . '@handle' , ], ]; Copy the part: \\SocialiteProviders\\GitHub\\GitHubExtendSocialite and run; settings/auth/socialite lnms config:set auth.socialite.configs.github.listener \"\\SocialiteProviders\\GitHub\\GitHubExtendSocialite\" Don't forget the initial backslash (\\) ! Find the section looking like: protected $listen = [ \\SocialiteProviders\\Manager\\SocialiteWasCalled :: class => [ // ... other providers \\SocialiteProviders\\Microsoft\\MicrosoftExtendSocialite :: class . '@handle' , ], ]; Copy the part: \\SocialiteProviders\\Microsoft\\MicrosoftExtendSocialite and run; settings/auth/socialite lnms config:set auth.socialite.configs.microsoft.listener \"\\SocialiteProviders\\Microsoft\\MicrosoftExtendSocialite\" Don't forget the initial backslash (\\) ! Find the section looking like: protected $listen = [ \\SocialiteProviders\\Manager\\SocialiteWasCalled :: class => [ // ... other providers \\SocialiteProviders\\Okta\\OktaExtendSocialite :: class . '@handle' , ], ]; Copy the part: \\SocialiteProviders\\Okta\\OktaExtendSocialite and run; settings/auth/socialite lnms config:set auth.socialite.configs.okta.listener \"\\SocialiteProviders\\Okta\\OktaExtendSocialite\" Don't forget the initial backslack (\\) ! Now you are done with setting up the OAuth provider! If it doesn't work, please double check your configuration values by using the config:get command below. settings/auth/socialite lnms config:get auth.socialite Default Role Since most Socialite Providers don't provide Authorization only Authentication it is possible to set the default User Role for Authorized users. Appropriate care should be taken. none: No Access : User has no access normal: Normal User : You will need to assign device / port permissions for users at this level. global-read: Global Read : Read only Administrator. admin: Administrator : This is a global read/write admin account. settings/auth/socialite lnms config:set auth.socialite.default_role global-read Claims / Access Scopes Socialite can specifiy scopes that should be included with in the authentication request. (see Larvel docs ) For example, if Okta is configured to expose group information it is possible to use these group names to configure User Roles. First enable sending the 'groups' claim (along with the normal openid, profile, and email claims). Be aware that the scope name must match the claim name. For identity providers where the scope does not match (e.g. Keycloak: roles -> groups) you need to configure a custom scope. settings/auth/socialite lnms config:set auth.socialite.scopes.+ groups Then setup mappings from the returned claim arrays to the User levels you want settings/auth/socialite lnms config:set auth.socialite.claims.RETURN_FROM_CLAIM.roles '[\"admin\"]' lnms config:set auth.socialite.claims.OTHER_RETURN_FROM_CLAIM.roles '[\"global-read\",\"cleaner\"]' SAML2 Example Install plugin The first step is to install the plugin itself. lnms plugin:add socialiteproviders/saml2 Add configuration Depending on what your identity provider (Google, Azure, ...) supports, the configuration could look different from what you see next so please use this as a rough guide. It is up the IdP to provide the relevant details that you will need for configuration. Google Azure Go to https://admin.google.com/ac/apps/unified Press \"DOWNLOAD METADATA\" and save the file somewhere accessible by your LibreNMS server ACS URL = https:// your-librenms-url /auth/saml2/callback Entity ID = https:// your-librenms-url /auth/saml2 Name ID format = PERSISTANT Name ID = Basic Information > Primary email First name = http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname Last name = http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname Primary email = http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata \" $( cat /tmp/GoogleIDPMetadata.xml ) \" Alternatively, you can copy the content of the file and run it like so, this will result in the exact same result as above. settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata '''''' echo \"SESSION_SAME_SITE_COOKIE=none\" >> .env lnms plugin:add socialiteproviders/saml2 lnms config:set auth.socialite.redirect true lnms config:set auth.socialite.register true lnms config:set auth.socialite.configs.saml2.acs https://login.microsoftonline.com/xxxidfromazurexxx/saml2 lnms config:set auth.socialite.configs.saml2.entityid https://sts.windows.net/xxxidfromazurexxx/ lnms config:set auth.socialite.configs.saml2.certificate xxxcertinonelinexxx lnms config:set auth.socialite.configs.saml2.listener \"\\SocialiteProviders\\Saml2\\Saml2ExtendSocialite\" lnms config:set auth.socialite.configs.saml2.metadata https://nexus.microsoftonline-p.com/federationmetadata/saml20/federationmetadata.xml lnms config:set auth.socialite.configs.saml2.sp_default_binding_method urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST lnms config:clear Using an Identity Provider metadata URL Note This is the prefered and easiest way, if your IdP supports it! settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata https://idp.co/metadata/xml Using an Identity Provider metadata XML file settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata \" $( cat GoogleIDPMetadata.xml ) \" Manually configuring the Identity Provider with a certificate string settings/auth/socialite lnms config:set auth.socialite.configs.saml2.acs https://idp.co/auth/acs lnms config:set auth.socialite.configs.saml2.entityid http://saml.to/trust lnms config:set auth.socialite.configs.saml2.certificate MIIC4jCCAcqgAwIBAgIQbDO5YO.... Manually configuring the Identity Provider with a certificate file settings/auth/socialite lnms config:set auth.socialite.configs.saml2.acs https://idp.co/auth/acs lnms config:set auth.socialite.configs.saml2.entityid http://saml.to/trust lnms config:set auth.socialite.configs.saml2.certificate \" $( cat /path/to/certificate.pem ) \" Add provider event listener Now we just need to define the listener service within LibreNMS: settings/auth/socialite lnms config:set auth.socialite.configs.saml2.listener \"\\SocialiteProviders\\Saml2\\Saml2ExtendSocialite\" SESSION_SAME_SITE_COOKIE You most likely will need to set SESSION_SAME_SITE_COOKIE=none in .env if you use SAML2! If you get an error with http code 419, you should try to remove SESSION_SAME_SITE_COOKIE=none from your .env . Note Don't forget to run lnms config:clear after you modify .env to flush the config cache Service provider metadata Your identify provider might ask you for your Service Provider (SP) metadata. LibreNMS exposes all of this information from your LibreNMS install Troubleshooting If it doesn't work, please double check your configuration values by using the config:get command below. settings/auth/socialite lnms config:get auth.socialite Redirect URL If you have a need to, then you can override redirect url with the following commands: OAuth SAML2 Replace github and the relevant URL below with your identity provider details. lnms config:set auth.socialite.configs.github.redirect https://demo.librenms.org/auth/github/callback lnms config:set auth.socialite.configs.saml2.sp_acs auth/saml2/callback Post configuration settings settings/auth/socialite From here you can configure the settings for any identity providers you have configured along with some bespoke options. Redirect Login page: This setting will skip your LibreNMS login and take the end user straight to the first idP you configured. Allow registration via provider: If this setting is disabled, new users signing in via the idP will not be authenticated. This setting allows a local user to be automatically created which permits their login.","title":"Oauth/SAML support"},{"location":"Extensions/OAuth-SAML/#oauth-and-saml-support","text":"","title":"OAuth and SAML Support"},{"location":"Extensions/OAuth-SAML/#introduction","text":"LibreNMS has support for Laravel Socialite to try and simplify the use of OAuth 1 or 2 providers such as using GitHub, Microsoft, Twitter + many more and SAML. Socialite Providers supports more than 100+ 3rd parties so you will most likely find support for the SAML or OAuth provider you need without too much trouble. Please do note however, these providers are not maintained by LibreNMS so we cannot add support for new ones and we can only provide you basic help with general configuration. See the Socialite Providers website for more information on adding a new OAuth provider. Below we will guide you on how to install SAML or some of these OAth providers, you should be able to use these as a guide on how to install any others you may need but please, please, ensure you read the Socialite Providers documentation carefully . GitHub Provider Microsoft Provider Okta Provider SAML2","title":"Introduction"},{"location":"Extensions/OAuth-SAML/#requirements","text":"LibreNMS version 22.3.0 or later. Please ensure you set APP_URL within your .env file so that callback URLs work correctly with the identify provider. Note Once you have configured your OAuth or SAML2 provider, please ensure you check the Post configuration settings section at the end.","title":"Requirements"},{"location":"Extensions/OAuth-SAML/#github-and-microsoft-examples","text":"","title":"GitHub and Microsoft Examples"},{"location":"Extensions/OAuth-SAML/#install-plugin","text":"Note First we need to install the plugin itself. The plugin name can be slightly different so be sure to check the Socialite Providers documentation and look for this line, composer require socialiteproviders/github which will give you the name you need for the command, i.e: socialiteproviders/github . GitHub Microsoft Okta lnms plugin:add socialiteproviders/github lnms plugin:add socialiteproviders/microsoft lnms plugin:add socialiteproviders/okta","title":"Install plugin"},{"location":"Extensions/OAuth-SAML/#find-the-provider-name","text":"Next we need to find the provider name and writing it down Note It's almost always the name of the provider in lowercase but can be different so check the Socialite Providers documentation and look for this line, github => [ which will give you the name you need for the above command: github . GitHub Microsoft Okta For GitHub we can find the line: 'github' => [ 'client_id' => env ( 'GITHUB_CLIENT_ID' ), 'client_secret' => env ( 'GITHUB_CLIENT_SECRET' ), 'redirect' => env ( 'GITHUB_REDIRECT_URI' ) ], So our provider name is github , write this down. For Microsoft we can find the line: 'microsoft' => [ 'client_id' => env ( 'MICROSOFT_CLIENT_ID' ), 'client_secret' => env ( 'MICROSOFT_CLIENT_SECRET' ), 'redirect' => env ( 'MICROSOFT_REDIRECT_URI' ) ], So our provider name is microsoft , write this down. For Okta we can find the line: 'okta' => [ 'base_url' => env ( 'OKTA_BASE_URL' ), 'client_id' => env ( 'OKTA_CLIENT_ID' ), 'client_secret' => env ( 'OKTA_CLIENT_SECRET' ), 'redirect' => env ( 'OKTA_REDIRECT_URI' ) ], So our provider name is okta , write this down.","title":"Find the provider name"},{"location":"Extensions/OAuth-SAML/#register-oauth-application","text":"","title":"Register OAuth application"},{"location":"Extensions/OAuth-SAML/#register-a-new-application","text":"Now we need some values from the OAuth provider itself, in most cases you need to register a new \"OAuth application\" at the providers site. This will vary from provider to provider but the process itself should be similar to the examples below. Note The callback URL is always: https:// your-librenms-url /auth/ provider /callback It doesn't need to be a public available site, but it almost always needs to support TLS (https)! GitHub Microsoft Okta For our example with GitHub we go to GitHub Developer Settings and press \"Register a new application\": Fill out the form accordingly (with your own values): For our example with Microsoft we go to \"Azure Active Directory\" > \"App registrations\" and press \"New registration\" Fill out the form accordingly using your own values): Copy the value of the Application (client) ID and Directory (tenant) ID and save them, you will need them in the next step. For our example with Okta, we go to Applications>Create App Integration , Select OIDC - OpenID Connect , then Web Application . Fill in the Name, Logo, and Assignments based on your preferred settings. Leave the Sign-In Redirect URI field, this is where you will edit this later: Note your Okta domain or login url. Sometimes this can be a vanity url like login.company.com , or sometimes just company.okta.com . Click save.","title":"Register a new application"},{"location":"Extensions/OAuth-SAML/#generate-a-new-client-secret","text":"GitHub Microsoft Okta Press 'Generate a new client secret' to get a new client secret. Copy the Client ID and Client secret In the example above it is: Client ID : 7a41f1d8215640ca6b00 Client secret : ea03957288edd0e590be202b239e4f0ff26b8047 Select Certificates & secrets under Manage. Select the 'New client secret' button. Enter a value in Description and select one of the options for Expires and select 'Add'. Copy the client secret Value (not Secret ID!) before you leave this page. You will need it in the next step. This step is done for you when creating the app. All you have to do is copy down the client secret. You will need it in the next step.","title":"Generate a new client secret"},{"location":"Extensions/OAuth-SAML/#saving-configuration","text":"Now we need to set the configuration options for your provider within LibreNMS itself. Please replace the values in the examples below with the values you collected earlier: The format of the configuration string is auth.socialite.configs.*provider name*.*value* GitHub Microsoft Okta settings/auth/socialite lnms config:set auth.socialite.configs.github.client_id 7a41f1d8215640ca6b00 lnms config:set auth.socialite.configs.github.client_secret ea03957288edd0e590be202b239e4f0ff26b8047 settings/auth/socialite lnms config:set auth.socialite.configs.microsoft.client_id 7983ac13-c955-40e9-9b85-5ba27be52a52 lnms config:set auth.socialite.configs.microsoft.client_secret J9P7Q~K2F5C.L243sqzbGj.cOOcjTBgAPak_l lnms config:set auth.socialite.configs.microsoft.tenant a15edc05-152d-4eb4-973c-14f1fdc57d8b settings/auth/socialite lnms config:set auth.socialite.configs.okta.client_id 0oa1c08tti8D7xgXb697 lnms config:set auth.socialite.configs.okta.client_secret sWew90IKqKDmURj1XLsCPjXjre0U3zmJuFR6SzsG lnms config:set auth.socialite.configs.okta.base_url \"https://\"","title":"Saving configuration"},{"location":"Extensions/OAuth-SAML/#add-provider-event-listener","text":"The final step is to now add an event listener. Note It's important to copy exactly the right value here, It should begin with a \\ and end before the ::class.'@handle' GitHub Microsoft Okta Find the section looking like: protected $listen = [ \\SocialiteProviders\\Manager\\SocialiteWasCalled :: class => [ // ... other providers \\SocialiteProviders\\GitHub\\GitHubExtendSocialite :: class . '@handle' , ], ]; Copy the part: \\SocialiteProviders\\GitHub\\GitHubExtendSocialite and run; settings/auth/socialite lnms config:set auth.socialite.configs.github.listener \"\\SocialiteProviders\\GitHub\\GitHubExtendSocialite\" Don't forget the initial backslash (\\) ! Find the section looking like: protected $listen = [ \\SocialiteProviders\\Manager\\SocialiteWasCalled :: class => [ // ... other providers \\SocialiteProviders\\Microsoft\\MicrosoftExtendSocialite :: class . '@handle' , ], ]; Copy the part: \\SocialiteProviders\\Microsoft\\MicrosoftExtendSocialite and run; settings/auth/socialite lnms config:set auth.socialite.configs.microsoft.listener \"\\SocialiteProviders\\Microsoft\\MicrosoftExtendSocialite\" Don't forget the initial backslash (\\) ! Find the section looking like: protected $listen = [ \\SocialiteProviders\\Manager\\SocialiteWasCalled :: class => [ // ... other providers \\SocialiteProviders\\Okta\\OktaExtendSocialite :: class . '@handle' , ], ]; Copy the part: \\SocialiteProviders\\Okta\\OktaExtendSocialite and run; settings/auth/socialite lnms config:set auth.socialite.configs.okta.listener \"\\SocialiteProviders\\Okta\\OktaExtendSocialite\" Don't forget the initial backslack (\\) ! Now you are done with setting up the OAuth provider! If it doesn't work, please double check your configuration values by using the config:get command below. settings/auth/socialite lnms config:get auth.socialite","title":"Add provider event listener"},{"location":"Extensions/OAuth-SAML/#default-role","text":"Since most Socialite Providers don't provide Authorization only Authentication it is possible to set the default User Role for Authorized users. Appropriate care should be taken. none: No Access : User has no access normal: Normal User : You will need to assign device / port permissions for users at this level. global-read: Global Read : Read only Administrator. admin: Administrator : This is a global read/write admin account. settings/auth/socialite lnms config:set auth.socialite.default_role global-read","title":"Default Role"},{"location":"Extensions/OAuth-SAML/#claims-access-scopes","text":"Socialite can specifiy scopes that should be included with in the authentication request. (see Larvel docs ) For example, if Okta is configured to expose group information it is possible to use these group names to configure User Roles. First enable sending the 'groups' claim (along with the normal openid, profile, and email claims). Be aware that the scope name must match the claim name. For identity providers where the scope does not match (e.g. Keycloak: roles -> groups) you need to configure a custom scope. settings/auth/socialite lnms config:set auth.socialite.scopes.+ groups Then setup mappings from the returned claim arrays to the User levels you want settings/auth/socialite lnms config:set auth.socialite.claims.RETURN_FROM_CLAIM.roles '[\"admin\"]' lnms config:set auth.socialite.claims.OTHER_RETURN_FROM_CLAIM.roles '[\"global-read\",\"cleaner\"]'","title":"Claims / Access Scopes"},{"location":"Extensions/OAuth-SAML/#saml2-example","text":"","title":"SAML2 Example"},{"location":"Extensions/OAuth-SAML/#install-plugin_1","text":"The first step is to install the plugin itself. lnms plugin:add socialiteproviders/saml2","title":"Install plugin"},{"location":"Extensions/OAuth-SAML/#add-configuration","text":"Depending on what your identity provider (Google, Azure, ...) supports, the configuration could look different from what you see next so please use this as a rough guide. It is up the IdP to provide the relevant details that you will need for configuration. Google Azure Go to https://admin.google.com/ac/apps/unified Press \"DOWNLOAD METADATA\" and save the file somewhere accessible by your LibreNMS server ACS URL = https:// your-librenms-url /auth/saml2/callback Entity ID = https:// your-librenms-url /auth/saml2 Name ID format = PERSISTANT Name ID = Basic Information > Primary email First name = http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname Last name = http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname Primary email = http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata \" $( cat /tmp/GoogleIDPMetadata.xml ) \" Alternatively, you can copy the content of the file and run it like so, this will result in the exact same result as above. settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata '''''' echo \"SESSION_SAME_SITE_COOKIE=none\" >> .env lnms plugin:add socialiteproviders/saml2 lnms config:set auth.socialite.redirect true lnms config:set auth.socialite.register true lnms config:set auth.socialite.configs.saml2.acs https://login.microsoftonline.com/xxxidfromazurexxx/saml2 lnms config:set auth.socialite.configs.saml2.entityid https://sts.windows.net/xxxidfromazurexxx/ lnms config:set auth.socialite.configs.saml2.certificate xxxcertinonelinexxx lnms config:set auth.socialite.configs.saml2.listener \"\\SocialiteProviders\\Saml2\\Saml2ExtendSocialite\" lnms config:set auth.socialite.configs.saml2.metadata https://nexus.microsoftonline-p.com/federationmetadata/saml20/federationmetadata.xml lnms config:set auth.socialite.configs.saml2.sp_default_binding_method urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST lnms config:clear","title":"Add configuration"},{"location":"Extensions/OAuth-SAML/#using-an-identity-provider-metadata-url","text":"Note This is the prefered and easiest way, if your IdP supports it! settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata https://idp.co/metadata/xml","title":"Using an Identity Provider metadata URL"},{"location":"Extensions/OAuth-SAML/#using-an-identity-provider-metadata-xml-file","text":"settings/auth/socialite lnms config:set auth.socialite.configs.saml2.metadata \" $( cat GoogleIDPMetadata.xml ) \"","title":"Using an Identity Provider metadata XML file"},{"location":"Extensions/OAuth-SAML/#manually-configuring-the-identity-provider-with-a-certificate-string","text":"settings/auth/socialite lnms config:set auth.socialite.configs.saml2.acs https://idp.co/auth/acs lnms config:set auth.socialite.configs.saml2.entityid http://saml.to/trust lnms config:set auth.socialite.configs.saml2.certificate MIIC4jCCAcqgAwIBAgIQbDO5YO....","title":"Manually configuring the Identity Provider with a certificate string"},{"location":"Extensions/OAuth-SAML/#manually-configuring-the-identity-provider-with-a-certificate-file","text":"settings/auth/socialite lnms config:set auth.socialite.configs.saml2.acs https://idp.co/auth/acs lnms config:set auth.socialite.configs.saml2.entityid http://saml.to/trust lnms config:set auth.socialite.configs.saml2.certificate \" $( cat /path/to/certificate.pem ) \"","title":"Manually configuring the Identity Provider with a certificate file"},{"location":"Extensions/OAuth-SAML/#add-provider-event-listener_1","text":"Now we just need to define the listener service within LibreNMS: settings/auth/socialite lnms config:set auth.socialite.configs.saml2.listener \"\\SocialiteProviders\\Saml2\\Saml2ExtendSocialite\"","title":"Add provider event listener"},{"location":"Extensions/OAuth-SAML/#session_same_site_cookie","text":"You most likely will need to set SESSION_SAME_SITE_COOKIE=none in .env if you use SAML2! If you get an error with http code 419, you should try to remove SESSION_SAME_SITE_COOKIE=none from your .env . Note Don't forget to run lnms config:clear after you modify .env to flush the config cache","title":"SESSION_SAME_SITE_COOKIE"},{"location":"Extensions/OAuth-SAML/#service-provider-metadata","text":"Your identify provider might ask you for your Service Provider (SP) metadata. LibreNMS exposes all of this information from your LibreNMS install","title":"Service provider metadata"},{"location":"Extensions/OAuth-SAML/#troubleshooting","text":"If it doesn't work, please double check your configuration values by using the config:get command below. settings/auth/socialite lnms config:get auth.socialite","title":"Troubleshooting"},{"location":"Extensions/OAuth-SAML/#redirect-url","text":"If you have a need to, then you can override redirect url with the following commands: OAuth SAML2 Replace github and the relevant URL below with your identity provider details. lnms config:set auth.socialite.configs.github.redirect https://demo.librenms.org/auth/github/callback lnms config:set auth.socialite.configs.saml2.sp_acs auth/saml2/callback","title":"Redirect URL"},{"location":"Extensions/OAuth-SAML/#post-configuration-settings","text":"settings/auth/socialite From here you can configure the settings for any identity providers you have configured along with some bespoke options. Redirect Login page: This setting will skip your LibreNMS login and take the end user straight to the first idP you configured. Allow registration via provider: If this setting is disabled, new users signing in via the idP will not be authenticated. This setting allows a local user to be automatically created which permits their login.","title":"Post configuration settings"},{"location":"Extensions/Oxidized/","text":"Oxidized Integrating LibreNMS with Oxidized brings the following benefits: Config viewing: Current, History, and Diffs all under the Configs tab of each device Automatic addition of devices to Oxidized: Including filtering and grouping to ease credential management Configuration searching (Requires oxidized-web 0.8.0 or newer) First you will need to install Oxidized following their documentation . Then you can procede to the LibreNMS Web UI and go to Oxidized Settings in the External Settings section of Global Settings. Enable it and enter the url to your oxidized instance. To have devices automatically added, you will need to configure oxidized to pull them from LibreNMS Feeding Oxidized Note: this means devices will be controlled by the LibreNMS API, and not router.db, passwords will still need to be in the oxidized config file. LibreNMS will automatically map the OS to the Oxidized model name if they don't match. this means you shouldn't need to use the model_map config option within Oxidized. Detailed integration information This is a straight forward use of Oxidized, it relies on you having a working Oxidized setup which is already taking config snapshots for your devices. When you have that, you only need the following config to enable the display of device configs within the device page itself: external/oxidized lnms config:set oxidized.enabled true lnms config:set oxidized.url http://127.0.0.1:8888 LibreNMS supports config versioning if Oxidized does. This is known to work with the git output module. external/oxidized lnms config:set oxidized.features.versioning true Oxidized supports various ways to utilise credentials to login to devices, you can specify global username/password within Oxidized, Group level username/password or per device. LibreNMS currently supports sending groups back to Oxidized so that you can then define group credentials within Oxidized. To enable this support please switch on 'Enable the return of groups to Oxidized': external/oxidized lnms config:set oxidized.group_support true You can set a default group that devices will fall back to with: external/oxidized lnms config:set oxidized.default_group default You can ignore specific groups external/oxidized lnms config:set oxidized.ignore_groups '[\"badgroup\", \"nobackup\"]' One trick you can do to ignore all ungrouped devices is set both of these settings external/oxidized lnms config:set oxidized.default_group nobackup lnms config:set oxidized.ignore_groups.+ nobackup SELinux If you're running SELinux, you'll need to allow httpd to connect outbound to the network, otherwise Oxidized integration in the web UI will silently fail: setsebool -P httpd_can_network_connect 1 Feeding Oxidized Oxidized has support for feeding devices into it via an API call, support for Oxidized has been added to the LibreNMS API. A sample config for Oxidized is provided below. You will need to configure default credentials for your devices in the Oxidized config, LibreNMS doesn't provide login credentials at this time. source: default: http debug: false http: url: https://librenms/api/v0/oxidized map: name: hostname model: os group: group headers: X-Auth-Token: '01582bf94c03104ecb7953dsadsadwed' LibreNMS is able to reload the Oxidized list of nodes, each time a device is added to LibreNMS. To do so, edit the option in Global Settings>External Settings>Oxidized Integration or add the following to your config. external/oxidized lnms config:set oxidized.reload_nodes true Creating overrides To return an override to Oxidized you can do this by providing the override key, followed by matching a lookup for a host (or hosts), and finally by defining the overriding value itself. LibreNMS does not check for the validity of these attributes but will deliver them to Oxidized as defined. Matching of hosts can be done using hostname , sysname , os , location , sysDescr , hardware , purpose or notes and including either a 'match' key and value, or a 'regex' key and value. The order of matching is: hostname sysName sysDescr hardware os location ip purpose notes To match on the device hostnames or sysNames that contain 'lon-sw' or if the location contains 'London' then you would set the following: external/oxidized lnms config:set oxidized.maps.group.hostname.+ '{\"regex\": \"/^lon-sw/\", \"value\": \"london-switches\"}' lnms config:set oxidized.maps.group.sysName.+ '{\"regex\": \"/^lon-sw/\", \"value\": \"london-switches\"}' lnms config:set oxidized.maps.group.location.+ '{\"regex\": \"/london/\", \"value\": \"london-switches\"}' To match on a device os of edgeos then please use the following: external/oxidized lnms config:set oxidized.maps.group.os.+ '{\"match\": \"edgeos\", \"value\": \"wireless\"}' Matching on OS requires system name of the OS. For example, \"match\": \"RouterOS\" will not work, while \"match\": \"routeros\" will. To match on a device purpose or device notes that contains 'lon-net' then you would set the following: external/oxidized lnms config:set oxidized.maps.group.purpose.+ '{\"regex\": \"/^lon-sw/\", \"value\": \"london-network\"}' lnms config:set oxidized.maps.group.notes.+ '{\"regex\": \"/^lon-sw/\", \"value\": \"london-network\"}' To edit an existing map, you must use the index to override it. external/oxidized lnms config:get oxidized.maps.os.os [ { \"match\" : \"airos-af-ltu\" , \"value\" : \"airfiber\" } , { \"match\" : \"airos-af\" , \"value\" : \"airfiber\" } , ] lnms config:set oxidized.maps.os.os.1 '{\"match\": \"airos-af\", \"value\": \"something-else\"}' To override the IP Oxidized uses to poll the device, set the following: external/oxidized lnms config:set oxidized.maps.ip.sysName.+ '{\"regex\": \"/^my.node/\", \"value\": \"192.168.1.10\"}' lnms config:set oxidized.maps.ip.sysName.+ '{\"match\": \"my-other.node\", \"value\": \"192.168.1.20\"}' This allows extending the configuration further by providing a completely flexible model for custom flags and settings, for example, below shows the ability to add an ssh_proxy host within Oxidized simply by adding the below to your configuration: external/oxidized lnms config:set oxidized.maps.ssh_proxy.sysName.+ '{\"regex\": \"/^my.node/\", \"value\": \"my-ssh-gateway.node\"}' Or of course, any custom value that could be needed or wanted can be applied, for example, setting a \"myAttribute\" to \"Super cool value\" for any configured and enabled \"routeros\" device. external/oxidized lnms config:set oxidized.maps.myAttribute.os.+ '{\"match\": \"routeros\", \"value\": \"Super cool value\"}' Verify the return of groups by querying the API: curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/oxidized If you need to, you can specify credentials for groups by using the following in your Oxidized config: groups: : username: password: Miscellaneous If you have devices which you do not wish to appear in Oxidized then you can edit those devices in Device -> Edit -> Misc and enable \"Exclude from Oxidized?\" The use of custom ssh and telnet ports can be set through device settings misc tab, and can be passed on to oxidized with the following vars_map source: http: map: name: hostname model: os group: group vars_map: ssh_port: ssh_port telnet_port: telnet_port It's also possible to exclude certain device types and OS' from being output via the API. external/oxidized lnms config:set oxidized.ignore_types '[\"server\", \"power\"]' lnms config:set oxidized.ignore_os '[\"linux\", \"windows\"]' You can also ignore whole groups of devices external/oxidized lnms config:set oxidized.ignore_groups '[\"london-switches\", \"default\"]' Trigger configuration backups Using the Oxidized REST API and Syslog Hooks , Oxidized can trigger configuration downloads whenever a configuration change event has been logged. An example script to do this is included in ./scripts/syslog-notify-oxidized.php . Oxidized can spawn a new worker thread and perform the download immediately with the following configuration next_adds_job: true Validate Oxidized config You can perform basic validation of the Oxidized configuration by going to the Overview -> Tools -> Oxidized link and in the Oxidized config validation page, paste your yaml file into the input box and click 'Validate YAML'. We check for yaml syntax errors and also actual config values to ensure they are used in the correct location. Accessing configuration of a disabled/removed device When you're disabling or removing a device from LibreNMS, the configuration will no longer be available via the LibreNMS web interface. You can gain access to these configurations directly in the Git repository of Oxidized (if using Git for version control). 1: Check in your Oxidized where are stored your Git repositories: /home/oxidized/.config/oxidized/config 2: Go the correct Git repository for the needed device (the .git one) and get the list of devices using this command: git ls-files -s 3: Save the object ID of the device, and run the command to get the file content: git cat-file -p