Integrate Zabbix 7 with network automation and orchestration tools using Ansible and Python APIs

Advanced 45 min Apr 14, 2026 838 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

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"
          orga

Automated install script

Run this to automate the entire setup

Non vuoi gestirlo da solo?

Gestiamo l'infrastruttura di aziende che dipendono dall'uptime. Completamente gestita, con un referente fisso che conosce il tuo ambiente.

Avete un referente fisso che conosce il vostro ambiente

Alla scrivania a Rotterdam 09:06 · raggiungibile con un messaggio, senza modulo ticket