Ansible Role linuxfabrik.lfops.librenms¶
This role installs and configures LibreNMS.
Available since LFOps 2.0.0.
How the Role Behaves¶
The role installs LibreNMS from a git checkout on the target host, not on the Ansible controller, and checks out the latest upstream release on every run. The version is not pinned, so a run updates an existing installation to whatever upstream currently offers. Between runs LibreNMS keeps itself up to date as well: the cron jobs are the ones upstream ships, and their nightly daily.sh updates the code on its own. librenms__config_update_channel selects the channel it follows.
librenms__url is the one place the address of the instance is configured. The role writes it to base_url in /opt/librenms/config.php, which overrides the URL LibreNMS otherwise detects from each request, and to APP_URL in /opt/librenms/.env, which Laravel uses wherever there is no request to detect from, alert notifications above all. Both are needed: LibreNMS builds part of its links itself and leaves the rest to Laravel. Note that base_url ties the instance to that address, so opening the web interface under a different name makes the built-in validation fail rather than only warn. config.php outranks the config database table, so a base_url set through the web interface or lnms config:set on an existing host is masked from the next run onwards.
The Python packages LibreNMS lists in its requirements.txt are installed with pip into the user site of the librenms user, /opt/librenms/.local. That is where LibreNMS looks for them itself: its nightly daily.sh runs the same pip call, and the requirements check behind validate.php reads the installed distribution metadata from there. Distribution packages cannot cover this, because no RHEL release ships command_runner and the psutil of RHEL 8 and 9 is older than LibreNMS requires. On RHEL 8 the role installs a current pip into that same user site first, since the pip of the distribution cannot use the prebuilt psutil wheel and would need a compiler on the host to build it. A host that carries such packages from an earlier manual pip install as root keeps them; they are outranked by the user site for LibreNMS, but pip3 uninstall as root is worth running once so only one place provides them.
LibreNMS stores its time series in RRD files below /opt/librenms/rrd. By default the role puts RRDCached in front of them, which collects the updates of a poll cycle in memory and writes them out every 30 minutes instead of on every update. This typically cuts the disk I/O of the poller by 30% to 40%.
- The RRD files stay where they are and keep their format, so enabling or disabling RRDCached needs no data migration. Only who writes them changes.
- RRDCached runs as
librenmsand listens on the Unix socket/run/rrdcached.sock. It is not reachable over the network, and the socket is deliberately not in/tmp, whichhttpdandphp-fpmcannot see because both run withPrivateTmp=true. - The role configures the
rrdcached.serviceof therrdtoolpackage with a systemd drop-in and disables therrdcached.socketunit shipped alongside it, because socket activation would make RRDCached ignore the configured socket path. - On RHEL-compatible systems RRDCached needs the
rrdcached_librenmsSELinux policy module, without which it cannot write the RRD files and the web interface cannot draw graphs. The module is declared inlibrenms__selinux__modules__dependent_varand deployed by theselinuxrole, so skipping that role in the playbook leaves RRDCached without it. - Up to 30 minutes of collected data live in memory only. RRDCached journals them to
/var/tmpand replays the journal after a crash. - Setting
librenms__rrdcached_enabledtofalsestops and disablesrrdcached.service, which flushes the collected data to the RRD files on the way out, and points LibreNMS at the files directly. The systemd drop-in, therrdcached_librenmsSELinux policy module and the RRD files themselves stay in place, so the switch can be reversed with another run of the role.
Dependent Roles¶
Any LFOps playbook that installs this role runs these for you. Optional ones can be disabled via the playbook's skip variables.
- Python 3, and the python3-policycoreutils module (required for the SELinux Ansible tasks) must be installed (role: linuxfabrik.lfops.policycoreutils).
- MariaDB must be installed, with a database and a user for said database created (role: linuxfabrik.lfops.mariadb_server).
- A web server (for example Apache httpd) must be installed, with a virtual host for LibreNMS configured (role: linuxfabrik.lfops.apache_httpd).
- PHP version >= 8.4 must be installed (role: linuxfabrik.lfops.php).
- The Python modules the poller and the discovery need must be installed (have a look at
librenms__python__modules__dependent_varin thedefaults/main.yml) (role: linuxfabrik.lfops.python). - On RHEL-compatible systems, the SELinux booleans in
librenms__selinux__booleans__dependent_varmust be enabled (role: linuxfabrik.lfops.selinux). - On RHEL-compatible systems, the appropriate SELinux file contexts must be set (have a look at
librenms__selinux__fcontexts__dependent_varin thedefaults/main.yml) (role: linuxfabrik.lfops.selinux). - On RHEL-compatible systems, the
http_fpingandrrdcached_librenmsSELinux policy modules must be installed (have a look atlibrenms__selinux__modules__dependent_varin thedefaults/main.yml) (role: linuxfabrik.lfops.selinux).
Requirements¶
- Outbound HTTPS access from the target host to
github.com, both for the release lookup and for the git checkout, topackagist.orgfor the PHP dependencies Composer installs, and topypi.organdfiles.pythonhosted.orgfor the Python packagespipinstalls. The role does no downloading on the Ansible controller.
Post-Installation Steps¶
- The role prepares the database credentials in
/opt/librenms/.env, but creates neither the database schema nor an account to log in with. Open<librenms__url>/installand follow the web installer, which does both. An administrator can also be added on the host withlnms user:add <username>.
Tags¶
librenms
- Installs and configures LibreNMS.
- Triggers: rrdcached.service restart.
librenms:configure
- Deploys the LibreNMS configuration, the scheduled jobs and the logrotate configuration.
- Triggers: none.
librenms:cron
- Deploys the cron jobs and the units of the LibreNMS scheduler.
- Triggers: none.
librenms:logrotate
- Deploys the logrotate configuration.
- Triggers: none.
librenms:rrdcached
- Installs and configures RRDCached, and manages its service.
- Triggers: rrdcached.service restart.
librenms:state
- Manages the state of the LibreNMS scheduler timer (start, stop, enable, disable).
- Triggers: none.
Mandatory Role Variables¶
librenms__database_login
- The user account for accessing the MySQL database.
- Type: Dictionary.
-
Subkeys:
-
username:- Mandatory. The database user.
- Type: String.
-
password:- Mandatory. The password of the database user.
- Type: String.
-
librenms__url
- The URL under which LibreNMS is reachable, including the scheme and, where applicable, a port or a subdirectory. It is the single source for three settings: the
ServerNameof the vHost gets its host part,APP_URLin/opt/librenms/.envandbase_urlin/opt/librenms/config.phpget the URL itself. Use the URL your users type in the browser, which with a TLS-terminating reverse proxy in front is anhttps://URL even though Apache httpd on the host serves plain HTTP. - Type: String.
Example:
# mandatory
librenms__database_login:
username: 'librenms'
password: 'linuxfabrik'
librenms__url: 'https://librenms.example.com'
Optional Role Variables¶
librenms__config_app_trusted_proxies
- A list of trusted reverse proxy IPs or CIDR ranges, joined into the comma separated
APP_TRUSTED_PROXIESsetting in/opt/librenms/.env, and written on every run. Have a look at https://docs.librenms.org/Support/Environment-Variables/. The empty default trusts no proxy at all, so LibreNMS ignores theX-Forwarded-*headers of any host: list your proxy here if one sits in front of LibreNMS, otherwise client addresses and the detected protocol are those of the proxy. Have a look at "Troubleshooting" below for how to check what a running instance makes of the setting. - Type: List.
- Default:
[] - Deviates from the upstream default
127.0.0.1: a proxy on the LibreNMS host itself is not the common case in LFOps, and a host that trusts one accepts spoofedX-Forwarded-Forheaders from anything able to reach it locally.
librenms__config_auth_mechanism
- Which authentication mechanism LibreNMS should use. Have a look at https://docs.librenms.org/Extensions/Authentication/. Note that only one mechanism can be active at the same time. Possible options:
active_directory,http-auth,ldap,ldap-authorization,mysql,sso. - Type: String.
- Default:
'mysql'
librenms__config_rrd_purge
- Number in days of how long to keep old rrd files.
0disables this feature. - Type: Number.
- Default:
0
librenms__config_session_secure_cookie
- Whether LibreNMS marks its session cookie as secure, so a browser only sends it over HTTPS. Sets
SESSION_SECURE_COOKIEin/opt/librenms/.envon every run. Defaults totrueas soon aslibrenms__urlnames anhttps://URL, which is the host's own statement that it serves HTTPS. Do not set it totrueon a host that is reachable over plain HTTP only: the browser then never sends the cookie back and the login fails with "419 Page Expired". LibreNMS is a Laravel application and issues this cookie itself, sophp__ini_session_cookie_secureof thephprole does not reach it. - Type: Boolean.
- Default:
trueiflibrenms__urlstarts withhttps://, elsefalse
librenms__config_update_channel
- Which update channel LibreNMS should use during automatic updates. Possible options:
master,release. - Type: String.
- Default:
'release'
librenms__database_host
- The host on which the MySQL database is reachable.
- Type: String.
- Default:
'localhost'
librenms__database_name
- The name of the SQL database.
- Type: String.
- Default:
'librenms'
librenms__rrdcached_enabled
- Whether LibreNMS reads and writes its RRD files through RRDCached. Set this to
falseto stop and disable RRDCached and have LibreNMS access the files directly. Have a look at "How the Role Behaves" above. - Type: Boolean.
- Default:
true - Deviates from the upstream default
false: LibreNMS writes every RRD file on every poll cycle without it, which is the bulk of the disk I/O of a poller and the first thing to hurt once a host monitors more than a handful of devices.
librenms__rrdcached_service_enabled
- Enables or disables the RRDCached service, analogous to
systemctl enable/disable --now. Only used iflibrenms__rrdcached_enabledistrue. - Type: Bool.
- Default:
true
librenms__rrdcached_service_state
- Changes the state of the RRDCached service, analogous to
systemctl start/stop/restart/reload. Only used iflibrenms__rrdcached_enabledistrue. - Type: String. One of
reloaded,restarted,started,stopped. - Default:
'started'iflibrenms__rrdcached_service_enabledistrue, else'stopped'
librenms__scheduler_service_enabled
- Enables or disables the timer of the LibreNMS scheduler, analogous to
systemctl enable/disable --now. The scheduler runs the maintenance and alerting jobs of LibreNMS. - Type: Bool.
- Default:
true
librenms__scheduler_service_state
- Changes the state of the timer of the LibreNMS scheduler, analogous to
systemctl start/stop/restart/reload. - Type: String. One of
reloaded,restarted,started,stopped. - Default:
'started'iflibrenms__scheduler_service_enabledistrue, else'stopped'
Example:
# optional
librenms__config_app_trusted_proxies:
- '192.0.2.0/24'
- '198.51.100.7'
librenms__config_auth_mechanism: 'mysql'
librenms__config_rrd_purge: 730
librenms__config_session_secure_cookie: true
librenms__config_update_channel: 'release'
librenms__database_host: 'localhost'
librenms__database_name: 'librenms'
librenms__rrdcached_enabled: true
librenms__rrdcached_service_enabled: true
librenms__rrdcached_service_state: 'started'
librenms__scheduler_service_enabled: true
librenms__scheduler_service_state: 'started'
Troubleshooting¶
Logs and access control show the address of the reverse proxy instead of the client's
- LibreNMS honours the
X-Forwarded-*headers only from an address listed inlibrenms__config_app_trusted_proxies, and the empty default trusts none. To check what a running instance does, log in through the proxy and open "Auth History" under Settings in the web interface: the "IP Address" column of the top row is the address LibreNMS derived from the request, so it has to show the client and not the proxy. Reading that page requires the admin or the global-read role. - To confirm that a host which is not listed cannot forge an address, repeat the login from such a host with an
X-Forwarded-Forheader of its own. The row in "Auth History" has to carry that host's own address; if it carries the forged one, the host is trusted. sudo -u librenms lnms config:show trustedproxyprints the list as the application resolved it. This tells an unsetAPP_TRUSTED_PROXIES, where LibreNMS falls back to trusting127.0.0.1, apart from one that is deliberately empty.