Automating Cacti Network Monitoring Deployment with Ansible

DevOpsDevOps Best Practices

YOUR COSMETIC CARE STARTS HERE

Find the Best Cosmetic Hospitals

Trusted • Curated • Easy

Looking for the right place for a cosmetic procedure? Explore top cosmetic hospitals in one place and choose with confidence.

“Small steps lead to big changes — today is a perfect day to begin.”

Explore Cosmetic Hospitals Compare hospitals, services & options quickly.

✓ Shortlist providers • ✓ Review options • ✓ Take the next step with confidence

Source: opensourceforu.com

What Is Cacti?

Cacti is an open-source network monitoring and graphing tool written in PHP, released under the GNU General Public License. It uses MySQL as its backend database and relies on RRDtool (Round-Robin Database tool) to store and render time-series performance data. Cacti has built-in SNMP support, making it well-suited for polling network devices such as routers, switches, and servers.

Deploying Cacti manually involves installing and configuring several interdependent components. This article walks through automating the entire process with Ansible, reducing a multi-step manual procedure to a single playbook invocation.

Environment Overview

The walkthrough uses the following environment:

  • Target host: CentOS 6.8 virtual machine running on KVM
  • Control node: Parabola GNU/Linux-libre x86_64 running Ansible 2.2.1.0
  • Guest VM IP: 192.168.122.98

Security note: SELinux is disabled in this demonstration to simplify the walkthrough. Set SELINUX=disabled in /etc/selinux/config and reboot the VM only for testing purposes. Always enable and properly configure SELinux in production environments.

Inventory and Directory Structure

The Ansible project uses the following layout:

ansible/inventory/kvm/inventory
ansible/inventory/kvm/group_vars/all/all.yml

The inventory file defines the target CentOS VM:

centos ansible_host=192.168.122.98 ansible_connection=ssh ansible_user=root ansible_password=password

Add a corresponding entry to the control node’s /etc/hosts:

192.168.122.98 centosCode language: CSS (css)

The all.yml group variables file references sensitive values from an Ansible Vault file rather than storing them in plain text:

---
mysql_cacti_password_hash: "{{ vault_mysql_cacti_password_hash }}"

mysql_username: "{{ vault_mysql_user }}"
mysql_password: "{{ vault_mysql_password }}"Code language: JavaScript (javascript)

The main playbook file cacti.yml lives under ansible/playbooks/configuration/.

Managing Secrets with Ansible Vault

Ansible Vault encrypts sensitive files so that credentials are never stored in plain text. Set your preferred editor before creating a vault file:

$ export EDITOR=nanoCode language: JavaScript (javascript)

Create the vault file to hold MySQL credentials:

$ ansible-vault create inventory/kvm/group_vars/all/vault.yml

Ansible will prompt for an encryption password, then open your editor. Enter the credentials and save the file:

---
vault_mysql_cacti_password_hash: "*528573A4E6FE4F3E8B455F2F060EB6F63ECBECAA"

vault_mysql_user: "cacti"
vault_mysql_password: "cacti123"Code language: JavaScript (javascript)

To edit the vault file later, use:

$ ansible-vault edit inventory/kvm/group_vars/all/vault.yml

Ansible will prompt for the vault password before decrypting the file for editing.

Important: The password shown above (cacti123) is a placeholder for demonstration only. Use strong, unique credentials in any real deployment.

Play 1: Install Apache HTTP Server

The first play installs the Apache web server. It updates the package cache, installs httpd and supporting utilities, starts the service, and waits until port 80 is accepting connections before continuing.

---
- name: Install web server
  hosts: centos
  gather_facts: true
  tags: [httpd]

  tasks:
    - name: Update the software package repository
      yum:
        name: '*'
        update_cache: yes

    - name: Install HTTP packages
      package:
        name: "{{ item }}"
        state: latest
      with_items:
        - wget
        - nano
        - httpd
        - httpd-devel

    - name: Start the httpd server
      service:
        name: httpd
        state: started

    - wait_for:
        port: 80Code language: JavaScript (javascript)

Play 2: Install MySQL, PHP, RRDtool, and SNMP

The second play installs Cacti’s core dependencies: MySQL, a full set of PHP extensions, RRDtool, and the SNMP utilities. After installation, both the SNMP daemon and the MySQL server are started, and the play waits for MySQL to become available on port 3306.

- name: Install MySQL, PHP packages
  hosts: centos
  become: yes
  become_method: sudo
  gather_facts: true
  tags: [database-web]

  tasks:
    - name: Install database/web packages
      package:
        name: "{{ item }}"
        state: latest
      with_items:
        - mysql
        - mysql-server
        - MySQL-python
        - php-mysql
        - php-pear
        - php-common
        - php-gd
        - php-devel
        - php
        - php-mbstring
        - php-cli
        - php-process
        - php-snmp
        - net-snmp-utils
        - net-snmp-libs
        - rrdtool

    - name: Start snmpd server
      service:
        name: snmpd
        state: started

    - name: Start mysqld server
      service:
        name: mysqld
        state: started

    - wait_for:
        port: 3306Code language: JavaScript (javascript)
Figure 4: Binary location and version
Figure 4: Binary location and version

Play 3: Install Cacti from EPEL

Cacti is available in the EPEL (Extra Packages for Enterprise Linux) repository, which is not enabled on CentOS by default. This play imports the EPEL GPG key, adds the EPEL repository, updates the package cache, installs Cacti, and creates a dedicated MySQL database user for the application.

