Automating Zabbix Installations Using Ansible: A Comprehensive Guide

Automating Zabbix Installations Using Ansible

Automating Zabbix Installations Using Ansible simplifies the deployment and configuration of Zabbix, an open-source monitoring solution. This comprehensive guide provides step-by-step instructions, essential YAML configurations, and best practices to enhance efficiency and reduce manual errors in your monitoring setup. Perfect for IT administrators looking to streamline their infrastructure management.

Table of Contents

Introduction

In the realm of IT infrastructure, automation is not just a luxury but a necessity. Ansible, a powerful automation tool, combined with Zabbix, an open-source monitoring solution, provides a robust framework for managing and monitoring IT environments. This guide will walk you through the process of automating the installation and configuration of Zabbix using Ansible, leveraging the provided YAML configurations.

Why Use Ansible with Zabbix

Ansible is a simple yet powerful tool for automating IT tasks, including configuration management, application deployment, and orchestration. It uses a declarative language to describe system configurations.

Zabbix is a comprehensive monitoring solution for networks and applications. It provides capabilities such as real-time monitoring, alerting, and trending. By automating Zabbix installation with Ansible roles, you can ensure consistent deployments across multiple environments, reducing manual errors and saving time.

Now, let’s proceed with the breakdown of all the configuration files required to automate an install of Zabbix on RHEL 9 or CentOS 9.

Configuration FileDescription
install_zabbix.ymlThe main playbook that orchestrates the installation of Zabbix on all specified hosts using the ansible-zabbix-install role.
inventory.ymlDefines the inventory of Zabbix nodes, specifying hostnames and their corresponding IP addresses.
defaults/main.ymlContains default variables for the Ansible role, including Zabbix version, RHEL version, database passwords, and repository URLs.
handlers/main.ymlDefines handlers to restart or reload services (like Zabbix, Apache, and PostgreSQL) when changes occur during the playbook execution.
tasks/main.ymlIncludes various task files necessary for setting up Zabbix, such as PostgreSQL, network configuration, SSL setup, SELinux configuration, and frontend installation.
tasks/network.ymlConfigures firewall settings and SELinux policies to ensure proper access for Zabbix, PostgreSQL, and Apache.
tasks/postgresql.ymlHandles the installation and configuration of PostgreSQL, including user creation, database setup, and remote access configuration.
tasks/selinux.ymlInstalls SELinux policy utilities and creates custom SELinux modules to allow PHP to allocate executable memory.
tasks/zabbix.ymlInstalls the Zabbix server, frontend, and agent, and configures the database and user permissions.
tasks/ssl.ymlManages the creation of SSL directories and self-signed certificates for secure communication.
tasks/frontend.ymlInstalls and configures Apache and PHP for the Zabbix frontend, ensuring all necessary services are started and enabled.

Prerequisites

Before we begin, ensure you have the following:

  • Two Servers/Virtual Machines (VMs): We recommend at least two servers to follow along with this article.
  • Sudo Admin Privileges: You will need administrative privileges to perform the installation and configuration steps.
  • Subscription to Red Hat: If you are using RHEL instances, ensure you have an active subscription to access necessary repositories and updates.

For demonstration purposes, we’ve configured our Linux nodes as follows (2 nodes, 1 ansible-ctl, 1 for zabbix install):

HostnamesRAM (GB)CoresOperating System (OS)
ansible-ctl.dev.naijalabs.net42Red Hat Enterprise Linux release 9.4 (Plow)
zbx-node1.dev.naijalabs.net42Red Hat Enterprise Linux release 9.4 (Plow)

Copy and paste the following entries in the /etc/hosts file on each node (replace IP addresses and hostnames with your actual settings):

				
					# Ansible Zabbix Hosts
192.168.1.22  ansible-ctl.dev.naijlabs.net ansible-ctl
192.168.1.218 zbx-node1.dev.naijalabs.net
				
			
Automating Zabbix Installations Using Ansible

Photo by admingeek from Infotechys

Automating Zabbix Installations Using Ansible: A Step-by-Step Guide

On your Ansible node, create a directory named ansible and another one named inventory that will house all your inventory files. Then,  navigate into the ansible directory:
				
					$ mkdir -p ansible; mkdir -p inventory; cd ansible
				
			

If you don’t already have Ansible installed, install it with the following command:

				
					$ sudo dnf install ansible -y
				
			

