* docs: comprehensive audit, Spine poller overhaul, and technical refactor - Overhaul Spine documentation (Spine.md) with complete end-to-end guide: architecture, prerequisites for modern distros (EL8/9 CRB, Ubuntu 22/24, Debian 11/12, FreeBSD), SUID root permissions, secure spine.conf setup (0640), Web UI configuration (Paths, Poller type, Data Collectors tuning), MySQL max_connections sizing, and troubleshooting. - Fix broken links and anchors (Hardening, SNMP data queries, Hook API references). - Fix broken image reference in Sites.md (add-site.JPG -> add-site.png). - Fix syntax errors in documentation PHP code blocks, including invalid parenthesization, missing SQL execute quotes, and malformed comments in FAQ. - Fix DevOps installation commands: use config.php.dist, correct systemctl service names for MySQL/MariaDB/PHP-FPM, remove nonexistent php-json, add missing composer install, and correct Debian/Ubuntu systemd environment path. - Correct grammatical errors, repeated words, and typos across all markdown documents. - Remove obsolete unreferenced duplicate installation guides. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: correct reviewed examples and guidance Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: correct guidance that disagrees with the Cacti source Verified each claim against include/global_arrays.php, lib/auth.php, lib/functions.php, host_templates.php and the Spine config parser. The notable ones: api_plugin_safe_exec() does not exist on either branch, Spine reads DB_Pass rather than DB_Password, and the CDEF special data source table was missing five entries and renamed four others. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: wrap Spine prose and fence the connection sizing formula The formula's bare asterisks rendered as emphasis, dropping the multiplication signs. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * chore: refresh copyright year in scripts and issue templates Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
11 KiB
Spine
Spine is the high-speed, multi-threaded poller replacement for cmd.php.
Written in C, it provides dramatic performance improvements for data collection.
Where cmd.php can take several minutes to poll large installations, Spine
routinely polls tens of thousands of data sources in well under 60 seconds on
modern multi-core hardware.
Spine does not replace your cron or systemd scheduling entries. The scheduler
entry point remains poller.php. When Spine is selected as the poller engine,
poller.php launches Spine processes to perform the data collection across all
configured devices.
Spine Architecture and Operating Principles
- Multi-Threaded Polling: Spine executes a thread-per-device polling model within multiple concurrent processes, allowing hundreds of metrics to be collected simultaneously.
- Persistent PHP Script Server: For custom scripts, Spine starts and
maintains long-running PHP script server processes (
script_server.php). This eliminates the heavy overhead of repeatedly spawning the PHP binary for every individual script item. - Privilege Separation (SUID Root): To perform raw ICMP pings without
invoking external ping utilities, Spine requires raw socket access. Spine
achieves this by shipping with the SUID root bit enabled (
chmod u+s). At runtime, Spine strictly limits elevated privileges: it elevates effective UID only during raw socket creation (serialized by an internal lock) and immediately drops back to the calling user (such asapacheorwww-data). - Direct Database Communication: Spine queries the Cacti database directly via the MySQL/MariaDB client library to retrieve polling targets and writes collected data directly into the poller cache and RRD files.
Installing Spine
Because Spine is written in C, it must be compiled against your local database and Net-SNMP client development libraries.
Prerequisites by Distribution
Enterprise Linux 8 & 9 (RHEL, Rocky Linux, AlmaLinux)
Spine requires development headers found in the CodeReady Builder (crb)
repository on EL 9, or powertools on EL 8:
-
Enable the repository:
# On EL 9 (RHEL 9, Rocky Linux 9, AlmaLinux 9): dnf config-manager --set-enabled crb # On EL 8 (RHEL 8, Rocky Linux 8, AlmaLinux 8): dnf config-manager --set-enabled powertools -
Install compiler tools and development libraries:
dnf install -y gcc autoconf automake libtool dos2unix help2man \ openssl-devel mariadb-devel net-snmp-devel
Ubuntu and Debian
On Ubuntu (22.04 LTS / 24.04 LTS) and Debian (11 / 12):
apt-get update
apt-get install -y build-essential autoconf automake libtool dos2unix help2man \
libssl-dev default-libmysqlclient-dev librrd-dev libsnmp-dev
FreeBSD
On FreeBSD, Spine can be installed directly from pre-built packages or compiled from Ports:
# Using binary packages:
pkg install spine
# Or via FreeBSD Ports:
cd /usr/ports/net-mgmt/spine
make install clean
Downloading and Compiling Spine
Important
: The version of Spine MUST match your Cacti version. Use Spine 1.2.31 with Cacti 1.2.31.
-
Download the release archive matching your Cacti version (replace
X.Y.Zwith your version):cd /tmp wget https://github.com/Cacti/spine/archive/refs/tags/release/X.Y.Z.tar.gz -O cacti-spine-X.Y.Z.tar.gz tar -zxvf cacti-spine-X.Y.Z.tar.gz cd spine-release-X.Y.Z -
Bootstrap, configure, and compile:
./bootstrap ./configure make make installBy default, Spine is installed to
/usr/local/spine. -
Set binary permissions (SUID Root):
Spine must be owned by
rootwith the setuid bit set so it can open raw ICMP sockets:chown root:root /usr/local/spine/bin/spine chmod u+s /usr/local/spine/bin/spine
Configuring spine.conf
Spine reads its database connection parameters from spine.conf.
-
Create the configuration file from the template:
cp /usr/local/spine/etc/spine.conf.dist /usr/local/spine/etc/spine.conf -
Secure the file permissions:
Because
spine.confcontains the database password in plaintext, restrict permissions so onlyrootand the web server / poller group can read it:# On RHEL / Rocky / AlmaLinux (web group: apache): chown root:apache /usr/local/spine/etc/spine.conf chmod 0640 /usr/local/spine/etc/spine.conf # On Ubuntu / Debian (web group: www-data): chown root:www-data /usr/local/spine/etc/spine.conf chmod 0640 /usr/local/spine/etc/spine.conf -
Edit
/usr/local/spine/etc/spine.confand update the database settings to match your Cacticonfig.php:DB_Host localhost DB_Database cacti DB_User cactiuser DB_Pass cactiuser_password DB_Port 3306 #DB_UseSSL 0 #RDB_SSL_Key #RDB_SSL_Cert #RDB_SSL_CA
Testing Spine from the Command Line
Before activating Spine in the Cacti web interface, verify that it can connect to the database, query devices, and send ICMP pings without error.
1. Read-Only Global Test
Run Spine in read-only test mode (-R) with summary statistics (-S) and
verbosity level 3 (-V 3). In this mode, Spine polls devices but does not write
results into the database:
/usr/local/spine/bin/spine -R -V 3 -S
Verify that the output shows Spine reading /usr/local/spine/etc/spine.conf and
completes with: SPINE: Execution Time: ... Total Hosts: ...
2. Device-Specific Test
To test a single device without polling your entire infrastructure, pass the
host ID range using -f <host_id> -l <host_id>:
/usr/local/spine/bin/spine -R -f 1 -l 1 -V 5
Check the verbose output for ICMP ping success, SNMP retrieval, and script execution without errors.
Enabling Spine in the Cacti Web UI
Once command-line verification passes, activate Spine in Cacti:
Step 1: Set the Binary Path
- Log in to Cacti as an administrator.
- Navigate to Console > Configuration > Settings > Paths.
- Under Spine Poller File Path (or Spine Binary File Location), enter:
/usr/local/spine/bin/spine - Optionally, set Spine Config File Path to
/usr/local/spine/etc/spine.conf(if left blank, Spine automatically searches its sibling../etcdirectory). - Verify that Cacti indicates
[OK: FILE FOUND]. - Click Save.
Step 2: Switch the Poller Engine
- Navigate to Console > Configuration > Settings > Poller.
- Change the Poller Type dropdown from
cmd.phptospine. - Click Save.
The next scheduled polling cycle by poller.php will immediately invoke Spine.
Tuning Spine for Optimal Performance
Spine parameters are configured at three distinct levels:
1. System-Level Settings
Configured under Console > Configuration > Settings > Poller:
| Parameter | Recommended Value | Description |
|---|---|---|
| Script and Script Server Timeout | 25 seconds | Maximum duration Spine waits for an external script or Script Server call before timing out and returning NaN. Must be less than your polling interval. |
2. Data Collector-Level Settings
Configured under Console > Data Collection > Data Collectors (select your collector):
| Parameter | Recommended Value | Description |
|---|---|---|
| Maximum Concurrent Poller Processes | 1–2 per CPU core | Number of Spine processes launched concurrently. For a 4-core system, 4 to 8 processes is typical. |
| Maximum Threads per Process | 10–20 threads | Number of concurrent threads per process. Do not set higher than 50, as excessive context switching degrades performance. |
| Number of PHP Script Servers | 2–5 per process | Number of persistent script_server.php workers maintained per Spine process to handle script data queries. |
3. Device-Level Overrides
Configured on individual devices under Console > Management > Devices:
| Parameter | Default | Description |
|---|---|---|
| Device Threads | 1 | Number of concurrent threads dedicated to polling this specific device. Increase for high-density switches or routers with hundreds of interfaces. |
| Maximum OIDs Per Get Request | 10–60 | Number of SNMP OIDs bundled into a single SNMP GET request. Higher values increase throughput over high-latency links, provided the device agent supports it. |
Database Connection Sizing (max_connections)
Each concurrent Spine process, thread, and script server requires database
connections. Ensure your MySQL/MariaDB max_connections limit is sized
adequately:
Total Connections >= (Data Collectors * Processes * (Threads + Script Servers + 2)) + 50
If this setting is too low, Spine will fail with FATAL: Connection to MySQL database failed.
Edit /etc/my.cnf.d/server.cnf (or /etc/mysql/mariadb.conf.d/50-server.cnf)
and set:
[mysqld]
max_connections = 500
Restart the database server after changing max_connections.
Security Policies (SELinux & AppArmor)
SELinux (RHEL, Rocky Linux, AlmaLinux)
If SELinux is enforcing, allow the web server and poller to establish outgoing network connections:
setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1
Ensure the Spine binary has the appropriate system binary context (bin_t):
semanage fcontext -a -t bin_t "/usr/local/spine/bin/spine"
restorecon -v /usr/local/spine/bin/spine
AppArmor (Ubuntu / Debian)
If using a confined profile for Apache or PHP-FPM, allow execution of the Spine binary:
# Add to /etc/apparmor.d/local/usr.sbin.apache2:
/usr/local/spine/bin/spine rix,
/usr/local/spine/etc/spine.conf r,
Reload AppArmor:
apparmor_parser -r /etc/apparmor.d/usr.sbin.apache2
Troubleshooting Spine
Common Errors and Solutions
1. FATAL: Unable to read configuration file! (Spine init)
-
Cause: Spine cannot locate or read
spine.conf. -
Fix: Ensure
/usr/local/spine/etc/spine.confexists and is readable by the user executing the poller (e.g.apacheorwww-data):ls -la /usr/local/spine/etc/spine.conf chmod 640 /usr/local/spine/etc/spine.conf
2. DEBUG: Falling back to UDP Ping Due to SetUID Issues
-
Cause: Spine is missing the SUID root permission required to open raw ICMP sockets.
-
Fix: Restore SUID permissions on the binary:
chown root:root /usr/local/spine/bin/spine chmod u+s /usr/local/spine/bin/spine
3. FATAL: Connection to MySQL database failed
- Cause: Incorrect database credentials in
spine.conf, database host unreachable, or MySQL/MariaDBmax_connectionsreached. - Fix: Test database connectivity manually with
mysql -u cactiuser -p -h localhost cactiand increasemax_connectionsin your MySQL configuration.
4. Verification in Cacti Log
To confirm Spine is functioning in production, open Console > Utilities > System Utilities > View Cacti Log. Look for the poller completion summary line:
SYSTEM STATS: Time:12.3456 Method:spine Processes:4 Threads:40 Hosts:250 HostsPerProcess:63 DataSources:12400 RRDsProcessed:6200
If the log displays Method:spine, Spine is running successfully.
Copyright (c) 2004-2026 The Cacti Group
