Ansible Zabbix — Deploy and Configure Monitoring

Introduction

Zabbix is an enterprise-class monitoring solution for networks, servers, and applications. With the community.zabbix Ansible collection, you can automate the entire monitoring stack — deploy Zabbix server, install agents on all hosts, configure monitoring templates, and manage alerts through code.

Prerequisites

ansible-galaxy collection install community.zabbix
pip install zabbix-api

Deploy Zabbix Server

---
- name: Deploy Zabbix Server
  hosts: monitoring
  become: true
  vars:
    zabbix_version: "7.0"
    zabbix_db_password: "{{ vault_zabbix_db_password }}"
    zabbix_server_ip: "{{ ansible_default_ipv4.address }}"

  tasks:
    - name: Install Zabbix repository
      ansible.builtin.apt:
        deb: "https://repo.zabbix.com/zabbix/{{ zabbix_version }}/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_{{ ansible_distribution_release }}_all.deb"
      when: ansible_os_family == "Debian"

    - name: Install Zabbix server packages
      ansible.builtin.apt:
        name:
          - zabbix-server-pgsql
          - zabbix-frontend-php
          - zabbix-nginx-conf
          - zabbix-sql-scripts
          - zabbix-agent2
          - postgresql
          - python3-psycopg2
        state: present
        update_cache: true

    - name: Create Zabbix database
      community.postgresql.postgresql_db:
        name: zabbix
        encoding: UTF-8
      become_user: postgres

    - name: Create Zabbix database user
      community.postgresql.postgresql_user:
        name: zabbix
        password: "{{ zabbix_db_password }}"
        db: zabbix
        priv: ALL
      become_user: postgres

    - name: Import Zabbix schema
      ansible.builtin.shell:
        cmd: zcat /usr/share/zabbix-sql-scripts/postgresql/server.sql.gz | psql -U zabbix zabbix
      become_user: postgres
      args:
        creates: /etc/zabbix/.schema_imported

    - name: Mark schema as imported
      ansible.builtin.file:
        path: /etc/zabbix/.schema_imported
        state: touch
        mode: '0644'

    - name: Configure Zabbix server
      ansible.builtin.lineinfile:
        path: /etc/zabbix/zabbix_server.conf
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
      loop:
        - { regexp: '^# DBPassword=', line: 'DBPassword={{ zabbix_db_password }}' }
        - { regexp: '^# CacheSize=', line: 'CacheSize=128M' }
        - { regexp: '^# StartPollers=', line: 'StartPollers=10' }
      notify: Restart Zabbix server

    - name: Configure Nginx for Zabbix
      ansible.builtin.lineinfile:
        path: /etc/zabbix/nginx.conf
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
      loop:
        - { regexp: '#.*listen.*8080', line: '        listen 80;' }
        - { regexp: '#.*server_name', line: '        server_name zabbix.example.com;' }
      notify: Restart Nginx

    - name: Start services
      ansible.builtin.systemd:
        name: "{{ item }}"
        state: started
        enabled: true
      loop:
        - zabbix-server
        - zabbix-agent2
        - nginx
        - php8.3-fpm

  handlers:
    - name: Restart Zabbix server
      ansible.builtin.systemd:
        name: zabbix-server
        state: restarted

    - name: Restart Nginx
      ansible.builtin.systemd:
        name: nginx
        state: restarted

Deploy Zabbix Agent on All Hosts

---
- name: Deploy Zabbix Agent
  hosts: all
  become: true
  vars:
    zabbix_server_ip: "192.168.1.10"
    zabbix_version: "7.0"

  tasks:
    - name: Install Zabbix agent2
      ansible.builtin.package:
        name: zabbix-agent2
        state: present

    - name: Configure Zabbix agent
      ansible.builtin.template:
        src: zabbix_agent2.conf.j2
        dest: /etc/zabbix/zabbix_agent2.conf
        mode: '0644'
      notify: Restart Zabbix agent

    - name: Start Zabbix agent
      ansible.builtin.systemd:
        name: zabbix-agent2
        state: started
        enabled: true

  handlers:
    - name: Restart Zabbix agent
      ansible.builtin.systemd:
        name: zabbix-agent2
        state: restarted
# templates/zabbix_agent2.conf.j2
Server={{ zabbix_server_ip }}
ServerActive={{ zabbix_server_ip }}
Hostname={{ inventory_hostname }}
LogFile=/var/log/zabbix/zabbix_agent2.log
LogFileSize=10
PidFile=/var/run/zabbix/zabbix_agent2.pid
Include=/etc/zabbix/zabbix_agent2.d/*.conf
ControlSocket=/tmp/agent.sock

Register Hosts via API

---
- name: Register hosts in Zabbix
  hosts: localhost
  connection: local
  vars:
    zabbix_url: "http://zabbix.example.com"
    zabbix_user: Admin
    zabbix_password: "{{ vault_zabbix_admin_password }}"

  tasks:
    - name: Create host group
      community.zabbix.zabbix_group:
        server_url: "{{ zabbix_url }}"
        login_user: "{{ zabbix_user }}"
        login_password: "{{ zabbix_password }}"
        host_groups:
          - Production Servers
          - Web Servers
        state: present

    - name: Register hosts
      community.zabbix.zabbix_host:
        server_url: "{{ zabbix_url }}"
        login_user: "{{ zabbix_user }}"
        login_password: "{{ zabbix_password }}"
        host_name: "{{ item }}"
        host_groups:
          - Production Servers
        link_templates:
          - Linux by Zabbix agent active
        interfaces:
          - type: agent
            main: 1
            dns: "{{ item }}"
        status: enabled
        state: present
      loop: "{{ groups['all'] }}"

Custom Monitoring Items

    - name: Create custom monitoring template
      community.zabbix.zabbix_template:
        server_url: "{{ zabbix_url }}"
        login_user: "{{ zabbix_user }}"
        login_password: "{{ zabbix_password }}"
        template_name: "Custom App Monitoring"
        template_groups:
          - Templates
        state: present

    - name: Deploy custom UserParameters
      ansible.builtin.copy:
        content: |
          # Custom application monitoring
          UserParameter=app.status,systemctl is-active myapp
          UserParameter=app.connections,ss -tn | grep :8080 | wc -l
          UserParameter=app.response_time,curl -s -o /dev/null -w '%{time_total}' http://localhost:8080/health
          UserParameter=disk.iops[*],iostat -d $1 1 2 | tail -1 | awk '{print $$4}'
        dest: /etc/zabbix/zabbix_agent2.d/custom.conf
        mode: '0644'
      notify: Restart Zabbix agent

Troubleshooting

IssueSolution
Agent not connectingCheck firewall port 10050/10051
No data in ZabbixVerify Server= matches Zabbix server IP
API authentication failedCheck admin credentials, URL must include /api_jsonrpc.php path
Template import failedEnsure template XML version matches Zabbix version
High CPU on serverIncrease CacheSize, tune StartPollers

Best Practices

  1. Use Zabbix Agent 2 (Go-based) — better performance than legacy agent
  2. Active checks (ServerActive) — agent pushes data, works behind NAT
  3. Template everything — link templates to hosts, don't configure items per host
  4. Autoregister agents — configure auto-registration rules for dynamic environments
  5. Encrypt agent communication — use PSK or TLS certificates
  6. Monitor the monitor — set up external checks for Zabbix server itself

Conclusion

Ansible automates the entire Zabbix lifecycle — from server deployment to agent installation to host registration via API. The community.zabbix collection handles the API integration, while standard Ansible modules manage packages, configs, and services. Define your monitoring as code alongside your infrastructure.