How to Self-Host Cacti with Docker Compose

Docker Compose Configuration

Cacti does not have an official Docker image — the project predates Docker conventions. The most reliable community image is smcline06/cacti, which bundles Apache, PHP, Spine poller, and SNMP tools into a single container alongside a MariaDB database.

Create a docker-compose.yml file:

services:
  cacti:
    image: smcline06/cacti:1.2.17
    container_name: cacti
    restart: unless-stopped
    ports:
      - "8443:443"
      - "8080:80"
    environment:
      # Database connection
      DB_NAME: cacti_master
      DB_USER: cactiuser
      DB_PASS: "${DB_PASSWORD}"
      DB_HOST: cacti-db
      DB_PORT: "3306"
      DB_ROOT_PASS: "${DB_ROOT_PASSWORD}"
      # Auto-create database on first boot
      INITIALIZE_DB: "1"
      # Timezone (must match PHP and MariaDB)
      TZ: "UTC"
    volumes:
      - cacti_data:/var/www/html/cacti
      - cacti_spine:/var/www/html/spine
      - cacti_backups:/var/www/html/backups
    depends_on:
      cacti-db:
        condition: service_healthy
    networks:
      - cacti

  cacti-db:
    image: mariadb:11.4.10
    container_name: cacti-db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
      MYSQL_DATABASE: cacti_master
      MYSQL_USER: cactiuser
      MYSQL_PASSWORD: "${DB_PASSWORD}"
    volumes:
      - cacti_db:/var/lib/mysql
    command: >
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci
      --max_connections=200
      --max_heap_table_size=256M
      --tmp_table_size=256M
      --innodb_buffer_pool_size=1G
      --innodb_doublewrite=OFF
      --innodb_flush_log_at_timeout=3
      --innodb_read_io_threads=32
      --innodb_write_io_threads=16
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s
    networks:
      - cacti

networks:
  cacti:
    driver: bridge

volumes:
  cacti_data:
  cacti_spine:
  cacti_backups:
  cacti_db:

Create a .env file alongside:

# CHANGE THESE — use strong, unique passwords
DB_PASSWORD=change_me_strong_password_here
DB_ROOT_PASSWORD=change_me_root_password_here

Start the stack:

docker compose up -d

What Is Cacti?

Cacti is an RRDtool-based network graphing platform that polls SNMP-enabled devices on a schedule and renders the data as graphs. It’s been the go-to SNMP graphing solution since 2001, used primarily for monitoring bandwidth utilization on switches, routers, and servers. Think of it as a web frontend for RRDtool with built-in SNMP polling, device management, and user access control. Official site

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 2 GB of RAM minimum (4 GB recommended for 100+ devices)
  • 10 GB of free disk space
  • Network devices with SNMP enabled (v2c or v3)
  • A domain name (optional, for remote access)

Initial Setup

  1. First boot takes 5–10 minutes while the database schema imports. Watch progress:
    docker compose logs -f cacti
  2. Open https://your-server-ip:8443/cacti in your browser (HTTPS with self-signed cert).
  3. Accept the license agreement.
  4. The installer checks PHP dependencies, database connectivity, and file permissions. All should pass with the Docker image.
  5. Select New Primary Server installation type.
  6. Log in with default credentials: admin / admin. You’ll be prompted to change the password immediately.

Add Your First Device

  1. Go to Management → Devices → Add
  2. Enter the device IP and SNMP community string (default: public)
  3. Select a device template (e.g., Cisco Router, Linux Server, Net-SNMP Device)
  4. Click Create and wait for Cacti to query the device
  5. Once SNMP data is confirmed, go to Create → New Graphs and select the interfaces you want to graph

Configuration

Spine Poller

Cacti’s default poller (cmd.php) is slow — it polls devices sequentially. The Spine poller (included in the Docker image) polls in parallel using multithreaded C code.

Enable Spine:

  1. Go to Configuration → Settings → Poller
  2. Change Poller Type to spine
  3. Set Maximum Concurrent Poller Processes based on your CPU cores (4–8 is typical)
  4. Cacti polls every 5 minutes by default — this is the standard RRDtool interval

SNMP v3 Configuration

For secure SNMP polling:

  1. When adding a device, select SNMP Version 3
  2. Configure:
    • Security Level: authPriv (recommended)
    • Auth Protocol: SHA
    • Auth Passphrase: your SNMP v3 auth password
    • Privacy Protocol: AES
    • Privacy Passphrase: your SNMP v3 privacy password

Graph Templates

Cacti ships with templates for common metrics:

  • Interface traffic (in/out bytes, errors, discards)
  • CPU utilization (via Host MIB)
  • Memory usage (via Host MIB)
  • Disk space (via Host MIB)
  • Temperature sensors (via Entity Sensor MIB)

For custom OIDs, create a Data Query or Data Template under Configuration → Data Queries.

Advanced Configuration

Threshold Alerting (Thold Plugin)

Cacti doesn’t include alerting out of the box — you need the Thold plugin:

  1. Go to Configuration → Plugins → Install/Enable Thold
  2. Create threshold: Management → Thresholds → Add
  3. Set high/low watermarks for bandwidth, CPU, etc.
  4. Configure email notifications in Configuration → Settings → Mail/DNS

Remote Pollers

