Zabbix is an enterprise-grade monitoring solution with multiple components including server, web frontend, database, proxies, and agents. Each tier requires specific security hardening to protect the monitoring infrastructure. This guide covers security measures for production Zabbix deployments.
Zabbix architecture consists of multiple security boundaries:
Key security concerns include agent authentication, API access control, database security, and frontend protection.
Configure firewall rules for Zabbix components:
# Zabbix Server
ufw allow from 10.0.0.0/8 to any port 10051 proto tcp # Server port
ufw allow from 10.0.0.0/8 to any port 10050 proto tcp # Agent checks
# Zabbix Frontend (Apache/Nginx)
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
# Database (restrict to server only)
ufw allow from 127.0.0.1 to any port 5432 proto tcp # PostgreSQL
ufw allow from 127.0.0.1 to any port 3306 proto tcp # MySQL
# Block external access
ufw deny from any to any port 10050 proto tcp
ufw deny from any to any port 10051 proto tcp
Network Architecture:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Public Zone │ │ DMZ Zone │ │ Internal Zone │
│ │ │ │ │ │
│ External Hosts │───▶│ Zabbix Proxy │───▶│ Zabbix Server │
│ (Internet) │ │ (Limited Access)│ │ + Database │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Configure Zabbix to bind to specific interfaces:
# /etc/zabbix/zabbix_server.conf
ListenIP=10.0.1.100
ListenPort=10051
# /etc/zabbix/zabbix_agentd.conf
Server=10.0.1.100
ServerActive=10.0.1.100
ListenIP=0.0.0.0
ListenPort=10050
For web frontend, configure Apache/Nginx binding:
# Apache configuration
<VirtualHost 10.0.1.100:443>
ServerName zabbix.company.com
# ... SSL configuration
</VirtualHost>
Configure secure user settings in Zabbix:
# /etc/zabbix/web/zabbix.conf.php
$ZBX_SERVER = 'localhost';
$ZBX_SERVER_PORT = '10051';
$ZBX_SERVER_NAME = 'Zabbix Server';
# Session security
$SESSION_COOKIE_LIFETIME = 3600;
$SESSION_COOKIE_SECURE = true;
$SESSION_COOKIE_HTTPONLY = true;
Zabbix provides granular role-based permissions:
| Role Type | Permissions |
|---|---|
| User | Read-only access to assigned hosts |
| Admin | Full configuration access, no user management |
| Super Admin | Complete system access including user management |
Configure user roles:
Implement least-privilege access:
Permission Levels:
- Read: View hosts, triggers, graphs
- Read/Write: Modify configurations
- Deny: Explicit access denial
SAML Authentication:
# Enable SAML in zabbix.conf.php
$SSO_ENABLED = true;
$SSO_SAML_IDP_ENTITYID = 'https://sso.company.com/saml';
$SSO_SAML_SP_ENTITYID = 'zabbix';
$SSO_SAML_ACS_URL = 'https://zabbix.company.com/saml/acs';
$SSO_SAML_SLO_URL = 'https://sso.company.com/saml/slo';
LDAP Authentication:
# /etc/zabbix/web/zabbix.conf.php
$LDAP_ENABLED = true;
$LDAP_HOST = 'ldap.company.com';
$LDAP_PORT = 636;
$LDAP_BASE_DN = 'dc=company,dc=com';
$LDAP_BIND_DN = 'cn=zabbix,ou=services,dc=company,dc=com';
$LDAP_BIND_PASSWORD = '${LDAP_PASSWORD}';
$LDAP_SEARCH_ATTRIBUTE = 'uid';
Enable two-factor authentication:
# In Zabbix frontend: Administration → Authentication
# Enable "Two-factor authentication"
# Configure TOTP or SMS providers
For API access, use token-based authentication:
# Create API token
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"username": "admin",
"password": "password"
},
"id": 1
}' \
http://zabbix.company.com/api_jsonrpc.php
Configure HTTPS for Zabbix frontend:
# Apache SSL configuration
<VirtualHost *:443>
ServerName zabbix.company.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/zabbix.crt
SSLCertificateKeyFile /etc/ssl/private/zabbix.key
SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder on
# Security headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
</VirtualHost>
Enable TLS for agent communications:
# /etc/zabbix/zabbix_agentd.conf
TLSConnect=psk
TLSAccept=psk
TLSPSKIdentity=PSK001
TLSPSKFile=/etc/zabbix/zabbix_agentd.psk
# Or with certificates
TLSConnect=cert
TLSAccept=cert
TLSCAFile=/etc/zabbix/ssl/ca.crt
TLSCertFile=/etc/zabbix/ssl/agent.crt
TLSKeyFile=/etc/zabbix/ssl/agent.key
Configure TLS on Zabbix Server:
# /etc/zabbix/zabbix_server.conf
TLSConnect=cert
TLSAccept=cert
TLSCAFile=/etc/zabbix/ssl/ca.crt
TLSCertFile=/etc/zabbix/ssl/server.crt
TLSKeyFile=/etc/zabbix/ssl/server.key
Secure proxy-to-server communication:
# /etc/zabbix/zabbix_proxy.conf
TLSConnect=cert
TLSAccept=cert
TLSCAFile=/etc/zabbix/ssl/ca.crt
TLSCertFile=/etc/zabbix/ssl/proxy.crt
TLSKeyFile=/etc/zabbix/ssl/proxy.key
Secure Zabbix API access:
| API Method | Risk Level | Access Control |
|---|---|---|
host.get |
Low | Authenticated users |
item.get |
Low | Authenticated users |
trigger.get |
Low | Authenticated users |
host.create |
High | Admin only |
user.create |
High | Super Admin only |
config.import |
Critical | Super Admin only |
script.execute |
Critical | Admin only |
Implement API rate limiting:
# Nginx rate limiting for API
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
location /api_jsonrpc.php {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://zabbix-frontend;
}
Configure security settings:
# /etc/zabbix/web/zabbix.conf.php
// Session settings
$SESSION_COOKIE_LIFETIME = 3600;
$SESSION_COOKIE_SECURE = true;
$SESSION_COOKIE_HTTPONLY = true;
$SESSION_COOKIE_SAMESITE = 'Strict';
// Disable unnecessary features
$ENABLE_HTTP_AUTH = false;
$ENABLE_SAML = false; // Unless using SAML
// CSP headers
$CSP_ENABLED = true;
Restrict remote command execution:
# /etc/zabbix/zabbix_server.conf
# Disable remote commands by default
EnableRemoteCommands=0
# For specific hosts, enable via frontend:
# Configuration → Hosts → [Host] → Templates → Macros
# Add: {$ENABLE_REMOTE_COMMANDS}=1
Secure Zabbix database:
-- Create dedicated database user with minimal privileges
CREATE USER zabbix@localhost IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON zabbix.* TO zabbix@localhost;
-- Do NOT grant DROP, ALTER, or CREATE privileges
-- Enable database encryption
ALTER USER zabbix@localhost REQUIRE SSL;
Implement database encryption:
PostgreSQL:
-- Enable pgcrypto extension
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Encrypt sensitive columns
UPDATE users SET passwd = crypt('password', gen_salt('bf'));
MySQL:
-- Enable TDE (Enterprise Edition)
ALTER TABLE users ENCRYPTION='Y';
Secure sensitive configuration:
# /etc/zabbix/web/zabbix.conf.php
$DB['PASSWORD'] = getenv('ZABBIX_DB_PASSWORD');
# /etc/zabbix/zabbix_agentd.conf
# Use external secret management
Include=/etc/zabbix/zabbix_agentd.d/*.conf
For Kubernetes deployments:
apiVersion: v1
kind: Secret
metadata:
name: zabbix-secrets
type: Opaque
data:
db-password: <base64-encoded>
admin-password: <base64-encoded>
Configure data retention:
# /etc/zabbix/zabbix_server.conf
# Housekeeping settings
HousekeepingFrequency=1
MaxHousekeeperDelete=500
HistoryStorageDateIndex=on
Enable audit trail:
# /etc/zabbix/zabbix_server.conf
# Audit settings are configured in frontend:
# Administration → General → Audit
# Enable: Actions, Changes, Login attempts
Configure audit log retention:
-- Audit log retention (in frontend)
-- Administration → General → Audit
-- Audit log retention: 365 days
Configure web server access logging:
# Apache access log
CustomLog /var/log/apache2/zabbix_access.log combined
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
# Log sensitive endpoints separately
CustomLog /var/log/apache2/zabbix_admin.log combined env=admin
SetEnvIf Request_URI "^/zabbix/admin" admin
Create Zabbix internal alerts:
Trigger: Failed login attempts
Expression: {Zabbix Server:zabbix[failed_login].count(300,"5","gt")}>0
Severity: Warning
Trigger: Configuration changes
Expression: {Zabbix Server:zabbix[audit_config].count(300)} > 10
Severity: Information
Trigger: Unauthorized API access
Expression: {Zabbix Server:zabbix[api_failed].count(60,"10","gt")}>0
Severity: Warning
Forward logs to SIEM systems:
# Configure rsyslog to forward Zabbix logs
cat >> /etc/rsyslog.d/zabbix.conf << EOF
:programname, isequal, "zabbix_server" @siem.company.com:514
:programname, isequal, "zabbix_agentd" @siem.company.com:514
EOF