Then, run the following command to create the directory structure for the ansible-zabbix-install role.

				
					$ ansible-galaxy init ansible-zabbix-install
				
			
				
					- Role ansible-zabbix-install was created successfully
				
			

Next, run the tree command to view the directory structure:

				
					$ tree
				
			
				
					.
└── ansible-zabbix-install
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml

9 directories, 8 files

				
			

Your directory structure should look similar to the output above. In the next section, we’ll breakdown all of the configuration files belonging to each sub-directory.

Breakdown of Configuration Files

install_zabbix.yml

This playbook is the entry point for the Ansible role ansible-zabbix-install, which sets up Zabbix on all specified hosts.

				
					---
- hosts: all
  become: yes
  roles:
    - ansible-zabbix-install
				
			

inventory/zabbix_inventory.yml

Defines the Zabbix nodes and their respective IP addresses.

				
					---
zabbix_nodes:
  hosts:
    zbx-node1.dev.naijalabs.net:
      ansible_host: 192.168.1.218
				
			

defaults/main.yml

Contains default variables for the Ansible role, such as Zabbix and RHEL versions, database passwords, and repository URLs.

				
					---
# defaults file for ansible-zabbix-install
playbook_dir: "~/ansible/ansible-zabbix-install"
zabbix_version: 6.4
rhel_version: 9
postgresql_password: postgres
zabbix_db_password: zabbix
zabbix_server_ip: 192.168.1.218
timezone: Etc/UTC
zabbix_repo_url: "https://repo.zabbix.com/zabbix/{{ zabbix_version }}/rhel/{{ rhel_version }}/x86_64/zabbix-release-latest.el{{ rhel_version }}.noarch.rpm"
				
			

handlers/main.yml

Defines handlers to restart or reload services when changes occur.

				
					---
# handlers file for ansible-zabbix-install to restart services
- name: Restart Zabbix Server
  systemd:
    name: zabbix-server
    state: restarted

- name: Restart Zabbix Agent
  systemd:
    name: zabbix-agent
    state: restarted

- name: Restart Apache
  systemd:
    name: httpd
    state: restarted

- name: Restart PHP-FPM
  systemd:
    name: php-fpm
    state: restarted

- name: Reload firewalld
  service:
    name: firewalld
    state: reloaded

- name: Reload PostgreSQL
  systemd:
    name: postgresql
    state: reloaded

- name: Restart PostgreSQL
  systemd:
    name: postgresql
    state: restarted
				
			

tasks/main.yml

Includes various task files necessary for setting up Zabbix.

				
					---
# tasks file for ansible-zabbix-install
- include_tasks: postgresql.yml
- include_tasks: zabbix.yml
- include_tasks: network.yml
- include_tasks: ssl.yml
- include_tasks: selinux.yml  
- include_tasks: frontend.yml
				
			

tasks/network.yml

Configures firewall settings and SELinux for Zabbix.

				
					---
# Firewall tasks section
- name: Open necessary firewall ports for Zabbix, PostgreSQL, and Apache
  firewalld:
    port: "{{ item }}"
    permanent: yes
    state: enabled
  with_items:
    - "10050/tcp"  # Zabbix server port
    - "10051/tcp"  # Zabbix server port
    - "5432/tcp"   # PostgreSQL port
    - "443/tcp"    # HTTPS/SSL port for Apache
  notify:
    - Reload firewalld

# SELinux configuration section
- name: Configure SELinux for Zabbix frontend access
  command: setsebool -P httpd_can_network_connect on
  when: ansible_selinux.status == "enabled"
				
			

tasks/postgresql.yml

Handles the installation and configuration of PostgreSQL.

				
					---
# Install PostgreSQL
- name: Install PostgreSQL packages
  dnf:
    name:
      - postgresql-server
      - postgresql-contrib
    state: present

# Initialize PostgreSQL database
- name: Initialize PostgreSQL Database
  command: postgresql-setup --initdb
  args:
    creates: /var/lib/pgsql/data/PG_VERSION

# Start and enable PostgreSQL
- name: Start and enable PostgreSQL
  systemd:
    name: postgresql
    state: started
    enabled: yes

# Install Python Pip      
- name: Install Python pip
  dnf:
    name: python3-pip
    state: present

# Install Python Library (psycopg2)      
- name: Install psycopg2 Python library
  pip:
    name: psycopg2-binary
    state: present
      
# Set PostgreSQL password for user 'postgres'
- name: Set PostgreSQL password for 'postgres' user
  become_user: postgres
  postgresql_user:
    name: postgres
    password: "{{ postgresql_password }}"

