Build comprehensive network automation workflows by integrating Zabbix 7 monitoring with Ansible playbooks and custom Python scripts. This tutorial covers API authentication, automated host provisioning, and dynamic monitoring configuration for enterprise infrastructure management.
Prerequisites
- Zabbix 7 server with admin access
- Python 3.8+
- Ansible 2.9+
- Network connectivity to target hosts
- Basic understanding of YAML and Python
What this solves
Modern network infrastructure requires seamless integration between monitoring and automation tools to maintain scalability and reliability. This tutorial demonstrates how to integrate Zabbix 7 with Ansible and Python APIs to create automated workflows for host provisioning, template deployment, and dynamic configuration management. You'll build a complete automation pipeline that reduces manual monitoring setup and enables infrastructure-as-code practices.
Step-by-step configuration
Install Python dependencies and Ansible modules
Start by installing the required Python libraries and Ansible collections for Zabbix integration. These packages provide the API client libraries and Ansible modules needed for automation.
sudo apt update
sudo apt install -y python3-pip python3-venv ansible
pip3 install --user pyzabbix requests
ansible-galaxy collection install community.zabbix
ansible-galaxy collection install ansible.posix
sudo dnf update -y
sudo dnf install -y python3-pip python3-virtualenv ansible
pip3 install --user pyzabbix requests
ansible-galaxy collection install community.zabbix
ansible-galaxy collection install ansible.posix
Configure Zabbix API authentication
Create a dedicated API user in Zabbix with appropriate permissions for automation tasks. This user will authenticate API requests from Ansible and Python scripts.
mkdir -p ~/zabbix-automation/{playbooks,scripts,inventory}
cd ~/zabbix-automation
Create the API authentication configuration file with your Zabbix server details:
zabbix:
server: https://zabbix.example.com
username: api-automation
password: secure-api-password-2024
validate_certs: true
timeout: 30
default_templates:
- Template Module ICMP Ping
- Template OS Linux by Zabbix agent
default_groups:
- Linux servers
- Production
proxy_settings:
use_proxy: false
proxy_name: ""
notification_settings:
enable_alerts: true
email_recipient: admin@example.com
Create Ansible inventory configuration
Set up dynamic inventory sources and group variables for consistent host management across your infrastructure.
[zabbix_servers]
zabbix-primary ansible_host=203.0.113.10 zabbix_role=primary
zabbix-secondary ansible_host=203.0.113.11 zabbix_role=secondary
[monitoring_targets]
web-server-01 ansible_host=203.0.113.20 server_type=web environment=production
db-server-01 ansible_host=203.0.113.21 server_type=database environment=production
app-server-01 ansible_host=203.0.113.22 server_type=application environment=staging
[monitoring_targets:vars]
zabbix_agent_version=6.4
zabbix_server_host=203.0.113.10
zabbix_agent_hostname_type=fqdn
Configure group variables for different server types:
zabbix_api_server: "{{ hostvars['zabbix-primary']['ansible_host'] }}"
zabbix_api_user: api-automation
zabbix_api_password: secure-api-password-2024
monitoring_templates:
web:
- Template App HTTP Service
- Template OS Linux by Zabbix agent
- Template Module ICMP Ping
database:
- Template DB MySQL
- Template OS Linux by Zabbix agent
- Template Module ICMP Ping
application:
- Template App Generic Java JMX
- Template OS Linux by Zabbix agent
- Template Module ICMP Ping
host_groups_mapping:
production: "Production servers"
staging: "Staging servers"
development: "Development servers"
Build Ansible playbook for host provisioning
Create a comprehensive playbook that automates Zabbix host creation, template assignment, and monitoring configuration based on inventory metadata.
---
- name: Provision Zabbix monitoring for infrastructure hosts
hosts: monitoring_targets
gather_facts: yes
vars_files:
- ../config.yml
tasks:
- name: Create host groups if they don't exist
community.zabbix.zabbix_group:
server_url: "{{ zabbix.server }}"
login_user: "{{ zabbix.username }}"
login_password: "{{ zabbix.password }}"
validate_certs: "{{ zabbix.validate_certs }}"
group_name: "{{ host_groups_mapping[environment] }}"
state: present
delegate_to: localhost
run_once: true
- name: Create Zabbix host entry
community.zabbix.zabbix_host:
server_url: "{{ zabbix.server }}"
login_user: "{{ zabbix.username }}"
login_password: "{{ zabbix.password }}"
validate_certs: "{{ zabbix.validate_certs }}"
host_name: "{{ inventory_hostname }}"
visible_name: "{{ inventory_hostname }} ({{ server_type | title }})"
description: "{{ server_type | title }} server in {{ environment }} environment"
host_groups:
- "{{ host_groups_mapping[environment] }}"
link_templates: "{{ monitoring_templates[server_type] }}"
interfaces:
- type: agent
main: 1
useip: 1
ip: "{{ ansible_host }}"
port: 10050
- type: snmp
main: 1
useip: 1
ip: "{{ ansible_host }}"
port: 161
details:
version: 2
community: public
inventory:
tag: "{{ environment }}"
location: "{{ datacenter | default('Primary DC') }}"
contact: "{{ owner_email | default('admin@example.com') }}"
state: present
delegate_to: localhost
- name: Configure host macros based on server type
community.zabbix.zabbix_hostmacro:
server_url: "{{ zabbix.server }}"
login_user: "{{ zabbix.username }}"
login_password: "{{ zabbix.password }}"
validate_certs: "{{ zabbix.validate_certs }}"
host_name: "{{ inventory_hostname }}"
macro_name: "{{ item.key }}"
macro_value: "{{ item.value }}"
state: present
loop:
- { key: '{$ENVIRONMENT}', value: "{{ environment }}" }
- { key: '{$SERVER_TYPE}', value: "{{ server_type }}" }
- { key: '{$CONTACT_EMAIL}', value: "{{ owner_email | default('admin@example.com') }}" }
delegate_to: localhost
Create Python automation script for advanced operations
Develop a Python script that performs complex Zabbix operations not easily handled by Ansible, including bulk operations and custom metric handling.
#!/usr/bin/env python3
import json
import yaml
import argparse
from pyzabbix import ZabbixAPI
from datetime import datetime, timedelta
import logging
import sys
from typing import Dict, List, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('/var/log/zabbix-automation.log'),
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
class ZabbixAutomation:
def __init__(self, config_file: str):
with open(config_file, 'r') as f:
self.config = yaml.safe_load(f)
self.zapi = ZabbixAPI(self.config['zabbix']['server'])
self.zapi.login(
self.config['zabbix']['username'],
self.config['zabbix']['password']
)
logger.info(f"Connected to Zabbix API version {self.zapi.api_version()}")
def bulk_host_operations(self, action: str, host_pattern: str) -> Dict:
"""Perform bulk operations on hosts matching pattern"""
hosts = self.zapi.host.get(
search={'host': host_pattern},
searchWildcardsEnabled=True,
output=['hostid', 'host', 'status']
)
results = {'success': [], 'failed': []}
for host in hosts:
try:
if action == 'enable':
self.zapi.host.update(
hostid=host['hostid'],
status=0
)
elif action == 'disable':
self.zapi.host.update(
hostid=host['hostid'],
status=1
)
elif action == 'maintenance':
self._create_maintenance(host)
results['success'].append(host['host'])
logger.info(f"Successfully {action}d host {host['host']}")
except Exception as e:
results['failed'].append({
'host': host['host'],
'error': str(e)
})
logger.error(f"Failed to {action} host {host['host']}: {e}")
return results
def create_custom_dashboard(self, dashboard_name: str, host_group: str) -> str:
"""Create custom dashboard for host group"""
try:
# Get hosts from group
hosts = self.zapi.host.get(
groupids=self.zapi.hostgroup.get(
filter={'name': host_group}
)[0]['groupid'],
output=['hostid', 'host']
)
# Dashboard configuration
dashboard_config = {
'name': dashboard_name,
'display_period': 30,
'auto_start': 1,
'pages': [{
'name': 'Overview',
'display_period': 0,
'widgets': []
}]
}
# Add widgets for each host
widget_id = 0
for i, host in enumerate(hosts[:10]): # Limit to 10 hosts
x = (i % 2) * 12
y = (i // 2) * 6
dashboard_config['pages'][0]['widgets'].append({
'type': 'graph',
'name': f"{host['host']} - CPU Usage",
'x': x,
'y': y,
'width': 12,
'height': 6,
'fields': [
{'type': 0, 'name': 'source_type', 'value': '0'},
{'type': 4, 'name': 'itemid', 'value': str(self._get_cpu_item_id(host['hostid']))}
]
})
widget_id += 1
# Create dashboard
result = self.zapi.dashboard.create(dashboard_config)
logger.info(f"Created dashboard '{dashboard_name}' with ID {result['dashboardids'][0]}")
return result['dashboardids'][0]
except Exception as e:
logger.error(f"Failed to create dashboard: {e}")
raise
def _get_cpu_item_id(self, hostid: str) -> Optional[str]:
"""Get CPU utilization item ID for host"""
items = self.zapi.item.get(
hostids=hostid,
search={'key_': 'system.cpu.util'},
output=['itemid']
)
return items[0]['itemid'] if items else None
def _create_maintenance(self, host: Dict) -> None:
"""Create maintenance period for host"""
maintenance_data = {
'name': f"Maintenance - {host['host']}",
'active_since': int(datetime.now().timestamp()),
'active_till': int((datetime.now() + timedelta(hours=2)).timestamp()),
'hostids': [host['hostid']],
'timeperiods': [{
'timeperiod_type': 0,
'start_date': int(datetime.now().timestamp()),
'period': 7200 # 2 hours
}]
}
self.zapi.maintenance.create(maintenance_data)
def export_configuration(self, output_file: str, export_type: str = 'hosts') -> None:
"""Export Zabbix configuration to file"""
try:
if export_type == 'hosts':
data = self.zapi.host.get(
output='extend',
selectGroups='extend',
selectTemplates='extend',
selectMacros='extend'
)
elif export_type == 'templates':
data = self.zapi.template.get(
output='extend',
selectGroups='extend',
selectItems='extend'
)
with open(output_file, 'w') as f:
json.dump(data, f, indent=2, default=str)
logger.info(f"Exported {export_type} configuration to {output_file}")
except Exception as e:
logger.error(f"Failed to export configuration: {e}")
raise
def main():
parser = argparse.ArgumentParser(description='Zabbix Automation Tool')
parser.add_argument('--config', default='config.yml', help='Config file path')
parser.add_argument('--action', required=True,
choices=['bulk-enable', 'bulk-disable', 'bulk-maintenance', 'create-dashboard', 'export'],
help='Action to perform')
parser.add_argument('--pattern', help='Host pattern for bulk operations')
parser.add_argument('--dashboard-name', help='Dashboard name')
parser.add_argument('--host-group', help='Host group name')
parser.add_argument('--export-type', choices=['hosts', 'templates'], default='hosts')
parser.add_argument('--output-file', default='zabbix-export.json', help='Export output file')
args = parser.parse_args()
try:
automation = ZabbixAutomation(args.config)
if args.action.startswith('bulk-'):
action = args.action.replace('bulk-', '')
if not args.pattern:
raise ValueError("Pattern required for bulk operations")
results = automation.bulk_host_operations(action, args.pattern)
print(json.dumps(results, indent=2))
elif args.action == 'create-dashboard':
if not args.dashboard_name or not args.host_group:
raise ValueError("Dashboard name and host group required")
dashboard_id = automation.create_custom_dashboard(args.dashboard_name, args.host_group)
print(f"Created dashboard with ID: {dashboard_id}")
elif args.action == 'export':
automation.export_configuration(args.output_file, args.export_type)
print(f"Configuration exported to {args.output_file}")
except Exception as e:
logger.error(f"Automation failed: {e}")
sys.exit(1)
if __name__ == '__main__':
main()
Make the script executable and create the log directory:
chmod +x ~/zabbix-automation/scripts/zabbix_automation.py
sudo mkdir -p /var/log
sudo touch /var/log/zabbix-automation.log
sudo chown $USER:$USER /var/log/zabbix-automation.log
Integrate with Ansible AWX for orchestration
Configure Ansible AWX integration for centralized automation management. This setup assumes you have AWX installed and running.
---
- name: AWX Integration for Zabbix Automation
hosts: localhost
vars:
awx_host: https://awx.example.com
awx_username: admin
awx_password: awx-admin-password
organization_name: Infrastructure Team
project_name: Zabbix Automation
inventory_name: Production Infrastructure
tasks:
- name: Create AWX project for Zabbix automation
uri:
url: "{{ awx_host }}/api/v2/projects/"
method: POST
user: "{{ awx_username }}"
password: "{{ awx_password }}"
force_basic_auth: yes
validate_certs: yes
body_format: json
body:
name: "{{ project_name }}"
organization: 1
scm_type: git
scm_url: https://github.com/company/zabbix-automation.git
scm_branch: main
scm_update_on_launch: true
status_code: [201, 400]
register: project_creation
- name: Create job template for host provisioning
uri:
url: "{{ awx_host }}/api/v2/job_templates/"
method: POST
user: "{{ awx_username }}"
password: "{{ awx_password }}"
force_basic_auth: yes
validate_certs: yes
body_format: json
body:
name: "Provision Zabbix Monitoring"
description: "Automated Zabbix host provisioning"
job_type: run
inventory: 2
project: "{{ project_creation.json.id | default(1) }}"
playbook: "playbooks/provision-monitoring.yml"
credential: 1
verbosity: 1
ask_variables_on_launch: true
status_code: [201, 400]
register: job_template
- name: Create workflow template for complete automation
uri:
url: "{{ awx_host }}/api/v2/workflow_job_templates/"
method: POST
user: "{{ awx_username }}"
password: "{{ awx_password }}"
force_basic_auth: yes
validate_certs: yes
body_format: json
body:
name: "Complete Zabbix Infrastructure Setup"
description: "End-to-end Zabbix monitoring deployment"
orgaAutomated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Zabbix 7 Network Automation Integration Setup
# Sets up Ansible, Python APIs, and automation tools for Zabbix monitoring
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Default values
ZABBIX_SERVER=""
API_USER="api-automation"
AUTOMATION_DIR="/opt/zabbix-automation"
print_usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -s <server> Zabbix server URL (e.g., https://zabbix.example.com)"
echo " -u <user> API username (default: api-automation)"
echo " -d <dir> Installation directory (default: /opt/zabbix-automation)"
echo " -h Show this help"
exit 1
}
log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
}
warn() {
echo -e "${YELLOW}[WARNING] $1${NC}"
}
error() {
echo -e "${RED}[ERROR] $1${NC}"
exit 1
}
cleanup() {
warn "Installation failed. Cleaning up..."
rm -rf "$AUTOMATION_DIR" 2>/dev/null || true
}
trap cleanup ERR
while getopts "s:u:d:h" opt; do
case $opt in
s) ZABBIX_SERVER="$OPTARG" ;;
u) API_USER="$OPTARG" ;;
d) AUTOMATION_DIR="$OPTARG" ;;
h) print_usage ;;
*) print_usage ;;
esac
done
if [[ -z "$ZABBIX_SERVER" ]]; then
error "Zabbix server URL is required. Use -s option."
fi
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root"
fi
log "[1/8] Detecting operating system..."
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update"
PYTHON_VENV="python3-venv"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
PYTHON_VENV="python3-virtualenv"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
PYTHON_VENV="python3-virtualenv"
;;
*)
error "Unsupported distribution: $ID"
;;
esac
log "Detected: $PRETTY_NAME"
else
error "Cannot detect operating system"
fi
log "[2/8] Updating package manager..."
$PKG_UPDATE
log "[3/8] Installing system packages..."
$PKG_INSTALL python3 python3-pip $PYTHON_VENV ansible git curl
log "[4/8] Creating automation directory structure..."
mkdir -p "$AUTOMATION_DIR"/{playbooks,scripts,inventory,templates,logs}
cd "$AUTOMATION_DIR"
log "[5/8] Setting up Python virtual environment..."
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install pyzabbix requests ansible-core
log "[6/8] Installing Ansible collections..."
ansible-galaxy collection install community.zabbix
ansible-galaxy collection install ansible.posix
log "[7/8] Creating configuration files..."
cat > config.yml << EOF
zabbix:
server: $ZABBIX_SERVER
username: $API_USER
password: "CHANGE_ME"
validate_certs: true
timeout: 30
default_templates:
- Template Module ICMP Ping
- Template OS Linux by Zabbix agent
default_groups:
- Linux servers
- Production
proxy_settings:
use_proxy: false
proxy_name: ""
notification_settings:
enable_alerts: true
email_recipient: admin@example.com
EOF
cat > inventory/hosts.ini << EOF
[zabbix_servers]
zabbix-primary ansible_host=192.168.1.10 zabbix_role=primary
[monitoring_targets]
# Add your hosts here
# web-server-01 ansible_host=192.168.1.20 server_type=web environment=production
[monitoring_targets:vars]
zabbix_agent_version=6.4
zabbix_server_host=192.168.1.10
zabbix_agent_hostname_type=fqdn
EOF
cat > inventory/group_vars/all.yml << EOF
zabbix_api_server: "$ZABBIX_SERVER"
zabbix_api_user: $API_USER
zabbix_api_password: "{{ vault_zabbix_password }}"
monitoring_templates:
web:
- Template App HTTP Service
- Template OS Linux by Zabbix agent
- Template Module ICMP Ping
database:
- Template DB MySQL
- Template OS Linux by Zabbix agent
- Template Module ICMP Ping
application:
- Template App Generic Java JMX
- Template OS Linux by Zabbix agent
- Template Module ICMP Ping
host_groups_mapping:
production: "Production servers"
staging: "Staging servers"
development: "Development servers"
EOF
cat > playbooks/provision-hosts.yml << 'EOF'
---
- name: Provision Zabbix monitoring for infrastructure hosts
hosts: monitoring_targets
gather_facts: yes
vars_files:
- ../config.yml
tasks:
- name: Create host groups if they don't exist
community.zabbix.zabbix_group:
server_url: "{{ zabbix.server }}"
login_user: "{{ zabbix.username }}"
login_password: "{{ zabbix.password }}"
validate_certs: "{{ zabbix.validate_certs }}"
host_groups:
- "{{ host_groups_mapping[environment] }}"
state: present
delegate_to: localhost
- name: Add hosts to Zabbix
community.zabbix.zabbix_host:
server_url: "{{ zabbix.server }}"
login_user: "{{ zabbix.username }}"
login_password: "{{ zabbix.password }}"
validate_certs: "{{ zabbix.validate_certs }}"
host_name: "{{ inventory_hostname }}"
visible_name: "{{ inventory_hostname }}"
host_groups:
- "{{ host_groups_mapping[environment] }}"
link_templates: "{{ monitoring_templates[server_type] | default(default_templates) }}"
interfaces:
- type: 1
main: 1
useip: 1
ip: "{{ ansible_host }}"
dns: ""
port: "10050"
state: present
delegate_to: localhost
EOF
cat > scripts/api_client.py << 'EOF'
#!/usr/bin/env python3
import sys
import yaml
from pyzabbix import ZabbixAPI
import argparse
def load_config():
with open('../config.yml', 'r') as f:
return yaml.safe_load(f)
def main():
parser = argparse.ArgumentParser(description='Zabbix API automation client')
parser.add_argument('--list-hosts', action='store_true', help='List all hosts')
parser.add_argument('--list-templates', action='store_true', help='List all templates')
args = parser.parse_args()
config = load_config()
zapi = ZabbixAPI(config['zabbix']['server'])
zapi.login(config['zabbix']['username'], config['zabbix']['password'])
if args.list_hosts:
hosts = zapi.host.get(output=['hostid', 'name', 'status'])
for host in hosts:
print(f"Host: {host['name']} (ID: {host['hostid']}, Status: {host['status']})")
if args.list_templates:
templates = zapi.template.get(output=['templateid', 'name'])
for template in templates:
print(f"Template: {template['name']} (ID: {template['templateid']})")
if __name__ == '__main__':
main()
EOF
chown -R root:root "$AUTOMATION_DIR"
chmod -R 755 "$AUTOMATION_DIR"
chmod 644 "$AUTOMATION_DIR"/config.yml
chmod 644 "$AUTOMATION_DIR"/inventory/*
chmod 644 "$AUTOMATION_DIR"/playbooks/*
chmod 755 "$AUTOMATION_DIR"/scripts/*
log "[8/8] Verifying installation..."
cd "$AUTOMATION_DIR"
source venv/bin/activate
if ! python -c "import pyzabbix; print('PyZabbix imported successfully')"; then
error "PyZabbix installation failed"
fi
if ! ansible --version >/dev/null 2>&1; then
error "Ansible installation failed"
fi
if ! ansible-galaxy collection list | grep -q community.zabbix; then
error "Zabbix Ansible collection not installed"
fi
log "Installation completed successfully!"
echo ""
echo "Next steps:"
echo "1. Edit $AUTOMATION_DIR/config.yml with your Zabbix credentials"
echo "2. Update inventory files in $AUTOMATION_DIR/inventory/"
echo "3. Activate virtual environment: source $AUTOMATION_DIR/venv/bin/activate"
echo "4. Run playbooks from: cd $AUTOMATION_DIR && ansible-playbook -i inventory/hosts.ini playbooks/provision-hosts.yml"
Review the script before running. Execute with: bash install.sh