LibreNMS is an auto-discovering network monitoring system with support for SNMP, OS monitoring, and alerting. As a system that interacts with network devices and stores sensitive configuration data, proper security hardening is essential. This guide covers security measures for production LibreNMS deployments.
LibreNMS architecture includes multiple security-sensitive components:
Key security concerns include SNMP credential protection, API access control, web interface security, and database protection.
Configure firewall rules for LibreNMS:
# LibreNMS Web Interface (Nginx/Apache)
ufw allow from 10.0.0.0/8 to any port 80 proto tcp
ufw allow from 10.0.0.0/8 to any port 443 proto tcp
# SNMP (for polling devices)
ufw allow out to any port 161 proto udp
ufw allow out to any port 162 proto udp # SNMP traps
# MySQL (restrict to localhost)
ufw allow from 127.0.0.1 to any port 3306 proto tcp
# Redis (if used for caching)
ufw allow from 127.0.0.1 to any port 6379 proto tcp
# Block external access to management ports
ufw deny from any to any port 3306 proto tcp
ufw deny from any to any port 6379 proto tcp
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: librenms-network-policy
spec:
podSelector:
matchLabels:
app: librenms
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 161
- protocol: UDP
port: 162
Configure Nginx binding for LibreNMS:
# /etc/nginx/sites-available/librenms
server {
listen 10.0.1.100:443 ssl http2;
server_name librenms.company.com;
root /opt/librenms/html;
ssl_certificate /etc/nginx/certs/librenms.crt;
ssl_certificate_key /etc/nginx/certs/librenms.key;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Configure SNMP source interface:
# /opt/librenms/config.php
$config['snmp']['transport'] = 'udp';
$config['snmp']['timeout'] = 2;
$config['snmp']['retries'] = 3;
Configure LibreNMS authentication:
// /opt/librenms/config.php
// Two-factor authentication
$config['auth_mechanism'] = 'mysql'; // or 'ldap', 'active_directory'
// Session security
$config['session_lifetime'] = 3600;
$config['session_secure'] = true;
$config['session_httponly'] = true;
// Password policy
$config['password_min_length'] = 12;
$config['password_require_uppercase'] = true;
$config['password_require_lowercase'] = true;
$config['password_require_number'] = true;
$config['password_require_special'] = true;
Configure LibreNMS user roles:
// /opt/librenms/config.php
// User permissions
$config['user_groups'] = [
'admin' => [
'global_read' => true,
'global_write' => true,
'admin' => true,
],
'operator' => [
'global_read' => true,
'global_write' => false,
'admin' => false,
],
'viewer' => [
'global_read' => true,
'global_write' => false,
'admin' => false,
],
];
Configure LDAP authentication:
// /opt/librenms/config.php
$config['auth_mechanism'] = 'ldap';
$config['ldap_server'] = 'ldap.company.com';
$config['ldap_port'] = 636;
$config['ldap_version'] = 3;
$config['ldap_starttls'] = false;
$config['ldap_userdn'] = 'cn=admin,dc=company,dc=com';
$config['ldap_password'] = '${LDAP_PASSWORD}';
$config['ldap_basedn'] = 'dc=company,dc=com';
$config['ldap_group'] = 'cn=librenms-users,ou=groups,dc=company,dc=com';
$config['ldap_uid_attribute'] = 'uid';
$config['ldap_fullname_attribute'] = 'cn';
Configure AD authentication:
// /opt/librenms/config.php
$config['auth_mechanism'] = 'active_directory';
$config['ad_domain'] = 'company.com';
$config['ad_url'] = 'ldaps://dc.company.com';
$config['ad_binddn'] = 'cn=librenms,ou=services,dc=company,dc=com';
$config['ad_bindpw'] = '${AD_PASSWORD}';
$config['ad_basedn'] = 'dc=company,dc=com';
$config['ad_userattr'] = 'sAMAccountName';
$config['ad_group'] = 'LibreNMS-Users';
Enable two-factor authentication:
// /opt/librenms/config.php
$config['two_factor'] = true;
$config['two_factor_mandatory'] = true; // For admin users
$config['two_factor_mandatory_groups'] = ['admin', 'operator'];
Configure HTTPS for LibreNMS:
# /etc/nginx/sites-available/librenms
server {
listen 443 ssl http2;
server_name librenms.company.com;
root /opt/librenms/html;
ssl_certificate /etc/nginx/certs/librenms.crt;
ssl_certificate_key /etc/nginx/certs/librenms.key;
ssl_trusted_certificate /etc/nginx/certs/ca-bundle.crt;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src * data:; font-src 'self' data:; connect-src 'self'" always;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Use SNMPv3 for secure device polling:
// /opt/librenms/config.php
// SNMPv3 default credentials
$config['snmpv3_default'] = [
'authlevel' => 'authPriv',
'authname' => 'librenms-user',
'authpass' => '${SNMP_AUTH_PASSWORD}',
'authalgo' => 'SHA',
'privpass' => '${SNMP_PRIV_PASSWORD}',
'privalgo' => 'AES',
];
// Per-device SNMPv3
$config['override_sysLocation'] = false;
Configure SNMPv3 on network devices:
# Cisco example
snmp-server group MONITORING v3 priv
snmp-server user librenms-user MONITORING v3 auth sha ${SNMP_AUTH_PASSWORD} priv aes 128 ${SNMP_PRIV_PASSWORD}
Configure TLS for MySQL:
// /opt/librenms/config.php
$config['db_server'] = 'localhost';
$config['db_port'] = 3306;
$config['db_name'] = 'librenms';
$config['db_user'] = 'librenms';
$config['db_pass'] = '${DB_PASSWORD}';
$config['db_ssl'] = true;
$config['db_ssl_ca'] = '/etc/mysql/ca.crt';
$config['db_ssl_cert'] = '/etc/mysql/client.crt';
$config['db_ssl_key'] = '/etc/mysql/client.key';
Secure LibreNMS API access:
| Endpoint | Risk Level | Access Control |
|---|---|---|
GET /api/v0/devices |
Low | Authenticated users |
GET /api/v0/ports |
Low | Authenticated users |
POST /api/v0/devices |
High | Admin only |
DELETE /api/v0/devices |
High | Admin only |
GET /api/v0/users |
Medium | Admin only |
POST /api/v0/bills |
Medium | Admin only |
Generate API tokens:
# Create API token
./lnms user:apikey:add --username=admin --description="Monitoring Integration"
# Use token
curl -X GET \
-H "X-Auth-Token: ${API_TOKEN}" \
https://librenms.company.com/api/v0/devices
Configure PHP security settings:
# /etc/php/8.1/fpm/php.ini
expose_php = Off
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Strict
session.use_strict_mode = 1
session.gc_maxlifetime = 3600
Never use default community strings:
// /opt/librenms/config.php
// Bad - Never use default strings
// $config['snmp']['community'] = 'public';
// Good - Use SNMPv3 or unique community strings
$config['snmp']['community'] = '${UNIQUE_COMMUNITY_STRING}';
// Per-device credentials
$config['devices']['hostname'] = [
'snmpver' => 'v3',
'authlevel' => 'authPriv',
'authname' => 'librenms-user',
'authpass' => '${SNMP_AUTH_PASSWORD}',
'privpass' => '${SNMP_PRIV_PASSWORD}',
];
Restrict device management access:
// /opt/librenms/config.php
// Device permissions
$config['device_groups'] = [
'core' => [
'admin_access' => ['admin-group'],
'read_access' => ['admin-group', 'operator-group'],
],
'access' => [
'admin_access' => ['admin-group'],
'read_access' => ['admin-group', 'operator-group', 'viewer-group'],
],
];
Secure LibreNMS database:
-- Create dedicated database user
CREATE USER 'librenms'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON librenms.* TO 'librenms'@'localhost';
GRANT CREATE TEMPORARY TABLES ON librenms.* TO 'librenms'@'localhost';
FLUSH PRIVILEGES;
-- Enable SSL requirement
ALTER USER 'librenms'@'localhost' REQUIRE SSL;
Implement database encryption:
-- Enable TDE (MySQL Enterprise)
ALTER TABLE devices ENCRYPTION='Y';
ALTER TABLE ports ENCRYPTION='Y';
ALTER TABLE sensors ENCRYPTION='Y';
Secure RRD files:
# Set restrictive permissions on RRD directory
chown -R librenms:librenms /opt/librenms/rrd
chmod -R 750 /opt/librenms/rrd
# Use encrypted filesystem for RRD storage
# Mount /opt/librenms/rrd on encrypted volume
Secure sensitive configuration:
// /opt/librenms/config.php
// Use environment variables
$config['db_pass'] = getenv('LIBRENMS_DB_PASSWORD');
$config['snmp']['community'] = getenv('LIBRENMS_SNMP_COMMUNITY');
// Or use external secrets file
if (file_exists('/etc/librenms/secrets.php')) {
include '/etc/librenms/secrets.php';
}
Protect secrets file:
# Set restrictive permissions
chown root:librenms /etc/librenms/secrets.php
chmod 640 /etc/librenms/secrets.php
Secure device credentials:
// /opt/librenms/config.php
// Encrypt stored credentials
$config['credentials_encryption'] = true;
$config['credentials_encryption_key'] = '${ENCRYPTION_KEY}';
Enable audit logging:
// /opt/librenms/config.php
$config['audit_log'] = true;
$config['audit_log_purge'] = 365; // Days to retain
Monitor audit logs:
# View audit log
./lnms logs:tail --type=audit
# Export audit log
./lnms logs:export --type=audit --output=/var/log/librenms/audit.log
Configure web server access logging:
# /etc/nginx/sites-available/librenms
access_log /var/log/nginx/librenms_access.log combined;
error_log /var/log/nginx/librenms_error.log warn;
# Log format with timing
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time';
Create LibreNMS alerts for security events:
// /opt/librenms/config.php
// Alert on failed login attempts
$config['alert']['failed_login'] = [
'enabled' => true,
'threshold' => 5,
'window' => 300, // seconds
'contacts' => ['security-team'],
];
// Alert on configuration changes
$config['alert']['config_change'] = [
'enabled' => true,
'contacts' => ['ops-team'],
];
// Alert on new device discovery
$config['alert']['new_device'] = [
'enabled' => true,
'contacts' => ['network-team'],
];
Forward logs to SIEM:
# /etc/rsyslog.d/librenms.conf
:programname, isequal, "librenms" /var/log/librenms/syslog.log
:programname, isequal, "librenms" @siem.company.com:514