# Ensure PostgreSQL Remote Access
- name: Ensure PostgreSQL Remote Access
  lineinfile:
    path: /var/lib/pgsql/data/postgresql.conf
    regexp: '^#listen_addresses ='
    line: "listen_addresses = '*'"
    backup: yes
    state: present
  notify:
    - Restart PostgreSQL

				
			

tasks/selinux.yml

Configures SELinux policies for Zabbix.

				
					---
- name: Install SELinux policy utilities
  dnf:
    name: policycoreutils-python-utils
    state: present
  become: yes

- name: Create custom SELinux module file for PHP PCRE JIT
  copy:
    dest: /tmp/php_jit.te
    content: |
      module php_jit 1.0;

      require {
          type httpd_t;
          class process execmem;
      }

      # Allow PHP to allocate executable memory
      allow httpd_t self:process execmem;

- name: Compile the custom SELinux module
  shell: |
    checkmodule -M -m -o /tmp/php_jit.mod /tmp/php_jit.te
    semodule_package -o /tmp/php_jit.pp -m /tmp/php_jit.mod
    semodule -i /tmp/php_jit.pp
  args:
    creates: /tmp/php_jit.pp
				
			

tasks/zabbix.yml

Installs and configures Zabbix server, frontend, and agent.

				
					---
# Disable EPEL repository if it exists
- name: Remove epel-release package if it exists
  ansible.builtin.package:
    name: epel-release
    state: absent
  ignore_errors: yes

# Install Zabbix repository
- name: Install Zabbix repository
  dnf:
    name: "{{ zabbix_repo_url }}"
    state: present
    disable_gpg_check: yes

# Install Zabbix server, frontend, agent, and dependencies
- name: Install Zabbix server, frontend, and agent packages
  dnf:
    name:
      - zabbix-server-pgsql
      - zabbix-web-pgsql
      - zabbix-web
      - zabbix-web-deps
      - zabbix-sql-scripts
      - zabbix-selinux-policy
      - zabbix-apache-conf
      - zabbix-agent
    state: present

# Create Zabbix database and user
- name: Create Zabbix user in PostgreSQL
  become_user: postgres
  postgresql_user:
    name: zabbix
    password: "{{ zabbix_db_password }}"
    state: present

- name: Create Zabbix database
  become_user: postgres
  postgresql_db:
    name: zabbix
    owner: zabbix

- name: Grant privileges to Zabbix database
  become_user: postgres
  postgresql_query:
    db: zabbix
    query: "GRANT ALL PRIVILEGES ON DATABASE zabbix TO zabbix;"

# Import Zabbix schema
- name: Import Zabbix schema into PostgreSQL
  ansible.builtin.shell: |
    zcat /usr/share/zabbix-sql-scripts/postgresql/server.sql.gz | sudo -u zabbix psql zabbix
  changed_when: false

- name: Update Zabbix Server Configuration with Database Credentials
  blockinfile:
    path: /etc/zabbix/zabbix_server.conf
    marker: "# {mark} MANAGED BLOCK"
    block: |
      DBPassword={{ zabbix_db_password }}
    state: present

# Configure PostgreSQL to Allow Database Connections    
- name: Modify PostgreSQL configuration for Zabbix
  ansible.builtin.shell: |
    sed -i 's/ident/md5/' /var/lib/pgsql/data/pg_hba.conf
  changed_when: false
  
# Configure PostgreSQL to Allow Database Connections    
- name: Ensure pg_hba.conf allows connections from localhost
  lineinfile:
    path: /var/lib/pgsql/data/pg_hba.conf
    regexp: '^host\s+zabbix\s+zabbix\s+127.0.0.1/32\s+md5'
    line: 'host    zabbix          zabbix          127.0.0.1/32            md5'
    state: present
  notify: Reload PostgreSQL

				
			

tasks/ssl.yml

Handles the creation of SSL directories and self-signed certificates.

				
					---
- name: Ensure SSL directories exist
  file:
    path: "{{ item }}"
    state: directory
    mode: '0700'
  with_items:
    - /etc/pki/tls/private
    - /etc/pki/tls/certs

- name: Check if SSL key exists
  stat:
    path: /etc/pki/tls/private/self_signed.key
  register: ssl_key_stat

- name: Check if SSL certificate exists
  stat:
    path: /etc/pki/tls/certs/self_signed.crt
  register: ssl_crt_stat