For monitoring devices across multiple sites:

services:
  cacti-remote:
    image: smcline06/cacti:1.2.17
    environment:
      REMOTE_POLLER: "1"
      DB_HOST: central-db-host
      RDB_HOST: central-db-host
      # ... remote database credentials

Remote pollers report back to the central Cacti instance, enabling distributed monitoring.

Weathermap Plugin

Visualize network topology with live bandwidth overlays:

  1. Install the Weathermap plugin via Cacti’s plugin management
  2. Create network maps showing device interconnections
  3. Associate graph data sources with map links
  4. Maps update automatically with each polling cycle

Reverse Proxy

The Docker image includes Apache with a self-signed certificate. For proper TLS:

server {
    listen 443 ssl;
    server_name cacti.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/cacti.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cacti.yourdomain.com/privkey.pem;

    location / {
        proxy_pass https://127.0.0.1:8443;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Reverse Proxy Setup

Backup

Cacti stores data in two locations:

  • MariaDB — device configurations, user accounts, graph templates, thresholds
  • RRD files — historical graph data (in the cacti_data volume under rra/)
# Backup database
docker exec cacti-db mariadb-dump -u root -p"${DB_ROOT_PASSWORD}" cacti_master > cacti-db-backup.sql

# Backup RRD files and configs
docker cp cacti:/var/www/html/cacti/rra ./cacti-rra-backup
docker cp cacti:/var/www/html/cacti/scripts ./cacti-scripts-backup

RRD files are compact (fixed-size, typically 100–500 KB per data source) and are the most important data to preserve.

Backup Strategy

Troubleshooting

Graphs show “No data” or are blank

Symptom: Device added and SNMP works, but graphs remain empty. Fix: Wait at least two polling cycles (10 minutes with default 5-minute interval). RRDtool requires two data points to draw a line. If still blank, check that the correct data query was associated with the device and that SNMP community string matches.

Spine poller not running

Symptom: Poller set to Spine but polling is slow or not happening. Fix: Verify Spine binary exists and is executable:

docker exec cacti which spine
docker exec cacti spine --version

Check cron is running inside the container: docker exec cacti crontab -l

SNMP timeouts

Symptom: Devices show “SNMP error” or “Down” status. Fix: Test SNMP from inside the container:

docker exec cacti snmpwalk -v2c -c public DEVICE_IP sysDescr.0

If this fails, the issue is network connectivity or SNMP configuration on the device. Ensure UDP port 161 is accessible from the container.

Database connection errors on startup

Symptom: Cacti container fails to start, logs show database connection refused. Fix: The depends_on with service_healthy ensures MariaDB is ready, but if the healthcheck fails, verify the database passwords match between the Cacti and MariaDB containers. Check MariaDB logs: docker compose logs cacti-db

High CPU during polling

Symptom: CPU spikes every 5 minutes during poll cycle. Fix: Reduce Maximum Concurrent Poller Processes in Spine settings. For a 2-core VPS, set to 2–4 threads. Also verify you’re using Spine, not cmd.php — PHP polling is significantly more CPU-intensive.

Resource Requirements

MetricValue
RAM (idle)~300 MB (Cacti + MariaDB)
RAM (100 devices)~800 MB
RAM (500+ devices)2–4 GB
CPULow (spikes during polling cycles)
Disk per device~5–50 MB (RRD files, depends on data sources)
Minimum total disk10 GB

RRD files are inherently space-efficient — they use fixed-size round-robin databases that automatically consolidate old data. A Cacti instance monitoring 100 switches with 20 interfaces each uses roughly 2–5 GB of RRD storage total, regardless of how long it’s been running.

Verdict

Cacti does one thing well: SNMP-based network graphing. If your primary need is monitoring bandwidth utilization across switches and routers with beautiful RRDtool graphs, Cacti delivers with minimal resource overhead. The Spine poller handles large-scale polling efficiently, and the fixed-size RRD storage model means disk usage stays predictable.

For new deployments in 2026, consider whether Zabbix or LibreNMS would serve you better — both offer SNMP graphing plus alerting, auto-discovery, and modern web interfaces. Cacti’s strength is its simplicity and 20+ years of proven reliability. If you don’t need alerting or auto-discovery, Cacti remains a perfectly valid choice that runs on minimal hardware.

FAQ

Is Cacti still maintained?

Yes, but development is slow. The community Docker image (smcline06/cacti) was last updated in 2021 with version 1.2.17. The upstream Cacti project continues receiving patches, but the Docker ecosystem lags behind significantly. Major new features are rare.

Can Cacti monitor things besides SNMP?

Yes, through custom data input methods and scripts. You can create scripts that query any data source (APIs, databases, files) and feed the results into RRDtool via Cacti’s data input system. But SNMP polling is the core strength.

Why is there no official Docker image?

Cacti predates modern Docker practices. The project maintains installation guides for bare-metal Linux but hasn’t invested in official container images. Community images like smcline06/cacti fill this gap reliably.

How does Cacti compare to LibreNMS?

LibreNMS is the modern successor to the same concept — SNMP-based network monitoring with auto-discovery, alerting, and a modern web UI. LibreNMS is the better choice for new deployments. See our Zabbix vs Cacti comparison for a detailed breakdown.

Comments