- name: Install Cacti
  hosts: centos
  become: yes
  become_method: sudo
  gather_facts: true
  tags: [cacti]

  tasks:
    - name: Import EPEL GPG key
      rpm_key:
        key: http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
        state: present

    - name: Add YUM repo
      yum_repository:
        name: epel
        description: EPEL YUM repo
        baseurl: https://dl.fedoraproject.org/pub/epel/$releasever/$basearch/
        gpgcheck: yes

    - name: Update the software package repository
      yum:
        name: '*'
        update_cache: yes

    - name: Install cacti
      package:
        name: "{{ item }}"
        state: latest
      with_items:
        - cacti

    - name: Create cacti database user
      mysql_user:
        name: cacti
        password: "{{ mysql_cacti_password_hash }}"
        encrypted: yes
        priv: '*.*:ALL,GRANT'
        state: presentCode language: JavaScript (javascript)

Play 4: Apply MySQL Timezone Bug Fix

MySQL 5.1.73-8 (the version shipped with CentOS 6) lacks timezone data in its system tables, which causes Cacti to report an error. To resolve this, the mysql_test_data_timezone.sql file must be imported into the mysql database, and the cacti user must be granted SELECT access to the time_zone_name table.

This fix is tracked in the Cacti project as issue #242. Isolating it in its own play (or separate playbook) makes it easy to skip once you upgrade to a MySQL version where the bug no longer applies.

- name: For bug https://github.com/Cacti/cacti/issues/242
  hosts: centos
  become: yes
  become_method: sudo
  gather_facts: true
  tags: [bug]

  tasks:
    - name: Import mysql_test_data_timezone.sql
      mysql_db:
        state: import
        name: mysql
        target: /usr/share/mysql/mysql_test_data_timezone.sql

    - name: Grant privileges
      mysql_user:
        name: cacti
        append_privs: true
        priv: 'mysql.time_zone_name:SELECT'
        state: presentCode language: JavaScript (javascript)

Play 5: Configure Cacti

The final play ties everything together:

  • Creates the cacti database and imports the Cacti schema (cacti.sql)
  • Updates database credentials in /etc/cacti/db.php using the lineinfile module
  • Opens port 80 in iptables
  • Updates /etc/httpd/conf.d/cacti.conf to allow access from all hosts (adjust this for production)
  • Enables the Cacti cron poller by uncommenting its entry in /etc/cron.d/cacti
  • Restarts both MySQL and Apache, then waits for each to become available
- name: Configuration
  hosts: centos
  become: yes
  become_method: sudo
  gather_facts: true
  tags: [config]

  tasks:
    - name: Create a database for cacti
      mysql_db:
        name: cacti
        state: present

    - name: Import cacti.sql
      mysql_db:
        state: import
        name: cacti
        target: /usr/share/doc/cacti-1.0.4/cacti.sql

    - name: Update database credentials in config file
      lineinfile:
        dest: /etc/cacti/db.php
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
      with_items:
        - { regexp: '^\$database_username', line: "$database_username = '{{ mysql_username }}';" }
        - { regexp: '^\$database_password', line: "$database_password = '{{ mysql_password }}';" }

    - name: Allow port 80
      shell: iptables -I INPUT 5 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT

    - name: Update access in cacti.conf for httpd
      replace:
        dest: /etc/httpd/conf.d/cacti.conf
        regexp: "{{ item.regexp }}"
        replace: "{{ item.replace }}"
      with_items:
        - { regexp: 'Require host localhost', replace: 'Require all granted' }
        - { regexp: 'Allow from localhost', replace: 'Allow from all' }

    - lineinfile:
        dest: /etc/cron.d/cacti
        regexp: '^#(.*)$'
        line: '\1'
        backrefs: yes

    - name: Restart mysqld server
      service:
        name: mysqld
        state: restarted

    - wait_for:
        port: 3306

    - name: Restart the httpd server
      service:
        name: httpd
        state: restarted

    - wait_for:
        port: 80Code language: JavaScript (javascript)

The Cacti cron poller runs every five minutes to collect device metrics:

*/5 * * * * cacti /usr/bin/php /usr/share/cacti/poller.php > /dev/null 2>&1Code language: JavaScript (javascript)
Figure 9: Cacti Web UI
Figure 9: Cacti Web UI after a successful deployment

Running the Full Playbook

Once all plays are defined in cacti.yml, run the complete deployment with a single command. The --ask-vault-pass flag prompts for the Ansible Vault password so that encrypted credentials can be decrypted at runtime:

$ ansible-playbook -i inventory/kvm/inventory playbooks/configuration/cacti.yml --ask-vault-pass

After the playbook completes successfully, navigate to http://<VM_IP>/cacti in a browser to run the Cacti web installer. The default login credentials are admin / admin; you will be prompted to change the password immediately after first login.

Key Takeaways

  • Ansible Vault keeps database credentials out of source control while still making them available to playbooks at runtime.
  • Tagging plays (httpd, database-web, cacti, bug, config) allows you to re-run or skip individual stages during troubleshooting or upgrades.
  • Isolating bug-fix plays makes it easy to remove them when you upgrade to a version of MySQL or Cacti where the fix is no longer needed.
  • The wait_for module prevents subsequent tasks from executing before a service is actually ready to accept connections, making the playbook more reliable than simple service start tasks alone.
  • For production use, replace the broad Require all granted / Allow from all Apache directives with IP-restricted access controls, re-enable SELinux, and use firewalld or a dedicated firewall role instead of raw iptables shell commands.
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x