- name: Generate self-signed SSL certificate if cert and key don't exist
  command: openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/pki/tls/private/self_signed.key -out /etc/pki/tls/certs/self_signed.crt -subj "/C=US/ST=State/L=City/O=Organization/OU=OrgUnit/CN=localhost"
  when: not (ssl_key_stat.stat.exists and ssl_crt_stat.stat.exists)

- name: Output a message if the SSL certificate and key already exist
  debug:
    msg: "SSL certificate and key already exist; skipping generation."
  when: ssl_key_stat.stat.exists and ssl_crt_stat.stat.exists
				
			

tasks/frontend.yml

Installs Apache and PHP, and configures them for Zabbix.

				
					---
# Install Apache and PHP
- name: Install Apache and PHP packages
  dnf:
    name:
      - httpd
      - php
      - php-pgsql
      - mod_ssl  
    state: present

# Start and enable Apache and PHP services
- name: Start and enable Apache and PHP-FPM services
  systemd:
    name: "{{ item }}"
    state: started
    enabled: yes
  loop:
    - httpd
    - php-fpm

# Update Zabbix.conf for PHP-FPM    
- name: Update Zabbix Configuration for PHP-FPM
  lineinfile:
    path: /etc/php-fpm.d/zabbix.conf  
    regexp: '^php_value\[date.timezone\]'
    line: 'php_value[date.timezone] = {{ timezone }}'
    state: present

# Configure PHP timezone for Zabbix
- name: Configure PHP timezone for Zabbix
  template:
    src: php.ini.j2
    dest: /etc/php.ini
  notify: Restart PHP-FPM

# Ensure all Zabbix Services are Started and Enabled
- name: Ensure all Zabbix Services are Started and Enabled
  ansible.builtin.shell: |
    systemctl enable --now zabbix-server zabbix-agent httpd php-fpm
  changed_when: false
				
			

Breakdown of Jinja2 Template Files

Jinja2 is a powerful templating engine that allows users to create dynamic configuration files by incorporating variables, control structures (like loops and conditionals), and filters. These templates enable the generation of customized content based on the specific needs of the deployment environment. When processed, the placeholders in the .j2 files are replaced with actual values, resulting in fully formed configuration files that can be deployed to servers. This approach enhances flexibility and maintainability in configuration management.

templates/php.ini.j2

Configures time zone settings for PHP.

				
					[Date]
date.timezone = {{ timezone }}
				
			

Automating Zabbix Installations Using Ansible: Playbook Execution

Having reviewed each configuration file in the ansible-zabbix-install role, we are now prepared to run the playbook. It’s advisable to perform a dry run first to ensure everything is set up correctly before executing it for real.
				
					$ ansible-playbook -i ~/ansible/inventory/zabbix_inventory.yml ~/ansible/install_zabbix.yml -K --check
				
			
				
					BECOME password:
				
			

Enter your sudo credentials to continue:

Automating Zabbix Installations Using Ansible

Photo by admingeek from Infotechys

If the playbook run completes without errors or failed tasks, run it again for real without the --check option.

Verify the Deployment

After execution, verify the Zabbix setup by accessing the web interface at:  https://<zabbix_server_ip>/zabbix

Automating Zabbix Installations Using Ansible

Photo by admingeek from Infotechys

Finally, log on to the Zabbix frontend using the default credentials:

  • Username: Admin
  • Password: zabbix

Quick Tips & Command-Line (CLI) Examples

Here are a few more Ansible CLI examples:  

Check Ansible Version:

				
					$ ansible --version
				
			

List Available Hosts:

				
					$ ansible-inventory --list -i inventory/zabbix_inventory.yml
				
			

Run the Playbook with Verbose Output:

				
					$ ansible-playbook -i inventory/zabbix_inventory.yml install_zabbix.yml -K -v
				
			

Conclusion

Deploying Zabbix using Ansible streamlines the process of setting up a monitoring infrastructure, ensuring consistency and reducing potential errors. The detailed configurations and tasks provided in this guide should serve as a comprehensive roadmap for automating Zabbix installations, allowing IT administrators to focus on more strategic tasks rather than repetitive setup procedures.

With this automation, your IT environment can become more resilient, scalable, and manageable, ultimately enhancing the overall efficiency and reliability of your operations. As always, test configurations in a staging environment before applying them in production to ensure everything works as intended.

Did you find this article useful? Your feedback is invaluable to us! Please feel free to share your thoughts in the comments section below.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *