This guide provides a complete Ansible playbook to install Cacti network monitoring with MySQL/MariaDB database, SNMP support, and poller configuration.
Current Cacti version: 1.2.30
Create a file named cacti.yml:
---
- name: Install and Configure Cacti Network Monitoring
hosts: cacti
become: true
vars:
cacti_version: "1.2.30"
cacti_port: 80
db_type: "mariadb"
db_name: "cacti"
db_user: "cacti"
db_password: "cacti_secure_password_123" # Change this!
db_root_password: "root_secure_password_456" # Change this!
cacti_admin_password: "cacti_admin_789" # Change this!
snmp_community: "public"
poller_interval: 60
tasks:
# =====================
# Prerequisites
# =====================
- name: Install prerequisites (Debian/Ubuntu)
apt:
name:
- apache2
- libapache2-mod-php
- php
- php-mysql
- php-gd
- php-snmp
- php-xml
- php-mbstring
- php-curl
- php-ldap
- php-zip
- php-intl
- mariadb-server
- mariadb-client
- snmp
- libsnmp-dev
- rrdtool
- librrds-perl
- wget
- unzip
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install prerequisites (RHEL/CentOS)
yum:
name:
- httpd
- php
- php-mysqlnd
- php-gd
- php-snmp
- php-xml
- php-mbstring
- php-curl
- php-ldap
- mariadb-server
- mariadb
- net-snmp
- net-snmp-utils
- rrdtool
- wget
- unzip
state: present
when: ansible_os_family == "RedHat"
# =====================
# Database Setup
# =====================
- name: Start and enable MariaDB
systemd:
name: "{{ 'mariadb' if ansible_os_family == 'Debian' else 'mariadb-server' }}"
enabled: true
state: started
- name: Set MariaDB root password
mysql_user:
name: root
password: "{{ db_root_password }}"
host_all: true
login_unix_socket: /var/run/mysqld/mysqld.sock
when: ansible_os_family == "Debian"
- name: Create Cacti database
mysql_db:
name: "{{ db_name }}"
encoding: utf8mb4
collation: utf8mb4_unicode_ci
login_unix_socket: /var/run/mysqld/mysqld.sock
login_user: root
login_password: "{{ db_root_password }}"
when: ansible_os_family == "Debian"
- name: Create Cacti database user
mysql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
priv: "{{ db_name }}.*:ALL"
host: localhost
login_unix_socket: /var/run/mysqld/mysqld.sock
login_user: root
login_password: "{{ db_root_password }}"
when: ansible_os_family == "Debian"
# =====================
# Cacti Installation
# =====================
- name: Download Cacti
get_url:
url: "https://www.cacti.net/downloads/cacti-{{ cacti_version }}.tar.gz"
dest: /tmp/cacti-{{ cacti_version }}.tar.gz
mode: '0644'
- name: Extract Cacti
unarchive:
src: /tmp/cacti-{{ cacti_version }}.tar.gz
dest: /var/www/html
remote_src: true
creates: "/var/www/html/cacti-{{ cacti_version }}"
- name: Create Cacti symlink
file:
src: "/var/www/html/cacti-{{ cacti_version }}"
dest: /var/www/html/cacti
state: link
force: true
- name: Set ownership for Cacti
file:
path: /var/www/html/cacti
owner: www-data
group: www-data
recurse: true
when: ansible_os_family == "Debian"
- name: Set ownership for Cacti (RHEL)
file:
path: /var/www/html/cacti
owner: apache
group: apache
recurse: true
when: ansible_os_family == "RedHat"
# =====================
# Cacti Configuration
# =====================
- name: Configure Cacti database connection
copy:
dest: /var/www/html/cacti/include/config.php
owner: "{{ 'www-data' if ansible_os_family == 'Debian' else 'apache' }}"
group: "{{ 'www-data' if ansible_os_family == 'Debian' else 'apache' }}"
mode: '0640'
content: |
<?php
/*
* Make sure these values match your actual database connection
*/
$database_type = 'mysql';
$database_default = '{{ db_name }}';
$database_hostname = 'localhost';
$database_username = '{{ db_user }}';
$database_password = '{{ db_password }}';
$database_port = '3306';
$database_ssl = false;
$database_ssl_key = '';
$database_ssl_cert = '';
$database_ssl_ca = '';
$database_ssl_capath = '';
$database_ssl_cipher = '';
$database_retries = 3;
$database_persist = false;
$url_path = '/cacti/';
?>
- name: Import Cacti database schema
mysql:
login_unix_socket: /var/run/mysqld/mysqld.sock
login_user: root
login_password: "{{ db_root_password }}"
name: "{{ db_name }}"
target: /var/www/html/cacti/cacti.sql
when: ansible_os_family == "Debian"
register: schema_import
- name: Create Cacti admin user in database
mysql:
login_unix_socket: /var/run/mysqld/mysqld.sock
login_user: root
login_password: "{{ db_root_password }}"
name: "{{ db_name }}"
query: "INSERT INTO user_auth (username, password, must_change_password, realm) VALUES ('admin', SHA2('{{ cacti_admin_password }}', 256), 0, 0) ON DUPLICATE KEY UPDATE password=SHA2('{{ cacti_admin_password }}', 256)"
when: ansible_os_family == "Debian"
# =====================
# Apache Configuration
# =====================
- name: Create Apache configuration for Cacti
copy:
dest: "/etc/{{ 'apache2/conf-available' if ansible_os_family == 'Debian' else 'httpd/conf.d' }}/cacti.conf"
owner: root
group: root
mode: '0644'
content: |
<Directory /var/www/html/cacti>
Options +FollowSymLinks
AllowOverride None
Require all granted
<IfModule mod_php.c>
php_flag register_globals off
php_flag magic_quotes_gpc off
php_flag allow_url_fopen off
</IfModule>
</Directory>
# Poller access
<Directory /var/www/html/cacti/poller>
Require all granted
</Directory>
- name: Enable Cacti Apache configuration (Debian/Ubuntu)
command: a2enconf cacti
args:
creates: /etc/apache2/conf-enabled/cacti.conf
when: ansible_os_family == "Debian"
notify: Restart Apache
- name: Restart Apache (Debian/Ubuntu)
systemd:
name: apache2
enabled: true
state: restarted
when: ansible_os_family == "Debian"
- name: Restart httpd (RHEL/CentOS)
systemd:
name: httpd
enabled: true
state: restarted
when: ansible_os_family == "RedHat"
# =====================
# Cron Configuration
# =====================
- name: Create Cacti poller cron job
cron:
name: "Cacti Poller"
job: "/usr/bin/php /var/www/html/cacti/poller.php > /dev/null 2>&1"
minute: "*/{{ (poller_interval // 60) | int }}"
user: "{{ 'www-data' if ansible_os_family == 'Debian' else 'apache' }}"
# =====================
# SNMP Configuration
# =====================
- name: Configure SNMP community
lineinfile:
path: /etc/snmp/snmp.conf
regexp: "^#?default"
line: "default {{ snmp_community }}"
failed_when: false
# =====================
# Firewall Configuration
# =====================
- name: Configure firewall (UFW)
ufw:
rule: allow
port: "{{ cacti_port }}"
proto: tcp
comment: "Cacti web interface"
when: ansible_os_family == "Debian"
failed_when: false
- name: Configure firewall (firewalld)
firewalld:
service: http
permanent: true
immediate: true
state: enabled
when: ansible_os_family == "RedHat"
failed_when: false
# =====================
# Permissions
# =====================
- name: Set proper permissions on Cacti directories
file:
path: "{{ item }}"
owner: "{{ 'www-data' if ansible_os_family == 'Debian' else 'apache' }}"
group: "{{ 'www-data' if ansible_os_family == 'Debian' else 'apache' }}"
mode: '0755'
recurse: true
loop:
- /var/www/html/cacti/log
- /var/www/html/cacti/resource
failed_when: false
- name: Wait for Cacti to be ready
wait_for:
port: "{{ cacti_port }}"
delay: 5
timeout: 120
- name: Display Cacti status
debug:
msg: |
Cacti {{ cacti_version }} installed successfully!
Web Interface: http://{{ ansible_default_ipv4.address | default(ansible_host) }}/cacti
Username: admin
Password: {{ cacti_admin_password }}
IMPORTANT: Change the default password after first login!
Poller runs every {{ poller_interval }} seconds via cron.
handlers:
- name: Restart Apache
systemd:
name: "{{ 'apache2' if ansible_os_family == 'Debian' else 'httpd' }}"
state: restarted
---
cacti:
hosts:
cacti-server:
ansible_host: 192.168.1.111
ansible_user: ansible
ansible_become: true
# Test connectivity
ansible all -i inventory.yml -m ping
# Run the Cacti playbook
ansible-playbook -i inventory.yml cacti.yml
# Run with custom passwords
ansible-playbook -i inventory.yml cacti.yml \
-e "db_password=MySecureDBPass123" \
-e "db_root_password=RootSecurePass456" \
-e "cacti_admin_password=AdminSecurePass789"
# Check Apache status
ssh cacti-server "sudo systemctl status apache2"
# Check MariaDB status
ssh cacti-server "sudo systemctl status mariadb"
# Test web interface
curl -I http://cacti-server/cacti
# Access web UI
# http://cacti-server/cacti
# Complete the installation wizard
- name: Add network devices to Cacti
hosts: cacti
become: true
vars:
cacti_db_name: "cacti"
cacti_db_user: "cacti"
cacti_db_password: "cacti_secure_password_123"
tasks:
- name: Add device via Cacti CLI
shell: |
php /var/www/html/cacti/cli/add_device.php \
--hostname={{ item.ip }} \
--description="{{ item.name }}" \
--snmp_community=public \
--snmp_version=2 \
--snmp_port=161 \
--snmp_timeout=500 \
--snmp_retries=3 \
--availability_method=ping \
--ping_method=icmp \
--ping_retries=2 \
--ping_timeout=400 \
--snmp_community=public
args:
chdir: /var/www/html/cacti
loop: "{{ devices_to_monitor }}"
register: add_device_result
changed_when: "'Device Added' in add_device_result.stdout"
- name: Display device addition status
debug:
msg: "Added {{ devices_to_monitor | length }} devices to Cacti"
- name: Configure SNMP on network devices
hosts: network_devices
gather_facts: false
vars:
snmp_community: "monitoring_public"
snmp_location: "Data Center"
snmp_contact: "admin@example.com"
tasks:
- name: Configure SNMP on Cisco devices
ios_config:
lines:
- snmp-server community {{ snmp_community }} RO
- snmp-server location {{ snmp_location }}
- snmp-server contact {{ snmp_contact }}
- snmp-server enable traps
match: none
when: ansible_network_os == 'cisco.ios.ios'
- name: Configure SNMP on Juniper devices
junos_config:
lines:
- set snmp community {{ snmp_community }} authorization read-only
- set snmp location {{ snmp_location }}
- set snmp contact {{ snmp_contact }}
when: ansible_network_os == 'junipernetworks.junos.junos'
# Check Apache logs
sudo tail -f /var/log/apache2/error.log # Debian/Ubuntu
sudo tail -f /var/log/httpd/error_log # RHEL/CentOS
# Check PHP errors
sudo tail -f /var/log/php/error.log
# Verify database connection
mysql -u cacti -p -e "SELECT version();"
# Check cron logs
sudo grep CRON /var/log/syslog
# Run poller manually
sudo -u www-data php /var/www/html/cacti/poller.php
# Check poller logs
sudo tail -f /var/www/html/cacti/log/cacti.log
# Test SNMP connection
snmpwalk -v2c -c public device-ip
# Check SNMP daemon
sudo systemctl status snmpd
# Verify SNMP configuration
sudo cat /etc/snmp/snmpd.conf
Beyond this playbook, we offer:
Contact our automation team: office@linux-server-admin.com