diff --git a/Command-Line-Scripts.md b/Command-Line-Scripts.md
index ddda4cf1..09b3a3d2 100644
--- a/Command-Line-Scripts.md
+++ b/Command-Line-Scripts.md
@@ -449,17 +449,11 @@ stick to the listing options
```console
shell>php -q add_device.php --list-host-templates
-
-Valid Host Templates: (id, name)
-1 Generic SNMP-enabled Host
-3 ucd/net SNMP Host
-4 Karlnet Wireless Bridge
-5 Cisco Router
-6 Netware 4/5 Server
-7 Windows 2000/XP Host
-8 Local Linux Machine
```
+The command lists the templates installed in your database. Use those
+IDs rather than assuming the IDs from another installation.
+
Why are those `Host Templates` of such importance for this script? Well, when
using this script to add a new device, there are 3 required parameters. The
`description` and the `device ip address` are of course left to you. But for
diff --git a/General-Installing-Instructions.md b/General-Installing-Instructions.md
index 3be2f6f1..920ef8dc 100644
--- a/General-Installing-Instructions.md
+++ b/General-Installing-Instructions.md
@@ -1,52 +1,30 @@
# General Installing Instructions
-> **Note**: As of Cacti 1.2.31, PHP 8.1 is required and PHP Composer is
-> required. Composer installs the vendor libraries and keeps them up to date.
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
-Make sure the following packages are installed according to your operating
-system's requirements. Verify that Apache and MySQL/MariaDB start at system
-startup.
+Install the packages required by the selected operating system and verify that
+the configured web server, PHP handler, and database start at boot.
+## Containers
-### A special note on installing Cacti in LXC containers such as those found on Proxmox
-
-We recommend creating a privileged container. You may need to update your
-container's config file with
-
-```console
-lxc.apparmor.profile: unconfined
-```
-
-This will allow ICMP ping and other functions to work.
-
-A tested configuration file like the one below should work. Tune it to your own
-needs and standards.
-
-```console
-arch: amd64
-cores: 2
-hostname: cacti
-memory: 2048
-net0: name=eth0,bridge=vmbr0,firewall=1,hwaddr=mac-id,ip=dhcp,type=veth
-ostype: ubuntu
-rootfs: local-lvm:vm-110-disk-0,size=8G
-swap: 2048
-lxc.apparmor.profile: unconfined
-```
-
+Use an unprivileged container with its normal security profile where possible.
+Diagnose the specific ICMP, socket, or filesystem permission that fails and
+adjust only the required capability or policy. Do not remove AppArmor
+confinement or make the entire container privileged as a general prerequisite.
## Required Packages for Most Operating Systems
Depending on your operating system and PHP version, certain packages are
-required for Cacti. The largest variable in these requirements comes with
-regard to PHP and MySQL/MariaDB.
+required for Cacti. The largest variable in these requirements come with regard
+to PHP and MySQL/MariaDB.
Installation requirements include the packages below. The installation of these
packages will vary by operating system.
### Base OS
-- Apache, IIS, or nginx
+- apache, IIS, or nginx
- net-snmp, net-snmp-utils
@@ -63,7 +41,9 @@ packages will vary by operating system.
### Database
-MySQL versions 8.0/8.4+ and MariaDB versions 10.5 through 11.x+ are supported.
+Use the database versions and configuration described in
+[Requirements](Requirements.md). The development branch recommends MySQL 8.4+
+or MariaDB 10.11+. Check the installed server with the Cacti installer.
- mysql
@@ -81,103 +61,165 @@ or
### PHP Modules
-The installation of these modules varies by OS. Use the `php -m` command to
-verify that they are installed.
-
-- posix
-
-- session
-
-- sockets
-
-- PDO
+Use PHP 8.3 or later in the PHP 8 series and the extensions listed in
+[Requirements](Requirements.md). Verify the CLI with `php -v` and `php -m` and
+check web PHP separately in the installer. Source deployments also need
+Composer and all extensions required by the selected revision's lock file.
+Run `composer install --no-dev` as the deployment owner, then
+`composer check-platform-reqs --no-dev`. Use the lock file rather than updating
+dependencies during installation.
-- pdo_mysql
+### Systems using PHP-FPM
-- xml
+After changing PHP configuration, test and restart the actual FPM service.
+Service names can be versioned, for example on Debian and Ubuntu. Check the
+installed unit rather than assuming that `php-fpm` is the service name. Confirm
+its socket path and permissions match the web-server handler.
-- ldap
-
-- mbstring
-
-- pcre
-
-- json
+## FreeBSD
-- openssl
+Use a patched release listed in [supported operating systems][supported-os].
+Choose binary packages or the Ports Collection using the
+[FreeBSD Handbook][freebsd-ports]. Run package and service administration
+commands as root. Use the dedicated poller account for collection.
-- gd
+### Choose the Cacti version and PHP flavor
-- zlib
+The FreeBSD `net-mgmt/cacti` port currently packages Cacti 1.2.31, not the
+unreleased Cacti 1.3 development branch covered by this manual. For a packaged
+release, follow its installed instructions and the [1.2.x manual][manual-12].
+For development source, meet [Requirements](Requirements.md) and follow the
+source-install steps below using FreeBSD paths and service configuration.
+Do not overlay a source checkout onto files owned by `pkg`.
-### PHP Optional Modules
+Cacti packages have PHP flavors. Discover the names available in your
+configured repository before selecting one:
-The following modules are optional, but preferred to be installed.
+```sh
+pkg update
+pkg search -S name -x '^cacti(-php[0-9]+)?$'
+```
-- snmp
+For example, if the repository offers `cacti-php84` and the installation uses
+PHP 8.4, review and install that flavor:
-- gmp (for plugin support)
+```sh
+pkg install -n cacti-php84
+pkg install cacti-php84
+pkg info -D cacti-php84
+pkg info -l cacti-php84
+```
-- com or dotnet (Windows only)
+Replace the example name with the selected flavor. Read the transaction before
+accepting it, particularly changes to PHP extensions and database clients.
+Dependencies do not configure a web server or create a database server. Set up
+a compatible local MariaDB/MySQL service, or an existing remote database,
+and configure Apache or nginx with the matching PHP handler separately.
+Use FreeBSD `service` and `sysrc` for installed rc.d services; Linux
+`systemctl` examples do not apply.
-### A special note for systems using PHP-FPM
+### Build from ports when custom options are required
-Before starting the Cacti setup process, restart the PHP-FPM daemon to rebuild
-its cache, or you may receive an HTTP 500 error.
+Use a maintained ports tree and read `/usr/ports/UPDATING`. Clone a tree only
+if `/usr/ports` does not already contain one:
-```console
-systemctl restart php-fpm
+```sh
+pkg install git
+# New tree only:
+git clone --depth 1 https://git.FreeBSD.org/ports.git /usr/ports
+# Existing Git tree instead:
+git -C /usr/ports pull --ff-only
```
-## FreeBSD
-
-There are two ways to install on FreeBSD. In both cases Cacti pulls in its
-dependent packages, so you do not need to install anything else. Each way has
-trade-offs:
+Build the chosen flavor, for example:
-- Compiled packages: fast, but with fixed dependency versions (for example an
- older MySQL server or PHP version).
+```sh
+cd /usr/ports/net-mgmt/cacti
+make FLAVOR=php84 config
+make FLAVOR=php84 install clean
+```
- ```sh
- pkg install cacti
- pkg install spine
- ```
+The supported flavors and dependencies come from that ports revision. Follow
+the handbook's dependency-management guidance before mixing custom ports with
+binary packages. Rebuilding a port does not turn the packaged release into
+Cacti development source.
+
+### Check installed paths and services
+
+The [Cacti port][freebsd-cacti] uses these default locations. Custom ports
+options and existing Cacti settings can change them; inspect the installed
+files and application configuration before copying commands.
+
+| Item | Default location or account |
+| --- | --- |
+| Application and bundled schema | `/usr/local/share/cacti` |
+| Database configuration | `/usr/local/share/cacti/include/config.php` |
+| PHP configuration | `/usr/local/etc/php.ini` |
+| RRD data | `/var/db/cacti/rra` |
+| Log directory | `/var/log/cacti` |
+| PHP CLI | `/usr/local/bin/php` |
+| Packaged poller account | `cacti` |
+| Web-server account | Commonly `www`; verify the service configuration |
+
+The port supplies `include/config.php.sample`; preserve an existing
+`include/config.php` and use the sample when creating a new one. Set the
+intended timezone in both CLI and web PHP. Initialize a new database from the
+bundled `cacti.sql`, grant the application account access to its database and
+`mysql.time_zone_name`, and verify database timezone data is loaded. Never
+import `cacti.sql` over an existing installation.
+
+Check package-specific patches as well as upstream instructions. For example,
+the current port sets `$php_snmp_support = false` for new configurations;
+verify the installed setting and Net-SNMP paths when troubleshooting polling.
+
+Configure write access only for the runtime directories needed by the actual
+poller and web processes. Keep application code and database credentials
+protected. Preserve Cacti's web-server restrictions on configuration, CLI,
+resource, and data directories.
+
+Create one Cacti schedule. For a five-minute launcher, an example entry in the
+`cacti` user's crontab is:
+
+```cron
+*/5 * * * * /usr/local/bin/php -q /usr/local/share/cacti/poller.php
+```
-- FreeBSD ports: compilation can take a long time, but dependency versions are
- not fixed (see
- [Using the Ports Collection](https://docs.freebsd.org/en/books/handbook/ports/))
+Match this cadence to **Cron/Daemon Interval** in Cacti. A system crontab needs
+the account field as well. Check for an existing cron entry or daemon first;
+do not run both. Use [Data Source Debugging](Data-Debug.md) and the Cacti log
+to verify collection after completing the web installer.
- ```sh
- pkg install git
- git clone https://git.FreeBSD.org/ports.git /usr/ports
- git -C /usr/ports pull
- # Choose either MariaDB or MySQL:
- cd /usr/ports/databases/mariadb106-server
- make install clean
- cd /usr/ports/net-mgmt/cacti
- make install
- cd /usr/ports/net-mgmt/spine
- make install
- ```
+### Optional Spine poller
-Apache and other software can be installed using packages or Ports as well.
+The [Spine port][freebsd-spine] is `net-mgmt/cacti-spine`; its package is
+`spine`. Install it only when its version matches the Cacti release you use:
-Everything in FreeBSD is installed under /usr/local/. This documentation shows
-paths such as /etc/php.ini and /usr/bin/spine.
+```sh
+pkg install -n spine
+pkg install spine
+```
-Use the FreeBSD equivalents instead: /usr/local/etc, /usr/local/bin/spine.
+Its default binary is `/usr/local/bin/spine`, with
+`/usr/local/etc/spine.conf.sample` as the configuration example. Supply the
+correct database connection in `spine.conf` and select the binary in Cacti.
+Verify the poller account can run it. Grant ICMP privileges only when the
+selected polling method requires them; do not apply a blanket setuid command.
-For Spine, set the suid bit (without it, ICMP ping cannot function):
+For an existing installation, follow
+[Upgrading Under FreeBSD](Upgrading-Cacti-Under-FreeBSD.md).
-```sh
-chmod +s /usr/local/bin/spine
-```
+[freebsd-ports]:
+[freebsd-cacti]:
+
+[freebsd-spine]:
+
+[manual-12]:
## Configure PHP
Verify that the modules are installed and configured correctly. There are
several ways to do so - consult
-[PHP configuration instructions](https://www.php.net/manual/en/configuration.php)
+[PHP configuration instructions][php-config]
for a complete description.
It is imperative that you set the `date.timezone` in your `/etc/php.ini`, or
@@ -189,52 +231,30 @@ no need to discuss that here.
## Configure the Webserver (Apache)
-Most Linux and UNIX systems automatically configure the web server to allow PHP
-content, so no additional configuration should be needed. The section below is
-included for reference in case you are running a UNIX version that does not
-configure the web server correctly. It is written specifically for RHEL and its
-variants, so the instructions may vary.
+Use the distribution's Apache/PHP integration, selecting either its PHP-FPM
+handler or a compatible Apache PHP module. Do not configure both handlers for
+the same files. The [Enterprise Linux LAMP guide][lamp] and
+[Ubuntu/Debian guide](Installing-Under-Ubuntu-Debian.md) provide examples.
-Find the file `/etc/httpd/conf/httpd.conf` or its equivalent and make the
-following changes to it:
-
-```ini
-# Load config files from the config directory "/etc/httpd/conf.d".
-Include conf.d/*.conf
-```
-
-Now, locate the PHP configuration file at `/etc/httpd/conf.d/php.conf`
-
-```ini
-# PHP is an HTML-embedded scripting language which attempts to make it
-# easy for developers to write dynamically generated webpages.
-LoadModule php_module modules/libphp.so
-#
-# Cause the PHP interpreter to handle files with a .php extension.
-AddHandler php-script .php
-AddType text/html .php
-#
-# Add index.php to the list of files that will be served as directory
-# indexes.
-DirectoryIndex index.php
-```
+Verify Apache's configuration before reloading. Restrict access during setup,
+use HTTPS, and ensure that PHP requests execute rather than expose source. Keep
+Cacti's shipped `.htaccess` restrictions active, or reproduce them in the
+server configuration if overrides are disabled. nginx and IIS need their own
+restrictions; they do not interpret Apache `.htaccess` files.
## Configure MySQL/MariaDB
-Set a password for the root user, and record this password. If you lose control
-of this password, you may have to re-install your database server in the case of
-any system disaster or recovering from a crash.
-
-```console
-mysql_secure_installation
-```
+Initialize and secure the database using the procedure for the installed MySQL
+or MariaDB package. Use the administrator authentication method configured by
+that package; some Unix packages use local socket authentication. Store
+credentials securely and do not put passwords directly on shell command lines.
You must also load timezone information into the database. This is required for
various plugin use. Later, you will be required to grant access to the
`time_zone_name` table during the final installation steps.
```sh
-shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
+mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
```
Since Cacti 1.x is supporting internationalization (i18n), it is important that
@@ -242,16 +262,16 @@ the default character set for MySQL/MariaDB be i18n compatible. The Cacti
installer will make specific recommendations on MySQL/MariaDB settings. Follow
those as applicable for your OS.
-Galera clustering: several tables use the MEMORY storage engine. Those tables
-are not replicated among nodes, which can cause problems. If you configure Cacti
-to connect to only one node of your cluster and are not load balancing, this
-does not apply to you.
+Galera clustering: There are several tables which are set to use the MEMORY
+storage engine which do not get replicated among nodes which can cause
+problems. If you configure Cacti to only connect to one node of your cluster
+and are not load balancing this does not apply to you.
If you are running multiple nodes in a load-balanced environment where you
-connect to a VIP, remove all but one node from rotation during Cacti
-installation or update. After the installation or update, log in to your MySQL
-server and run the following commands to convert those tables to the InnoDB
-engine:
+connect to a VIP you should remove all but one node from rotation during Cacti
+installation or update. After the installation/update login to your MySQL
+server and execute the following commands to update those tables to use the
+InnoDB engine:
```sql
MariaDB [(none)]> use cacti;
@@ -260,199 +280,225 @@ MariaDB [cacti]> ALTER TABLE `automation_processes` ENGINE=InnoDB;
MariaDB [cacti]> ALTER TABLE `data_source_stats_hourly_cache` ENGINE=InnoDB;
MariaDB [cacti]> ALTER TABLE `data_source_stats_hourly_last` ENGINE=InnoDB;
MariaDB [cacti]> ALTER TABLE `poller_output` ENGINE=InnoDB;
-MariaDB [cacti]> ALTER TABLE `poller_output_boost_local_data_ids` ENGINE=InnoDB;
MariaDB [cacti]> ALTER TABLE `poller_output_boost_processes` ENGINE=InnoDB;
-MariaDB [cacti]> ALTER TABLE `processes` ENGINE=InnoDB;
```
-On Cacti 1.3 the `data_source_stats_hourly_cache` table already uses InnoDB,
-so that one statement is a no-op there. It is still required on 1.2.x.
-
-These changes should replicate to the other nodes in your cluster. Allow Cacti
-to run at least two or three full polling cycles before placing the other nodes
-back into rotation.
+Before restoring database load balancing, verify the table-engine changes,
+replication state and successful polling on the configured topology. A fixed
+number of polling cycles is not proof that the cluster is ready.
## Install and Configure Cacti
-1. Extract the distribution tarball.
+These are fresh source-install examples for Cacti development (1.3).
+Package-managed installations should use the maintainer's procedure instead.
+For an existing installation, follow [Upgrading Cacti](Upgrading-Cacti.md). The
+examples use `/var/www/html/cacti`; adjust that path and the service accounts
+for your OS. Use administrator privileges for software installation and
+permission changes.
- ```sh
- shell> tar xzvf cacti-version.tar.gz
- ```
+### Extract the source and create the database
-2. Create the MySQL database:
+Obtain the intended source revision in a new installation directory. Do not run
+these commands over an existing deployment:
- ```sh
- shell> mysqladmin --user=root create cacti
- ```
+```sh
+git clone --branch develop --depth 1 https://github.com/Cacti/cacti.git cacti
+mv cacti /var/www/html/cacti
+cd /var/www/html/cacti
+composer install --no-dev
+composer check-platform-reqs --no-dev
+```
-3. Import the default cacti database:
+The installation root should now contain `cacti.sql`, `poller.php` and
+`include/config.php.dist`, rather than another nested release directory.
- ```sh
- shell> mysql cacti < cacti.sql
- ```
+Connect with a database administrator account:
-4. Optional: Create a MySQL username and password for Cacti.
+```sh
+mysql --user=root --password
+```
- ```sql
- shell> mysql --user=root mysql
- mysql> CREATE USER 'cactiuser'@'localhost' IDENTIFIED BY 'somepassword';
- mysql> GRANT ALL PRIVILEGES ON cacti.* TO 'cactiuser'@'localhost';
- mysql> GRANT SELECT ON mysql.time_zone_name TO 'cactiuser'@'localhost';
- mysql> FLUSH PRIVILEGES;
- ```
+Create the database and a dedicated application account. Replace the password
+placeholder before running this SQL, and use the same secret in the Cacti
+configuration. The database account is separate from the operating-system
+account that runs the poller.
- Note that if your `root` (or equivalent) user does not have `SUPER`
- permissions, it may still be possible to `GRANT SELECT` privileges to the
- Cacti user via an `INSERT INTO mysql.tables_priv`.
+```sql
+CREATE DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE USER 'cactiuser'@'localhost'
+ IDENTIFIED BY 'REPLACE_WITH_UNIQUE_DATABASE_PASSWORD';
+GRANT ALL PRIVILEGES ON cacti.* TO 'cactiuser'@'localhost';
+GRANT SELECT ON mysql.time_zone_name TO 'cactiuser'@'localhost';
+EXIT;
+```
- ```sql
- INSERT INTO mysql.tables_priv (Host, Db, User, Table_name, Grantor, Table_priv)
- VALUES ('localhost', 'mysql', 'cactiuser', 'time_zone_name', 'root@localhost', 'Select');
- ```
+Use an authorized database administrator to grant access. Do not edit
+`mysql.tables_priv` as a substitute for an authorized `GRANT` operation. Ensure
+the server's timezone tables are populated using the procedure for the
+installed MySQL or MariaDB server; granting access does not populate them.
-5. Edit `include/config.php` and specify the database type, name, host, user and
- password for your Cacti configuration.
+Import the schema into the new database using the appropriate client:
- ```php
- $database_type = "mysql";
- $database_default = "cacti";
- $database_hostname = "localhost";
- $database_username = "cactiuser";
- $database_password = "cacti";
- ```
+```sh
+mysql --user=root --password --default-character-set=utf8mb4 cacti \
+ < /var/www/html/cacti/cacti.sql
+```
-6. Set the appropriate permissions on Cacti's directories for graph/log
- generation. You should execute these commands from inside Cacti's directory
- to change the permissions.
+The `--password` option prompts for the password. Use `mariadb` in place of
+`mysql` where appropriate for the installed server.
- ```sh
- shell> chown -R cactiuser rra/ log/ cache/
- ```
+### Configure access and complete installation
- (Enter a valid username for _cactiuser_, this user will also be used in the
- next step for data gathering.)
+Copy the supplied configuration example:
-7. Create your cron task file or systemd units file
+```sh
+cp /var/www/html/cacti/include/config.php.dist \
+ /var/www/html/cacti/include/config.php
+```
- Starting with Cacti 1.2.16, you have the option to use either the legacy
- Crontab entry, or an optional cactid units file and server to run your Cacti
- pollers.
+Edit the copied file to match the account created above:
- For Crontab use, follow the instructions below:
+```php
+$database_type = 'mysql';
+$database_default = 'cacti';
+$database_hostname = 'localhost';
+$database_username = 'cactiuser';
+$database_password = 'REPLACE_WITH_UNIQUE_DATABASE_PASSWORD';
+$database_port = '3306';
+$url_path = '/cacti/';
+```
- Create and edit `/etc/cron.d/cacti` file. Make sure to setup the correct path
- to poller.php
+Identify the actual web and poller service accounts. Give them the required
+read/execute access to application files and external tools, and write access
+to the runtime paths they use, including RRD, log and cache paths. They need
+not be the same account. Do not assume a database username is also a local OS
+account or make the whole application tree writable.
+
+During installation and package imports, grant the performing identity the
+additional access required by the installer, including query/script resources
+and the location used to initialize the CSRF secret. Remove temporary setup
+permissions afterward. Preserve read access to the generated secret; do not
+create an empty secret file. See the platform-specific installation guides for
+their account and permission examples.
+
+Restrict installer access to the administrator and use HTTPS or a protected
+local connection before entering credentials. A freshly imported development
+schema uses application username `admin` and initial password `admin`. Open the
+configured Cacti URL, sign in and choose a unique administrator password when
+prompted. These are separate from the database credentials. Complete the
+installer's dependency, database, path and permission checks before allowing
+general access.
+
+### Schedule collection after installation
+
+Use either cron or `cactid.service`, not both. The following examples assume an
+existing local user and group named `cacti` with the required polling
+permissions; replace them with the actual service identity for your system. Do
+not start polling before completing the web installer.
+
+For a system cron file such as `/etc/cron.d/cacti`, use an absolute PHP CLI
+path and include the OS username:
- ```console
- */5 * * * * apache php /poller.php >/dev/null 2>&1
- ```
+```console
+*/5 * * * * cacti /usr/bin/php /var/www/html/cacti/poller.php >/dev/null 2>&1
+```
- To install the systemd unit file, first edit the included unit file to match
- your install location and the user and group the Cacti poller should run as.
- Then follow the procedure below:
+The five-minute launch interval must match **Cron/Daemon Interval** under the
+poller settings. This is separate from individual data-source polling
+intervals. The redirection above works with `/bin/sh`; `&>` is Bash-specific.
- ```console
- vim /service/cactid.service (edit the path)
- touch /etc/sysconfig/cactid
- cp -p /service/cactid.service /etc/systemd/system
- systemctl daemon-reload
- systemctl enable cactid
- systemctl start cactid
- systemctl status cactid
- ```
+The supplied systemd unit uses `Type=forking`. Confirm that the selected PHP
+CLI provides `pcntl_fork` before using it; otherwise use cron or install the
+appropriate PCNTL support. For the example CLI path, this should report
+`bool(true)`:
- The systemd units file makes managing a highly available Cacti setup a bit
- more convenient.
+```sh
+/usr/bin/php -r 'var_dump(function_exists("pcntl_fork"));'
+```
-8. During install, you will need to provide write access to the following files
- and directories:
+For systemd, copy the supplied unit and edit the installed copy:
- ```sh
- shell> chown -R apache:apache resource scripts include/config.php
- ```
+```sh
+cp /var/www/html/cacti/service/cactid.service \
+ /etc/systemd/system/cactid.service
+```
- Use the account your web server runs as. That is `apache` on Enterprise
- Linux and `www-data` on Debian and Ubuntu. Do not use the database
- account here, because it is a MySQL user rather than a system user.
+Replace the unit's existing `User`, `Group`, `ExecStart` and `EnvironmentFile`
+settings with values for the actual deployment, retaining its other settings.
+For example:
- Once the installation is complete, you may change the permissions to more
- restrictive settings.
+```ini
+User=cacti
+Group=cacti
+ExecStart=/usr/bin/php /var/www/html/cacti/cactid.php
+EnvironmentFile=-/etc/default/cactid
+```
-9. Point your web browser to:
+The `-` allows the optional environment file to be absent. Disable the
+Cacti-specific cron entry before enabling the daemon, then load the edited
+unit:
- `http:///cacti/`
+```sh
+systemctl daemon-reload
+systemctl enable cactid.service
+systemctl start cactid.service
+systemctl status cactid.service
+```
- Log in with a username and password of _admin_. You will be required to
- change this password immediately. Make sure to fill in all of the path
- variables carefully and correctly on the following screen.
+The unit manages the local daemon; it does not establish high availability.
+Verify scheduler execution, collector status, logs and recent graph data under
+the configured account.
## (Optional) Install and Configure Spine
Spine is a very fast data collection engine, written in C. It is an optional
replacement for cmd.php. If you decide to use it, you will have to install it
-explicitly. It does not come with Cacti itself.
+explicitly. It does not come with cacti itself.
The easiest way is to install Spine using rpm or ports. You will find packages
-for Spine at the main Cacti site or from your distribution.
+for Spine at the main cacti site or from your distribution.
To compile Spine, download it to any location of your liking. Then, issue from
the downloaded directory following commands
```sh
-shell> ./bootstrap
+./bootstrap
```
-If the `bootstrap` script is successful, you then will follow the instructions it
-provides to compile and install.
+After `bootstrap` succeeds, follow the release's build instructions to
+configure, compile and install Spine.
-Assuming you installed Spine correctly, you must now configure it. The
-configuration file may be placed in the same directory as Spine itself or at
-/etc/spine.conf.
+Assuming, you've managed to install spine correctly, you will have to configure
+it. Use the installed `spine.conf.dist` as the example, and configure the
+actual Spine configuration path in Cacti. Use the same database account and
+secret as the Cacti configuration, and restrict file access to the poller
+account and administrators.
```ini
-DB_Host 127.0.0.1 or hostname (not localhost)
+DB_Host localhost
DB_Database cacti
DB_User cactiuser
-DB_Pass cactiuser
+DB_Pass REPLACE_WITH_UNIQUE_DATABASE_PASSWORD
DB_Port 3306
```
### Considerations when using Proxies in front of Cacti (Cacti 1.2.23+)
-For optimal security, specify only the HTTP headers that your proxy software
-sets. This prevents unauthorized access through header spoofing. Set them by
-editing the following section of `config.php`:
+A header allowlist does not authenticate a proxy. Trust forwarded client-IP
+headers only when a trusted proxy replaces those headers and untrusted clients
+cannot bypass it to reach Cacti directly. Leave forwarding disabled otherwise.
+In `include/config.php`, select only the headers your proxy sets. For a
+deployment using `X-Forwarded-For`, the setting is:
```php
-/*
- * Allow the use of Proxy IPs when searching for client
- * IP to be used
- *
- * This can be set to one of the following:
- * - false: to use only REMOTE_ADDR
- * - true: to use all allowed headers (not advised)
- * - array of one or more the following:
- * 'X-Forwarded-For',
- * 'X-Client-IP',
- * 'X-Real-IP',
- * 'X-ProxyUser-Ip',
- * 'CF-Connecting-IP',
- * 'True-Client-IP',
- * 'HTTP_X_FORWARDED',
- * 'HTTP_X_FORWARDED_FOR',
- * 'HTTP_X_CLUSTER_CLIENT_IP',
- * 'HTTP_FORWARDED_FOR',
- * 'HTTP_FORWARDED',
- * 'HTTP_CLIENT_IP',
- *
- * NOTE: The following will always be checked:
- * 'REMOTE_ADDR',
- */
-$proxy_headers = null;
-
+$proxy_headers = ['X-Forwarded-For'];
```
+[lamp]: Install-Under-Enterprise-Linux-LAMP.md
+[supported-os]: Requirements.md#supported-operating-systems
+
+[php-config]:
+
---
Copyright (c) 2004-2026 The Cacti Group
diff --git a/How-To-SSH-Tunnels.md b/How-To-SSH-Tunnels.md
index 5f42b399..d93aa8ae 100644
--- a/How-To-SSH-Tunnels.md
+++ b/How-To-SSH-Tunnels.md
@@ -67,7 +67,8 @@ Option summary:
### Making the tunnel persistent (systemd)
-On systemd-based hosts (Ubuntu 16.04+, Debian 9+, most current distros),
+On systemd-based hosts covered by the
+[supported operating systems](Requirements.md#supported-operating-systems),
`/etc/rc.local` is deprecated and disabled by default. Use a systemd service
instead.
diff --git a/Install-Under-CentOS_LAMP.md b/Install-Under-CentOS_LAMP.md
new file mode 100644
index 00000000..2b618878
--- /dev/null
+++ b/Install-Under-CentOS_LAMP.md
@@ -0,0 +1,11 @@
+# Enterprise Linux LAMP Installation
+
+Use the [Enterprise Linux LAMP installation
+guide](Install-Under-Enterprise-Linux-LAMP.md)
+and the [supported operating
+systems](Requirements.md#supported-operating-systems).
+This page preserves an older manual URL.
+
+---
+
+Copyright (c) 2004-2026 The Cacti Group
diff --git a/Install-Under-CentOS_LEMP.md b/Install-Under-CentOS_LEMP.md
new file mode 100644
index 00000000..992bb2c4
--- /dev/null
+++ b/Install-Under-CentOS_LEMP.md
@@ -0,0 +1,11 @@
+# Enterprise Linux LEMP Installation
+
+Use the [Enterprise Linux LEMP installation
+guide](Install-Under-Enterprise-Linux-LEMP.md)
+and the [supported operating
+systems](Requirements.md#supported-operating-systems).
+This page preserves an older manual URL.
+
+---
+
+Copyright (c) 2004-2026 The Cacti Group
diff --git a/Install-Under-Enterprise-Linux-LAMP.md b/Install-Under-Enterprise-Linux-LAMP.md
index 81c721d0..0620500c 100644
--- a/Install-Under-Enterprise-Linux-LAMP.md
+++ b/Install-Under-Enterprise-Linux-LAMP.md
@@ -1,545 +1,165 @@
-# Installing on Enterprise Linux (RHEL / Rocky Linux / AlmaLinux)
+# Installing on Enterprise Linux with Apache
-> **Note**: As of Cacti 1.2.31, PHP 8.1 is required and PHP Composer is required.
-> Composer will be used to ensure all libraries are installed and up to date.
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
-## LAMP (Linux, Apache, MySQL/MariaDB, PHP) Required packages
+This source-install example covers the unreleased Cacti 1.3 development branch
+on RHEL, Rocky Linux, or AlmaLinux. Read [Requirements](Requirements.md)
+first. Run administrative commands as root and adapt paths and accounts to
+your deployment. For an existing installation, use
+[Upgrading Cacti](Upgrading-Cacti.md). For package-managed Cacti, follow the
+package maintainer's procedure instead of overlaying source files.
-### Web Server (Apache)
+## Choose repositories and PHP
-1. For EL 8 and EL 9+ (RHEL, Rocky Linux, AlmaLinux)
-
- ```console
- dnf module reset php
- dnf module enable php:8.1
- ```
-
-### A special note on installing Cacti in LXC containers such as those found on Proxmox
-
-We recommend creating a privileged container. You may need to update your container's config file with
+For a new, fully updated RHEL 9 installation with the stream available,
+[PHP 8.3][php-stream] is an example meeting the development minimum:
```console
-lxc.apparmor.profile: unconfined
+dnf module list php
+dnf module install php:8.3
```
-This will allow ICMP ping and other functions to work.
+This is a fresh-install example, not a stream-switching procedure for an
+existing server. Check the streams supplied by your distribution. EL 9 and EL
+10 do not share identical repositories or module availability. If the required
+PHP version is unavailable, choose a maintained distribution or repository that
+provides it before continuing.
-A tested configuration like the one below should work; tune to your needs and standards.
+## Install the web and database packages
-```console
-arch: amd64
-cores: 2
-hostname: cacti
-memory: 2048
-net0: name=eth0,bridge=vmbr0,firewall=1,hwaddr=mac-id,ip=dhcp,type=veth
-ostype: rocky
-rootfs: local-lvm:vm-110-disk-0,size=8G
-swap: 2048
-lxc.apparmor.profile: unconfined
-```
-
-### A special note for systems using PHP-FPM
-
-Before starting the Cacti setup process, restart the PHP-FPM daemon to rebuild
-its cache, or you may receive an HTTP 500 error.
+This example uses MariaDB. MySQL installations should use the package and
+service names for their selected MySQL repository. Review the database version
+against Cacti's requirements before installation.
```console
-systemctl restart php-fpm
+dnf install -y httpd php-fpm php-cli php-mysqlnd php-gd php-gmp \
+ php-intl php-ldap php-mbstring php-xml php-process php-snmp \
+ mariadb-server rrdtool net-snmp-utils cronie
+php -v
+php -m
```
-2. Install Apache
-
- ```console
- yum install -y httpd
- ```
-
-3. Enable and start the service to ensure it starts when the system reboots
+Additional packages can be required by the chosen source revision. Check
+[Requirements](Requirements.md), including Composer dependencies where
+applicable. Do not mix extensions from different PHP versions or repositories.
- ```console
- systemctl start httpd
- systemctl enable httpd
- ```
+Configure `date.timezone` in the PHP configuration used by both CLI and FPM.
+Check `php --ini` for CLI and the installer for web PHP. Review the FPM pool at
+`/etc/php-fpm.d/www.conf`; its account needs access to Cacti's runtime paths.
+Keep code owned by the deployment administrator.
-### Example configuration file for Apache 2.4 and SSL
-
-This example configuration assumes you have your own certificates already. You
-should make sure you change the paths to match your setup.
-
-Replace `YourOwnCertFile.crt` and `YourOwnCertFile.key` with the names of the
-files holding your certificate (`.crt`) and private key (`.key`).
+Start the database:
```console
-#
-# Cacti: An RRDtool based graphing web application
-#
+systemctl enable --now mariadb
+```
-# For security reasons, the Cacti web interface is accessible only to
-# localhost in the default configuration. If you want to allow other clients
-# to access your Cacti installation, change the httpd ACLs below.
-# For example:
-# On httpd 2.4, change "Require host localhost" to "Require all granted".
-# On httpd 2.2, change "Allow from localhost" to "Allow from all".
+Follow the installed database vendor's initialization and account-security
+procedure. Do not set a root password on the shell command line. Configure only
+variables accepted by that database version; use Cacti's installer
+recommendations rather than a fixed tuning block. Keep InnoDB doublewrite
+protection enabled.
-
- LogLevel warn
+## Configure Apache
- ServerName cacti.yourdomain.com
- ServerAdmin admin@yourdomain.com
+Use the distribution's Apache/PHP-FPM integration. Check that PHP requests are
+executed by FPM rather than served as text. This example exposes only
+`/cacti/`; replace the hostname and certificate paths before use. Save it in
+`/etc/httpd/conf.d/cacti.conf`:
- DocumentRoot "/var/www/html/cacti"
- Alias /cacti /var/www/html/cacti
+```apache
+
+ ServerName cacti.example.com
SSLEngine On
- SSLCertificateFile /etc/ssl/certs/YourOwnCertFile.crt
- SSLCertificateKeyFile /etc/ssl/private/YourOwnCertKey.key
-
-
-
- # httpd 2.4
- Require all granted
-
-
- # httpd 2.2
- Order deny,allow
- Deny from all
- Allow from all
-
-
-
-
- # mod_security overrides.
- # Uncomment these if you use mod_security.
- # allow POST of application/x-www-form-urlencoded during install
- #SecRuleRemoveById 960010
- # permit the specification of the RRDtool paths during install
- #SecRuleRemoveById 900011
-
-
- # These sections marked "Require all denied" (or "Deny from all")
- # should not be modified.
- # These are in place in order to harden Cacti.
-
-
- Require all denied
-
-
- Order deny,allow
- Deny from all
-
-
-
-
- Require all denied
-
-
- Order deny,allow
- Deny from all
-
+ SSLCertificateFile /etc/pki/tls/certs/cacti.crt
+ SSLCertificateKeyFile /etc/pki/tls/private/cacti.key
+ Alias /cacti /var/www/html/cacti
+
+
+ Options -Indexes
+ AllowOverride All
+ Require all granted
+ DirectoryIndex index.php
```
-### Database Server
-
-The choice between MySQL server and MariaDB is normally determined by the OS
-maintainers when using a predefined LAMP setup. If you are choosing between
-them yourself, research the differences via your preferred search engine.
-
-MySQL is the original open source SQL database server, created in 1995 and now
-owned by Oracle. MariaDB is designed as a drop-in replacement by some of the
-original MySQL developers. The two are expected to remain compatible until a
-major divergence occurs that cannot be bridged.
-
-#### MySQL
-
-1. Install MySQL server
-
- ```console
- yum install -y mysql mysql-server
- ```
-
-2. Enable and start the service to ensure it starts when the system reboots
-
- ```console
- systemctl enable mysqld
- systemctl start mysqld
- ```
-
-#### MariaDB
-
-1. Install MariaDB server
-
- ```console
- dnf install -y mariadb-server mariadb
- ```
-
-2. Enable and start the service to ensure it starts when the system reboots
-
- ```console
- systemctl enable mariadb
- systemctl start mariadb
- ```
-
-### MySQL/MariaDB common tasks and recommendations
-
-> **Note**: Secure your MySQL installation before making any further changes.
+Install `mod_ssl` if not already present. `AllowOverride All` lets Cacti's
+shipped `.htaccess` restrictions protect private paths; if your policy disables
+overrides, reproduce those restrictions in the server configuration. Do not
+grant general access to private directories as a troubleshooting step.
```console
-/usr/bin/mysql_secure_installation
+dnf install -y mod_ssl
+httpd -t
+systemctl enable --now php-fpm httpd
```
-The following MySQL/MariaDB recommendations may vary depending on your system
-setup. In any case, Cacti will prompt you with more accurate recommendations
-during the installation.
-
-1. Edit your `server.cnf` file
-
- ```console
- vim /etc/my.cnf.d/server.cnf
- ```
-
- The following `[mysqld]` section is a base configuration. The installer
- will provide recommendations tailored to your actual system; revise these
- values up or down based on those recommendations.
-
- **For MariaDB earlier than version 11.1, or MySQL:**
-
- ```shell
- [mysqld]
- character-set-server=utf8mb4
- collation-server=utf8mb4_unicode_ci
- # innodb_file_format and innodb_large_prefix were removed in MySQL 8.0 /
- # MariaDB 10.3+; omit those settings on newer releases.
- max_allowed_packet = 16777777
- join_buffer_size = 32M
- innodb_file_per_table = ON
- innodb_buffer_pool_size = 250M
- # innodb_additional_mem_pool_size was removed in MySQL 5.7.4 /
- # MariaDB 10.0; omit on newer releases.
- innodb_flush_log_at_trx_commit = 2
- log-error = /var/log/mysql/mysql-error.log
- log-queries-not-using-indexes = 1
- slow-query-log = 1
- slow-query-log-file = /var/log/mysql/mysql-slow.log
- ```
-
- **For MariaDB 11.0 or higher:**
-
- ```shell
- [mariadb]
- max_heap_table_size=500M
- character_set_client=utf8mb4
- character_set_server=utf8mb4
- collation_server=utf8mb4_unicode_ci
- innodb_buffer_pool_size=8G
- innodb_doublewrite=OFF
- tmp_table_size=500M
- log-error = /var/log/mysql/mysql-error.log
- log-queries-not-using-indexes = 1
- slow-query-log = 1
- slow-query-log-file = /var/log/mysql/mysql-slow.log
- ```
-
-2. Restart MySQL/MariaDB to apply the changes
-
- ```console
- systemctl restart mysqld # or: systemctl restart mariadb
- ```
+Use your certificate-management procedure and review any packaged default TLS
+virtual host for conflicts. Restrict access to administrators during setup.
-3. Populate the timezone table
+## Install and configure Cacti
- ```console
- mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
- ```
+Use [General Installing Instructions][general] to obtain the intended source,
+create a new database and dedicated application account, load timezone data,
+import `cacti.sql`, and configure `include/config.php`. The examples there use
+`/var/www/html/cacti`; use that same path here.
-#### Set up the Cacti database
+Complete the dependency and filesystem-permission checks before opening the
+installer. The database account and operating-system service accounts are
+separate identities. Grant runtime write access to the actual FPM and poller
+accounts, not automatically to the nginx master process or the database user.
+Keep executable code and credentials protected during normal operation.
-1. Log in to MySQL/MariaDB as root and create the Cacti database
+Open `https://cacti.example.com/cacti/` and complete the installer. Configure
+one scheduler after installation: either a Cacti-specific cron entry or the
+supplied `cactid` systemd service, using the procedure in the general guide. Do
+not run both for the same collector. The five-minute cron example is:
- ```console
- # mysql -u root -p
- MariaDB [(none)]> create database if not exists cacti;
- Query OK, 1 row affected (0.00 sec)
- ```
-
-2. Import the default Cacti schema
-
- ```sql
- MariaDB [(none)]> use cacti;
- Database changed
- MariaDB [(cacti)]> source /var/www/html/cacti/cacti.sql
- ```
-
-3. Create the Cacti database user. Replace `your_cacti_username` and
- `your_cacti_password` with your own credentials.
-
- ```sql
- MariaDB [(none)]> CREATE USER 'your_cacti_username'@'localhost'
- IDENTIFIED BY 'your_cacti_password';
- Query OK, 0 rows affected (0.00 sec)
- MariaDB [(none)]> GRANT ALL PRIVILEGES ON cacti.* TO 'your_cacti_username'@'localhost';
- Query OK, 0 rows affected (0.00 sec)
- ```
-
-4. Grant the Cacti user access to the timezone table
-
- ```sql
- MariaDB [(none)]> GRANT SELECT ON mysql.time_zone_name TO 'your_cacti_username'@'localhost';
- Query OK, 0 rows affected (0.00 sec)
- MariaDB [(none)]> FLUSH PRIVILEGES;
- Query OK, 0 rows affected (0.00 sec)
- ```
-
-5. Set the database character set and collation
-
- ```sql
- MariaDB [(none)]> ALTER DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- MariaDB [(none)]> FLUSH PRIVILEGES;
- ```
-
-### Common packages
-
-#### PHP
-
-PHP and the following packages are required for Cacti to operate.
-
-1. Install PHP and required packages
-
- ```console
- yum install -y php php-common php-bcmath php-cli \
- php-mysqlnd php-gd php-gmp php-intl \
- php-ldap php-mbstring \
- php-pdo php-pear php-snmp php-process \
- php-xml php-zip composer
- ```
-
-2. Set a timezone in your PHP configuration
-
- Edit `/etc/php.ini` and set:
-
- ```console
- date.timezone = America/Los_Angeles
- ```
-
-#### RRDtool
-
-RRDtool is required to store the data retrieved from devices in `.rra` files and
-produce the graphs shown within Cacti.
-
-```console
-yum install -y rrdtool
-```
-
-#### SNMP
-
-SNMP is used to query most devices for information.
-
-```console
-yum install -y net-snmp net-snmp-utils
+```cron
+*/5 * * * * apache /usr/bin/php /PATH/TO/cacti/poller.php >/dev/null 2>&1
```
-### Cacti
-
-The following steps show you how to manually download, install, and configure
-the basics for Cacti.
-
-1. Download the Cacti source code from the
- [Cacti website](https://www.cacti.net/download_cacti.php)
-
- ```console
- cd /tmp
- wget https://www.cacti.net/downloads/cacti-1.y.z.tar.gz
- tar -zxvf cacti-1.y.z.tar.gz
- mv -v cacti-1.y.z /var/www/html/cacti
- ```
-
-2. Create the config.php file
-
- ```console
- cp -v /var/www/html/cacti/include/config.php.dist /var/www/html/cacti/include/config.php
- ```
-
-3. Update the `database_` fields with your own details. This section applies
- only to the main Cacti server.
-
- ```php
- $database_type = 'mysql';
- $database_default = 'your_cacti_database';
- $database_hostname = 'localhost';
- $database_username = 'your_cacti_username';
- $database_password = 'your_cacti_password';
- $database_port = '3306';
- $database_ssl = false;
- $database_ssl_key = '';
- $database_ssl_cert = '';
- $database_ssl_ca = '';
- ```
+Replace `/PATH/TO/cacti` and `apache` with the installed path and chosen poller
+account. Enable `crond` if using cron. Verify a manual poll under that account,
+then check scheduled runs, logs, collector status, and fresh graph samples.
-4. Create your cron task file or systemd units file
-
- Starting with Cacti 1.2.16, you can use either a legacy crontab entry or the
- optional `cactid` systemd service to run your Cacti pollers.
+## SELinux and containers
- For crontab use, create and edit `/etc/cron.d/cacti`, setting the correct
- path to `poller.php`:
+Keep SELinux enforcing. For a custom installation path, use persistent file
+contexts and allow writes only on Cacti's runtime paths. Review audit denials
+and authorize the specific network and executable access needed by FPM,
+RRDtool, SNMP tools, and the collector. Do not use `setenforce 0` as the
+installation procedure. See the [RHEL SELinux guide][selinux].
- ```console
- */5 * * * * apache php /var/www/html/cacti/poller.php &>/dev/null
- ```
+For LXC or Proxmox, retain an unprivileged container and its confinement where
+possible. Diagnose the specific ICMP/socket permission or mapped-file access
+failure. Adjust only the required capability or policy; do not make the entire
+container privileged or set an unconfined AppArmor profile merely to run Cacti.
- For systemd, modify the included units file to reflect your install location
- and the desired user and group, then follow the procedure below:
+## Optional Spine and proxies
- ```console
- vim /var/www/html/cacti/service/cactid.service
- touch /etc/sysconfig/cactid
- cp -p /var/www/html/cacti/service/cactid.service /etc/systemd/system
- systemctl enable cactid
- systemctl start cactid
- systemctl status cactid
- ```
+Follow [Spine](Spine.md) for the optional compiled collector. Select a
+compatible source or package and the development headers for your OS.
+Repository names differ: do not apply Rocky/AlmaLinux `crb` commands to RHEL
+without checking its repository configuration. Configure the Spine database
+connection with the same application credentials and restrict access to its
+configuration file.
- The systemd units file makes managing a highly available Cacti setup more
- convenient.
+When using a reverse proxy, see the [proxy configuration in the general
+guide][proxy]. A header allowlist alone does not authenticate a proxy; prevent
+clients from bypassing the trusted proxy and require it to replace forwarded
+client-IP headers.
-#### Spine
+[general]: General-Installing-Instructions.md#install-and-configure-cacti
+[proxy]: General-Installing-Instructions.md
+[selinux]:
-1. Install the packages required to compile Spine
+[php-stream]:
- The required packages depend on your EL version. Choose the block that
- matches your distribution.
-
- **EL 9+ (RHEL 9, Rocky Linux 9, AlmaLinux 9 and later)**
-
- The `crb` (CodeReady Builder) repository provides the development headers
- needed to compile Spine.
-
- ```console
- dnf config-manager --set-enabled crb
- dnf install -y autoconf automake libtool dos2unix help2man \
- openssl-devel mariadb-devel net-snmp-devel
- ```
-
- **EL 8 (RHEL 8, Rocky Linux 8, AlmaLinux 8)**
-
- On EL 8 the same repository is called `powertools`.
-
- ```console
- dnf config-manager --set-enabled powertools
- dnf install -y autoconf automake libtool dos2unix help2man \
- openssl-devel mariadb-devel net-snmp-devel
- ```
-
- **EL 7 and earlier**
-
- ```console
- yum install -y autoconf automake libtool dos2unix help2man \
- openssl-devel mariadb-devel net-snmp-devel
- ```
-
-2. Download the Spine source code from the
- [Cacti website](https://www.cacti.net/spine_download.php)
-
- ```console
- cd /tmp
- wget https://www.cacti.net/downloads/spine/cacti-spine-1.y.z.tar.gz
- tar -zxvf cacti-spine-1.y.z.tar.gz
- cd cacti-spine-1.y.z
- ```
-
-3. Compile and install Spine
-
- ```console
- ./bootstrap
- ./configure
- make
- make install
- chown root:root /usr/local/spine/bin/spine
- chmod u+s /usr/local/spine/bin/spine
- ```
-
-4. Configure Spine
-
- ```console
- mv -v /usr/local/spine/etc/spine.conf.dist /usr/local/spine/etc/spine.conf
- vi /usr/local/spine/etc/spine.conf
- ```
-
-5. Set up the database connection in `spine.conf`
-
- ```console
- DB_Host localhost
- DB_Database your_cacti_database
- DB_User your_cacti_username
- DB_Pass your_cacti_password
- DB_Port 3306
- #DB_UseSSL 0
- #RDB_SSL_Key
- #RDB_SSL_Cert
- #RDB_SSL_CA
- ```
-
-### Security Enhanced Linux (SELinux)
-
-If you have trouble accessing the web interface, disable SELinux temporarily to
-determine whether the SELinux policy is the cause. Do not disable SELinux
-permanently.
-
-The [Rocky Linux SELinux Guide](https://docs.rockylinux.org/guides/security/learning_selinux/) provides
-guidance on managing SELinux policies.
-
-1. Check SELinux status
-
- ```console
- getenforce
- ```
-
-2. Disable SELinux temporarily
-
- ```console
- setenforce 0
- ```
-
-3. Re-enable SELinux
-
- ```console
- setenforce 1
- ```
-
-**Note:** If Cacti is installed outside `/var/www/html`, ensure that all SELinux
-file contexts and permissions are set correctly.
-
-### Considerations when using proxies in front of Cacti (Cacti 1.2.23+)
-
-For optimal security, specify only the HTTP headers that your proxy software
-actually sets. This prevents unauthorized access via header spoofing. Configure
-the setting by editing the following section of `config.php`:
-
-```ini
- * Allow the use of Proxy IPs when searching for client
- * IP to be used
- *
- * This can be set to one of the following:
- * - false: to use only REMOTE_ADDR
- * - true: to use all allowed headers (not advised)
- * - array of one or more the following:
- *'X-Forwarded-For',
- *'X-Client-IP',
- *'X-Real-IP',
- *'X-ProxyUser-Ip',
- *'CF-Connecting-IP',
- *'True-Client-IP',
- *'HTTP_X_FORWARDED',
- *'HTTP_X_FORWARDED_FOR',
- *'HTTP_X_CLUSTER_CLIENT_IP',
- *'HTTP_FORWARDED_FOR',
- *'HTTP_FORWARDED',
- *'HTTP_CLIENT_IP',
- *
- * NOTE: The following will always be checked:
- *'REMOTE_ADDR',
- */
-$proxy_headers = null;
-```
+[supported-os]: Requirements.md#supported-operating-systems
---
+
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Install-Under-Enterprise-Linux-LEMP.md b/Install-Under-Enterprise-Linux-LEMP.md
index f6e7960d..18f7fb1b 100644
--- a/Install-Under-Enterprise-Linux-LEMP.md
+++ b/Install-Under-Enterprise-Linux-LEMP.md
@@ -1,573 +1,224 @@
-# Installing on Enterprise Linux (RHEL / Rocky Linux / AlmaLinux)
+# Installing on Rocky Linux 9 and 10 with nginx
-> **Note**: As of Cacti 1.2.31, PHP 8.1 is required and PHP Composer is required.
-> Composer will be used to ensure all libraries are installed and up to date.
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
-## LEMP (Linux, Nginx, MySQL/MariaDB, PHP) Required packages
+This source-install example covers the unreleased Cacti 1.3 development branch
+on RHEL, Rocky Linux, or AlmaLinux. Read [Requirements](Requirements.md)
+first. Run administrative commands as root and adapt paths and accounts to
+your deployment. For an existing installation, use
+[Upgrading Cacti](Upgrading-Cacti.md). For package-managed Cacti, follow the
+package maintainer's procedure instead of overlaying source files.
-### Web Server (Nginx)
+## Choose the Rocky Linux release and packages
-1. Install Nginx
+Use the current security-updated minor release of Rocky Linux 9 or 10. This
+is a fresh-install procedure; do not reset or switch module streams on an
+existing database or PHP deployment without a separate upgrade plan.
- ```console
- yum install -y nginx
- ```
+| Rocky Linux branch | PHP and database selection |
+| --- | --- |
+| 9 | Enable the AppStream `php:8.3` and `mariadb:10.11` streams before installing packages |
+| 10 | Install the AppStream PHP and MariaDB packages directly; this branch does not use module streams |
-2. Enable and start the service to ensure it starts when the system reboots
+### Rocky Linux 9
- ```console
- systemctl start nginx
- systemctl enable nginx
- ```
+Inspect the available streams, then select the versions for this example:
-### Example Nginx configuration with SSL
-
-This example assumes you have your own certificates already. Change the paths to
-match your setup. Replace `YourOwnCertFile.crt` and `YourOwnCertFile.key` with
-the names of your certificate (`.crt`) and private key (`.key`) files.
-
-Save the following as `/etc/nginx/conf.d/cacti.conf`:
-
-```nginx
-# Advanced config for NGINX
-#server_tokens off;
-add_header X-XSS-Protection "1; mode=block";
-add_header X-Content-Type-Options nosniff;
-
-# Redirect all HTTP traffic to HTTPS
-server {
- listen 80;
- server_name cacti.yourdomain.com;
- return 301 https://$host$request_uri;
-}
-
-# SSL configuration
-server {
- listen 443 ssl;
- server_name cacti.yourdomain.com;
- root /usr/share/nginx/html/cacti;
- index index.php index.html index.htm;
-
- # Compression improves performance
- gzip on;
- gzip_types text/plain text/html text/xml text/css application/xml application/javascript application/x-javascript application/rss+xml application/xhtml+xml;
- gzip_proxied no-cache no-store private expired auth;
- gzip_min_length 1000;
-
- location / {
- try_files $uri $uri/ /index.php?$query_string;
- }
-
- error_page 404 /404.html;
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root /usr/share/nginx/html/;
- }
-
- location ~ \.php$ {
- root /usr/share/nginx/html/cacti;
- index index.php;
- try_files $uri $uri/ =404;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
-
- # Adjust path for your OS if needed
- fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
- fastcgi_index index.php;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- include /etc/nginx/fastcgi_params;
- }
-
- location /cacti {
- root /usr/share/nginx/html/;
- index index.php index.html index.htm;
- location ~ ^/cacti/(.+\.php)$ {
- try_files $uri =404;
- root /usr/share/nginx/html;
-
- # Adjust path for your OS if needed
- fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
- fastcgi_index index.php;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- include /etc/nginx/fastcgi_params;
- }
-
- location ~* ^/cacti/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
- expires max;
- log_not_found off;
- }
- }
-
- location /doc/ {
- alias /usr/share/nginx/html/cacti/doc/;
- location ~* ^/docs/(.+\.(html|md|txt))$ {
- root /usr/share/nginx/html/cacti/;
- autoindex on;
- allow 127.0.0.1; # Change this to allow your local networks
- allow ::1;
- deny all;
- }
- }
-
- location ~ ^/(cacti/)?(rra|log|cache)/ {
- deny all;
- }
-
- ## Access and error logs.
- access_log /var/log/nginx/cacti_access.log;
- error_log /var/log/nginx/cacti_error.log info;
-
- ssl_certificate /etc/ssl/certs/YourOwnCertFile.crt;
- ssl_certificate_key /etc/ssl/private/YourOwnCertKey.key;
-
- # Improve HTTPS performance with session resumption
- ssl_session_cache shared:SSL:10m;
- ssl_session_timeout 5m;
-
- # Only allow TLS 1.2 and 1.3; TLS 1.0 and 1.1 are prohibited by RFC 8996
- ssl_protocols TLSv1.2 TLSv1.3;
-
- # Secure cipher suites; excludes known-weak ciphers (3DES, RC4, NULL)
- ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:!ADH:!AECDH:!MD5:!3DES;
- ssl_prefer_server_ciphers on;
-
- # Diffie-Hellman parameter for DHE cipher suites
- # Generate with: openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
- ssl_dhparam /etc/ssl/certs/dhparam.pem;
-
- # Enable HSTS (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)
- add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
-}
+```console
+dnf module list php mariadb
+dnf module enable -y php:8.3 mariadb:10.11
```
-### Database Server
-
-The choice between MySQL and MariaDB is normally determined by the OS
-maintainers when using a predefined LAMP setup. If you are choosing between them
-yourself, research the differences via your preferred search engine.
-
-MySQL is the original open source SQL database server, created in 1995 and now
-owned by Oracle. MariaDB is designed as a drop-in replacement by some of the
-original MySQL developers. The two are expected to remain compatible until a
-major divergence occurs that cannot be bridged.
-
-#### MySQL
-
-1. Install MySQL server
-
- ```console
- yum install -y mysql mysql-server
- ```
-
-2. Enable and start the service
-
- ```console
- systemctl enable mysqld
- systemctl start mysqld
- ```
-
-#### MariaDB
-
-1. Install MariaDB server
-
- ```console
- dnf install -y mariadb-server mariadb
- ```
-
-2. Enable and start the service
+### Rocky Linux 10
- ```console
- systemctl enable mariadb
- systemctl start mariadb
- ```
-
-### MySQL/MariaDB common tasks and recommendations
-
-> **Note**: Secure your MySQL installation before making any further changes.
+Check the packages offered by AppStream; do not run `dnf module` commands:
```console
-/usr/bin/mysql_secure_installation
+dnf info php-fpm mariadb-server
```
-The following recommendations may vary depending on your system. Cacti will
-prompt you with more accurate recommendations during installation.
-
-1. Edit your `server.cnf` file
-
- ```console
- vim /etc/my.cnf.d/server.cnf
- ```
-
- The following is a base configuration. Adjust values up or down based on the
- recommendations Cacti provides during installation.
-
- **For MariaDB earlier than version 11.1, or MySQL:**
-
- ```shell
- [mysqld]
- character_set_client = utf8mb4
- character-set-server = utf8mb4
- collation-server = utf8mb4_unicode_ci
- # innodb_file_format and innodb_large_prefix were removed in MySQL 8.0 /
- # MariaDB 10.3+; omit those settings on newer releases.
- max_allowed_packet = 16777777
- max_heap_table_size = 500M
- join_buffer_size = 32M
- innodb_file_per_table = ON
- innodb_buffer_pool_size = 500M
- # innodb_additional_mem_pool_size was removed in MySQL 5.7.4 /
- # MariaDB 10.0; omit on newer releases.
- innodb_flush_log_at_trx_commit = 2
- log-error = /var/log/mysql/mysql-error.log
- log-queries-not-using-indexes = 1
- slow-query-log = 1
- slow-query-log-file = /var/log/mysql/mysql-slow.log
- ```
-
- **For MariaDB 11.0 or higher:**
-
- ```shell
- [mariadb]
- character_set_client = utf8mb4
- character_set_server = utf8mb4
- collation_server = utf8mb4_unicode_ci
- max_heap_table_size = 500M
- join_buffer_size = 32M
- innodb_buffer_pool_size = 8G
- innodb_doublewrite = OFF
- tmp_table_size = 500M
- log-error = /var/log/mysql/mysql-error.log
- log-queries-not-using-indexes = 1
- slow-query-log = 1
- slow-query-log-file = /var/log/mysql/mysql-slow.log
- ```
-
-2. Restart MySQL/MariaDB to apply the changes
-
- ```console
- systemctl restart mysqld # or: systemctl restart mariadb
- ```
-
-3. Populate the timezone table
-
- ```console
- mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
- ```
-
-#### Set up the Cacti database
-
-1. Log in to MySQL/MariaDB as root and create the Cacti database
-
- ```console
- # mysql -u root -p
- MariaDB [(none)]> create database if not exists cacti;
- Query OK, 1 row affected (0.00 sec)
- ```
-
-2. Import the default Cacti schema
-
- ```sql
- MariaDB [(none)]> use cacti;
- Database changed
- MariaDB [(cacti)]> source /usr/share/nginx/html/cacti/cacti.sql
- ```
-
-3. Create the Cacti database user. Replace `your_cacti_username` and
- `your_cacti_password` with your own credentials.
-
- ```sql
- MariaDB [(none)]> CREATE USER 'your_cacti_username'@'localhost'
- IDENTIFIED BY 'your_cacti_password';
- Query OK, 0 rows affected (0.00 sec)
- MariaDB [(none)]> GRANT ALL PRIVILEGES ON cacti.* TO 'your_cacti_username'@'localhost';
- Query OK, 0 rows affected (0.00 sec)
- ```
-
-4. Grant the Cacti user access to the timezone table
-
- ```sql
- MariaDB [(none)]> GRANT SELECT ON mysql.time_zone_name TO 'your_cacti_username'@'localhost';
- Query OK, 0 rows affected (0.00 sec)
- MariaDB [(none)]> FLUSH PRIVILEGES;
- Query OK, 0 rows affected (0.00 sec)
- ```
-
-5. Set the database character set and collation
-
- ```sql
- MariaDB [(none)]> ALTER DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- MariaDB [(none)]> FLUSH PRIVILEGES;
- ```
-
-### PHP
-
-PHP and the following packages are required for Cacti to operate.
-
-> **Note**: `php-fpm` is required when using Nginx as the web server.
-
-1. Install PHP and required packages
-
- ```console
- yum install -y php php-common php-bcmath php-cli \
- php-mysqlnd php-gd php-gmp php-intl \
- php-ldap php-mbstring \
- php-pdo php-pear php-snmp php-process \
- php-xml php-zip php-fpm composer
- ```
+Rocky's [PHP/FPM guide][rocky-php] explains the difference in packaging, and
+its [release notes][rocky-10] list the major-version package changes.
+Other Enterprise Linux distributions can differ in subscriptions, repositories,
+and package availability; verify those before adapting this Rocky example.
-2. Set a timezone in your PHP configuration
+## Install the web and database packages
- Edit `/etc/php.ini` and set:
-
- ```console
- date.timezone = America/Los_Angeles
- ```
-
-3. Disable insecure `cgi.fix_pathinfo`
-
- ```console
- cgi.fix_pathinfo=0
- ```
-
-#### Set up php-fpm
-
-1. Enable and start the service
-
- ```console
- systemctl start php-fpm
- systemctl enable php-fpm
- ```
-
-2. Edit `/etc/php-fpm.d/www.conf`
-
- Change the listen address from TCP to a Unix socket:
-
- ```console
- listen = /var/run/php-fpm/php-fpm.sock
- ```
-
- Set the socket owner and group to `nginx`:
-
- ```console
- listen.owner = nginx
- listen.group = nginx
- ```
-
- Set the process user and group to `nginx`:
-
- ```console
- user = nginx
- group = nginx
- ```
-
- Restart php-fpm to apply the changes:
-
- ```console
- systemctl restart php-fpm
- ```
-
-### RRDtool
-
-RRDtool is required to store the data retrieved from devices in `.rra` files and
-produce the graphs shown within Cacti.
+This example uses MariaDB. MySQL installations should use the package and
+service names for their selected MySQL repository. Review the database version
+against Cacti's requirements before installation.
```console
-yum install -y rrdtool
+dnf install -y nginx php-fpm php-cli php-mysqlnd php-gd php-gmp \
+ php-intl php-ldap php-mbstring php-xml php-process php-snmp php-pdo \
+ php-pecl-zip mariadb-server rrdtool net-snmp-utils cronie git unzip
+php -v
+php -m
```
-### SNMP
+Additional packages can be required by the chosen source revision. Check
+[Requirements](Requirements.md), including Composer dependencies where
+applicable. Do not mix extensions from different PHP versions or repositories.
-SNMP is used to query most devices for information.
+Configure `date.timezone` in the PHP configuration used by both CLI and FPM.
+Check `php --ini` for CLI and the installer for web PHP. Review the FPM pool
+at `/etc/php-fpm.d/www.conf`. For this example, retain the `apache` worker
+account and allow nginx to connect through the socket ACL:
-```console
-yum install -y net-snmp net-snmp-utils
-echo "rocommunity public" > /etc/snmp/snmpd.conf
-systemctl enable snmpd
-systemctl start snmpd
+```ini
+user = apache
+group = apache
+listen = /run/php-fpm/www.sock
+listen.acl_users = apache,nginx
```
-### Cacti
-
-The following steps show you how to manually download, install, and configure
-the basics for Cacti.
-
-1. Download the Cacti source code from the
- [Cacti website](https://www.cacti.net/download_cacti.php)
-
- ```console
- cd /tmp
- wget https://www.cacti.net/downloads/cacti-1.y.z.tar.gz
- tar -zxvf cacti-1.y.z.tar.gz
- mv -v cacti-1.y.z /usr/share/nginx/html/cacti
- ```
-
-2. Create the config.php file
-
- ```console
- cp -v /usr/share/nginx/html/cacti/include/config.php.dist /usr/share/nginx/html/cacti/include/config.php
- ```
-
-3. Update the `database_` fields with your own details. This section applies
- only to the main Cacti server.
-
- ```php
- $database_type = 'mysql';
- $database_default = 'your_cacti_database';
- $database_hostname = 'localhost';
- $database_username = 'your_cacti_username';
- $database_password = 'your_cacti_password';
- $database_port = '3306';
- $database_ssl = false;
- $database_ssl_key = '';
- $database_ssl_cert = '';
- $database_ssl_ca = '';
- ```
+Modify the existing entries rather than appending a second pool definition.
+The socket ACL grants nginx connection access; Cacti's runtime files must be
+writable by the FPM worker and poller accounts. Keep code owned by the
+administrator. Validate the pool with `php-fpm -t` before restarting FPM.
-4. Set your cookie domain to match your website domain name
+Start the database:
- ```php
- $cacti_cookie_domain = 'cacti.yourdomain.com';
- ```
-
-5. Create your cron task file or systemd units file
-
- Starting with Cacti 1.2.16, you can use either a legacy crontab entry or the
- optional `cactid` systemd service to run your Cacti pollers.
-
- For crontab use, create and edit `/etc/cron.d/cacti`, setting the correct
- path to `poller.php`:
-
- ```console
- */5 * * * * nginx php /usr/share/nginx/html/cacti/poller.php &>/dev/null
- ```
-
- For systemd, modify the included units file to reflect your install location
- and the desired user and group, then follow the procedure below:
-
- ```console
- vim /usr/share/nginx/html/cacti/service/cactid.service
- touch /etc/sysconfig/cactid
- cp -p /usr/share/nginx/html/cacti/service/cactid.service /etc/systemd/system
- systemctl enable cactid
- systemctl start cactid
- systemctl status cactid
- ```
-
- The systemd units file makes managing a highly available Cacti setup more
- convenient.
+```console
+systemctl enable --now mariadb
+```
-#### Spine
+Follow the installed database vendor's initialization and account-security
+procedure. Do not set a root password on the shell command line. Configure only
+variables accepted by that database version; use Cacti's installer
+recommendations rather than a fixed tuning block. Keep InnoDB doublewrite
+protection enabled.
-1. Install the packages required to compile Spine
+## Configure nginx
- ```console
- yum install -y autoconf automake libtool dos2unix help2man \
- openssl-devel mariadb-devel net-snmp-devel
- ```
+Configure the FPM pool's `listen` path and socket ACLs so nginx can connect.
+The example uses `/run/php-fpm/www.sock`; verify that it matches your pool.
+Keep the FPM worker account consistent with the permissions you grant later.
+Save this example in `/etc/nginx/conf.d/cacti.conf`, replacing the hostname and
+certificate paths:
-2. Download the Spine source code from the
- [Cacti website](https://www.cacti.net/spine_download.php)
+```nginx
+server {
+ listen 80;
+ server_name cacti.example.com;
+ return 301 https://cacti.example.com$request_uri;
+}
- ```console
- cd /tmp
- wget https://www.cacti.net/downloads/spine/cacti-spine-1.y.z.tar.gz
- tar -zxvf cacti-spine-1.y.z.tar.gz
- cd cacti-spine-1.y.z
- ```
+server {
+ listen 443 ssl;
+ server_name cacti.example.com;
+ root /usr/share/nginx/html;
+ index index.php;
+ ssl_certificate /etc/pki/tls/certs/cacti.crt;
+ ssl_certificate_key /etc/pki/tls/private/cacti.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ location = / { return 302 /cacti/; }
+ location = /cacti { return 301 /cacti/; }
+
+ # nginx does not read Apache .htaccess files.
+ location ~ (^|/)\. { deny all; }
+ location ~ ^/cacti/(bin|cli|contrib|log|mibs|rra|scripts|service|tests)/ {
+ deny all;
+ }
+ location ~ ^/cacti/cache/(boost|mibcache|realtime|spikekill)/ {
+ deny all;
+ }
+ location ~ ^/cacti/include/(config(_local)?\.php|vendor/.*\.php) {
+ deny all;
+ }
+
+ location ~ ^/cacti/(.+\.php)$ {
+ try_files $uri =404;
+ include /etc/nginx/fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_pass unix:/run/php-fpm/www.sock;
+ }
+ location /cacti/ { try_files $uri $uri/ =404; }
+}
+```
-3. Compile and install Spine
+Keep private-path restrictions before the PHP handler and validate them over
+HTTP. Static assets under `include/vendor` can be required by the interface; do
+not deny all vendor assets indiscriminately. Keep backups outside every web
+root. Restrict setup to administrators until installation is complete.
- ```console
- ./bootstrap
- ./configure
- make
- make install
- chown root:root /usr/local/spine/bin/spine
- chmod u+s /usr/local/spine/bin/spine
- ```
+```console
+nginx -t
+systemctl enable --now php-fpm nginx
+```
-4. Configure Spine
+## Install and configure Cacti
- ```console
- mv -v /usr/local/spine/etc/spine.conf.dist /usr/local/spine/etc/spine.conf
- vi /usr/local/spine/etc/spine.conf
- ```
+Install Composer using its [official installation procedure][composer] and
+verify the installer as documented there. Run `composer install --no-dev`
+and `composer check-platform-reqs --no-dev` as the deployment owner in the
+staged source tree before deploying it to the web root. Do not substitute
+`composer update` or run dependency scripts as the runtime service account.
-5. Set up the database connection in `spine.conf`
+Use [General Installing Instructions][general] to obtain the intended source,
+create a new database and dedicated application account, load timezone data,
+import `cacti.sql`, and configure `include/config.php`. The examples there use
+`/var/www/html/cacti`; substitute `/usr/share/nginx/html/cacti` here.
- ```console
- DB_Host localhost
- DB_Database your_cacti_database
- DB_User your_cacti_username
- DB_Pass your_cacti_password
- DB_Port 3306
- #DB_UseSSL 0
- #RDB_SSL_Key
- #RDB_SSL_Cert
- #RDB_SSL_CA
- ```
+Complete the dependency and filesystem-permission checks before opening the
+installer. The database account and operating-system service accounts are
+separate identities. Grant runtime write access to the actual FPM and poller
+accounts, not automatically to the nginx master process or the database user.
+Keep executable code and credentials protected during normal operation.
-### Security Enhanced Linux (SELinux)
+Open `https://cacti.example.com/cacti/` and complete the installer. Configure
+one scheduler after installation: either a Cacti-specific cron entry or the
+supplied `cactid` systemd service, using the procedure in the general guide. Do
+not run both for the same collector. The five-minute cron example is:
-If you have trouble accessing the web interface, disable SELinux temporarily to
-determine whether the SELinux policy is the cause. Do not disable SELinux
-permanently.
+```cron
+*/5 * * * * apache /usr/bin/php /PATH/TO/cacti/poller.php >/dev/null 2>&1
+```
-The [Rocky Linux SELinux Guide](https://docs.rockylinux.org/guides/security/learning_selinux/) provides
-guidance on managing SELinux policies.
+Replace `/PATH/TO/cacti` and `apache` with the installed path and chosen poller
+account. Enable `crond` if using cron. Verify a manual poll under that account,
+then check scheduled runs, logs, collector status, and fresh graph samples.
-1. Check SELinux status
+## SELinux and containers
- ```console
- getenforce
- ```
+Keep SELinux enforcing. For a custom installation path, use persistent file
+contexts and allow writes only on Cacti's runtime paths. Review audit denials
+and authorize the specific network and executable access needed by FPM,
+RRDtool, SNMP tools, and the collector. Do not use `setenforce 0` as the
+installation procedure. See the [RHEL SELinux guide][selinux].
-2. Disable SELinux temporarily
+For LXC or Proxmox, retain an unprivileged container and its confinement where
+possible. Diagnose the specific ICMP/socket permission or mapped-file access
+failure. Adjust only the required capability or policy; do not make the entire
+container privileged or set an unconfined AppArmor profile merely to run Cacti.
- ```console
- setenforce 0
- ```
+## Optional Spine and proxies
-3. Re-enable SELinux
+Follow [Spine](Spine.md) for the optional compiled collector. Select a
+compatible source or package and the development headers for your OS.
+Repository names differ: do not apply Rocky/AlmaLinux `crb` commands to RHEL
+without checking its repository configuration. Configure the Spine database
+connection with the same application credentials and restrict access to its
+configuration file.
- ```console
- setenforce 1
- ```
+When using a reverse proxy, see the [proxy configuration in the general
+guide][proxy]. A header allowlist alone does not authenticate a proxy; prevent
+clients from bypassing the trusted proxy and require it to replace forwarded
+client-IP headers.
-**Note:** If Cacti is installed outside `/usr/share/nginx/html`, ensure that all
-SELinux file contexts and permissions are set correctly.
+[general]: General-Installing-Instructions.md#install-and-configure-cacti
+[proxy]: General-Installing-Instructions.md#considerations-when-using-proxies-in-front-of-cacti-cacti-1223
+[selinux]:
-### Considerations when using proxies in front of Cacti (Cacti 1.2.23+)
+[supported-os]: Requirements.md#supported-operating-systems
-For optimal security, specify only the HTTP headers that your proxy software
-actually sets. This prevents unauthorized access via header spoofing. Configure
-the setting by editing the following section of `config.php`:
+[rocky-php]:
+[rocky-10]:
-```ini
- * Allow the use of Proxy IPs when searching for client
- * IP to be used
- *
- * This can be set to one of the following:
- * - false: to use only REMOTE_ADDR
- * - true: to use all allowed headers (not advised)
- * - array of one or more the following:
- *'X-Forwarded-For',
- *'X-Client-IP',
- *'X-Real-IP',
- *'X-ProxyUser-Ip',
- *'CF-Connecting-IP',
- *'True-Client-IP',
- *'HTTP_X_FORWARDED',
- *'HTTP_X_FORWARDED_FOR',
- *'HTTP_X_CLUSTER_CLIENT_IP',
- *'HTTP_FORWARDED_FOR',
- *'HTTP_FORWARDED',
- *'HTTP_CLIENT_IP',
- *
- * NOTE: The following will always be checked:
- *'REMOTE_ADDR',
- */
-$proxy_headers = null;
-```
+[composer]:
---
+
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Installing-Under-Ubuntu-Debian.md b/Installing-Under-Ubuntu-Debian.md
index e2590a69..83dfa4f4 100644
--- a/Installing-Under-Ubuntu-Debian.md
+++ b/Installing-Under-Ubuntu-Debian.md
@@ -1,74 +1,59 @@
-# Installing Cacti 1.x on Ubuntu/Debian — LAMP Stack
+# Installing Cacti Development on Ubuntu or Debian with Apache
-> **Note**: As of Cacti 1.2.31, PHP 8.1 is required and PHP Composer is required.
-> Composer will be used to ensure all libraries are installed and up to date.
-> PHP 8.1 reached end-of-life on 31 December 2025. Check the
-> [PHP supported versions page](https://www.php.net/supported-versions.php)
-> and substitute the current supported release (e.g. `php8.3`) where appropriate.
+For nginx with PHP-FPM on Ubuntu Server 26.04 LTS or 26.10, use the
+[Ubuntu LEMP guide](Installing-Under-Ubuntu-LEMP.md).
-## Installing the required packages
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
-```console
-apt-get update
-apt-get install -y apache2 rrdtool mariadb-server snmp snmpd \
- php8.3 php8.3-mysql php8.3-snmp php8.3-xml php8.3-mbstring \
- php8.3-gd php8.3-gmp php8.3-zip php8.3-ldap \
- php8.3-intl php8.3-curl php8.3-fpm composer
-```
-
-### A special note for systems using PHP-FPM
-
-Before starting the Cacti setup process, restart the PHP-FPM daemon to rebuild
-its cache, or you may receive an HTTP 500 error.
+This is a source-install example for Cacti development (1.3), not a tested
+distribution
+matrix. Use a maintained distribution and check its PHP version against
+[Requirements](Requirements.md) before
+installing packages. Run the administrative commands below as root. The
+example uses `/var/www/html/cacti` and the default Debian/Ubuntu web account,
+`www-data`; adjust both if your web-server setup differs.
-```console
-systemctl restart php8.3-fpm
-```
-
-### A special note on installing Cacti in LXC containers (e.g. Proxmox)
+## Install the required packages
-We recommend creating a privileged container. You may need to update your
-container's config file with:
+The unversioned PHP package names select the distribution's configured PHP
+version. Confirm that it is PHP 8.3 or later in the PHP 8 series before
+continuing. Use a distribution or configured repository that supplies the
+required version; do not mix extensions from different PHP versions.
```console
-lxc.apparmor.profile: unconfined
-```
-
-This allows ICMP ping and other functions to work.
-
-A tested configuration is shown below; tune to your needs and standards.
-
-```console
-arch: amd64
-cores: 2
-hostname: cacti
-memory: 2048
-net0: name=eth0,bridge=vmbr0,firewall=1,hwaddr=mac-id,ip=dhcp,type=veth
-ostype: ubuntu
-rootfs: local-lvm:vm-110-disk-0,size=8G
-swap: 2048
-lxc.apparmor.profile: unconfined
+apt-get update
+apt-get install -y apache2 libapache2-mod-php mariadb-server rrdtool snmp git cron \
+ composer php-cli php-curl php-sqlite3 php-mysql php-snmp php-xml php-mbstring php-gd php-gmp php-zip php-ldap php-intl
+systemctl enable --now apache2 mariadb cron
```
-### Downloading the Cacti software
+If using PHP-FPM instead of the Apache PHP module, configure Apache's FPM
+integration and use the installed FPM pool's account. FPM service names are
+versioned on Debian/Ubuntu; inspect them with `systemctl list-unit-files
+'php*-fpm.service'` and restart the actual unit after configuration changes. Do
+not assume a service named `php-fpm` exists.
-Once the OS packages are installed, clone the Cacti repository:
+## Download the Cacti source
-```console
-git clone -b 1.2.x https://github.com/Cacti/cacti.git
-```
-
-Move the files into the web root and install Composer dependencies:
+This example checks out the unreleased `develop` branch. Record the commit you
+deploy; do not treat a moving development branch as a stable release.
```console
-mv cacti /var/www/html
+git clone --branch develop --depth 1 https://github.com/Cacti/cacti.git cacti
+mv cacti /var/www/html/cacti
cd /var/www/html/cacti
composer install --no-dev
+composer check-platform-reqs --no-dev
```
-### Database creation
+Do not overwrite an existing installation with these fresh-install commands.
-Create the Cacti database and user:
+## Create the database
+
+Choose a unique database password and replace the example placeholder in both
+the SQL and `include/config.php`. Connect using your database administrator's
+authentication method; the example below prompts for a password.
```console
mysql -u root -p
@@ -76,152 +61,136 @@ mysql -u root -p
```sql
CREATE DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-CREATE USER 'cactiuser'@'localhost' IDENTIFIED BY 'cactiuser';
-GRANT ALL ON cacti.* TO 'cactiuser'@'localhost';
+CREATE USER 'cactiuser'@'localhost' IDENTIFIED BY 'replace-with-a-unique-password';
+GRANT ALL PRIVILEGES ON cacti.* TO 'cactiuser'@'localhost';
GRANT SELECT ON mysql.time_zone_name TO 'cactiuser'@'localhost';
-FLUSH PRIVILEGES;
+EXIT;
```
-> **Security note**: Replace `cactiuser`/`cactiuser` with a strong,
-> unique username and password before using this in production.
-
-Import the default Cacti schema:
+Load the system timezone data and the schema into this new database. A MariaDB
+installation may provide `mariadb-tzinfo-to-sql` as the timezone utility's
+name.
```console
-mysql -u root cacti < /var/www/html/cacti/cacti.sql
+mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
+mysql -u root -p cacti < /var/www/html/cacti/cacti.sql
```
-### Creating the config file
+## Configure Cacti and filesystem permissions
+
+Copy the distributed configuration example; do not rename or delete it.
```console
-cd /var/www/html/cacti/include
-cp config.php.dist config.php
+cp /var/www/html/cacti/include/config.php.dist /var/www/html/cacti/include/config.php
```
-Edit `config.php` to match your database settings:
+Edit the database fields to match the account and database created above:
```php
$database_type = 'mysql';
$database_default = 'cacti';
$database_hostname = 'localhost';
$database_username = 'cactiuser';
-$database_password = 'cactiuser';
+$database_password = 'replace-with-a-unique-password';
$database_port = '3306';
-$database_retries = 5;
-$database_ssl = false;
-$database_ssl_key = '';
```
-### Create your cron task or systemd units file
-
-Starting with Cacti 1.2.16, you can use either a legacy crontab entry or the
-optional `cactid` systemd service to run your Cacti pollers.
-
-For crontab use, create and edit `/etc/cron.d/cacti`:
+Keep application code owned by the administrator. The web and poller accounts
+must be able to read the configuration and write the runtime directories:
```console
-*/5 * * * * www-data php /var/www/html/cacti/poller.php >/dev/null 2>&1
+chown root:www-data /var/www/html/cacti/include/config.php
+chmod 640 /var/www/html/cacti/include/config.php
+chown -R www-data:www-data /var/www/html/cacti/rra /var/www/html/cacti/log /var/www/html/cacti/cache
+chmod -R u+rwX,go-rwx /var/www/html/cacti/rra /var/www/html/cacti/log /var/www/html/cacti/cache
```
-For systemd, modify the included units file to reflect your install location
-and the desired user and group, then:
+During installation or package import, the installer also checks write access
+to `resource/snmp_queries`, `resource/script_server`, `resource/script_queries`
+and `scripts`, and the location used to create the CSRF secret. Grant only the
+additional access requested by the installer and remove that temporary access
+afterwards. Do not make the entire application tree world-writable.
-```console
-vim /var/www/html/cacti/service/cactid.service
-cp -p /var/www/html/cacti/service/cactid.service /etc/systemd/system
-mkdir -p /etc/default && touch /etc/default/cactid
-systemctl daemon-reload
-systemctl enable cactid
-systemctl start cactid
-systemctl status cactid
-```
+Restrict installer access to the administrator. Configure HTTPS or use a
+protected local connection before entering credentials, then browse to
+`/cacti/`. For a freshly imported development schema, sign in with application
+username `admin` and initial password `admin`, then choose a unique
+administrator password when prompted. These are separate from the database
+credentials. Complete the web installer before starting scheduled polling or
+allowing general access.
+
+## Schedule polling
+
+Choose either cron or `cactid.service`, not both. Complete the web installer
+before starting the selected scheduler. The example cron interval is five
+minutes; match the **Cron/Daemon Interval** in Settings > Poller. This is
+separate from the data-source polling interval, which can be shorter.
-Set directory ownership so Apache and the poller can write to necessary directories:
+### Cron
+
+Create `/etc/cron.d/cacti` as root, with mode `644`, and include this line:
```console
-chown -R www-data:www-data /var/www/html/cacti/rra /var/www/html/cacti/log /var/www/html/cacti/cache /var/www/html/cacti/resource
+*/5 * * * * www-data /usr/bin/php /var/www/html/cacti/poller.php >/dev/null 2>&1
```
-The system is now ready. Browse to
-[http://serverip/cacti](http://serverip/cacti) to start the Cacti
-initialization wizard.
+This is a system cron file, so the username field is required. Use an absolute
+PHP CLI path and POSIX shell redirection; Debian cron uses `/bin/sh` by
+default. See [Debian crontab format][crontab-format].
-### AppArmor Configuration
+### systemd
-Ubuntu and Debian enable AppArmor by default, but they do not ship a
-confinement profile for Apache, so on a stock system Apache runs unconfined
-and no AppArmor changes are needed for Cacti. This section applies only if you
-have deliberately installed and loaded an Apache profile (for example from the
-`apparmor-profiles-extra` package).
+The supplied unit uses `Type=forking`, so the selected PHP CLI must provide
+`pcntl_fork`. Check `/usr/bin/php -r
+'var_dump(function_exists("pcntl_fork"));'` for `bool(true)` before using this
+example. If fork support is unavailable, use cron or install the appropriate
+PCNTL support for that PHP CLI.
-First confirm whether an Apache profile is actually loaded:
+Copy the supplied service and edit the installed copy:
```console
-aa-status | grep apache2
-ls /etc/apparmor.d/usr.sbin.apache2 2>/dev/null
+cp /var/www/html/cacti/service/cactid.service /etc/systemd/system/cactid.service
```
-If neither prints anything, Apache is unconfined and you can skip this section.
-If a profile is present and denials appear in `/var/log/syslog` or `dmesg`:
+Replace its existing `User`, `Group`, `EnvironmentFile` and `ExecStart` entries
+with the following, retaining the other service settings:
-```console
-grep -i "apparmor.*DENIED" /var/log/syslog | grep -E "apache|php"
+```ini
+User=www-data
+Group=www-data
+EnvironmentFile=-/etc/default/cactid
+ExecStart=/usr/bin/php /var/www/html/cacti/cactid.php
```
-add a local override so Apache can reach the Cacti directories
-(adjust the path if Cacti is not installed under `/var/www/html/cacti`):
+The leading `-` makes the optional environment file unnecessary if you do not
+use one. After completing the installer, load and start the service:
```console
-cat > /etc/apparmor.d/local/usr.sbin.apache2 << 'EOF'
-# Cacti: allow Apache to read web root and write to RRD/log/cache dirs
-/var/www/html/cacti/** r,
-/var/www/html/cacti/rra/** rw,
-/var/www/html/cacti/log/** rw,
-/var/www/html/cacti/cache/** rw,
-EOF
-
-apparmor_parser -r /etc/apparmor.d/usr.sbin.apache2
-systemctl restart apache2
+systemctl daemon-reload
+systemctl enable cactid.service
+systemctl start cactid.service
+systemctl status cactid.service
```
-Verify AppArmor is enforcing (not complaining) and no new denials appear:
-
-```console
-aa-status | grep apache2
-grep -i "apparmor.*DENIED" /var/log/syslog | grep apache | tail -5
-```
+The service manages the local polling daemon; it does not by itself provide
+high availability. Verify the poller log and newly created graphs after
+starting the selected scheduler.
-### Considerations when using proxies in front of Cacti (Cacti 1.2.23+)
+### Considerations when using Proxies in front of Cacti (Cacti 1.2.23+)
-For optimal security, specify only the HTTP headers that your proxy software
-actually sets. Configure this by editing the following section of `config.php`:
+A header allowlist does not authenticate a proxy. Trust forwarded client-IP
+headers only when a trusted proxy replaces those headers and untrusted clients
+cannot bypass it to reach Cacti directly. Leave forwarding disabled otherwise.
+In `include/config.php`, select only the headers your proxy sets. For a
+deployment using `X-Forwarded-For`, the setting is:
-```ini
- * Allow the use of Proxy IPs when searching for client
- * IP to be used
- *
- * This can be set to one of the following:
- * - false: to use only REMOTE_ADDR
- * - true: to use all allowed headers (not advised)
- * - array of one or more the following:
- *'X-Forwarded-For',
- *'X-Client-IP',
- *'X-Real-IP',
- *'X-ProxyUser-Ip',
- *'CF-Connecting-IP',
- *'True-Client-IP',
- *'HTTP_X_FORWARDED',
- *'HTTP_X_FORWARDED_FOR',
- *'HTTP_X_CLUSTER_CLIENT_IP',
- *'HTTP_FORWARDED_FOR',
- *'HTTP_FORWARDED',
- *'HTTP_CLIENT_IP',
- *
- * NOTE: The following will always be checked:
- *'REMOTE_ADDR',
- */
-$proxy_headers = null;
+```php
+$proxy_headers = ['X-Forwarded-For'];
```
+[crontab-format]:
+[supported-os]: Requirements.md#supported-operating-systems
+
---
+
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Installing-Under-Ubuntu-LEMP.md b/Installing-Under-Ubuntu-LEMP.md
new file mode 100644
index 00000000..d747eae7
--- /dev/null
+++ b/Installing-Under-Ubuntu-LEMP.md
@@ -0,0 +1,194 @@
+# Installing Cacti on Ubuntu Server with nginx
+
+This fresh-install guide covers Cacti development (1.3) with nginx, PHP-FPM,
+and MariaDB. Use the [requirements](Requirements.md) for this Cacti branch.
+For an existing installation, follow [Upgrading Cacti](Upgrading-Cacti.md).
+Do not overlay source files onto a package-managed Cacti installation.
+
+## Choose a supported Ubuntu release
+
+As of 26 October 2026, the latest LTS is **Ubuntu Server 26.04 LTS** and the
+latest interim release is **Ubuntu Server 26.10**. Use fully updated packages.
+The interim release has a shorter maintenance window; plan its next upgrade
+before security support expires. See the [LTS release notes][ubuntu-lts],
+[interim release notes][ubuntu-interim], and [Ubuntu lifecycle][ubuntu-cycle].
+
+| Ubuntu release | PHP selection | PHP-FPM unit and socket |
+| --- | --- | --- |
+| 26.04 LTS | Distribution PHP 8.5 packages | `php8.5-fpm.service`, `/run/php/php8.5-fpm.sock` |
+| 26.10 | Distribution PHP 8.5 packages | `php8.5-fpm.service`, `/run/php/php8.5-fpm.sock` |
+
+The [Ubuntu package index][ubuntu-php] documents the LTS FPM package; the
+[interim package index][ubuntu-php-interim] lists the corresponding package
+for 26.10. Check the package candidates before installation. Vendor OS support
+and package availability do not establish that every Cacti plugin has been
+tested with that PHP version. Validate the selected Cacti and plugin set on
+an isolated installation before production use.
+
+## Install nginx, PHP-FPM, and MariaDB
+
+Run administrative commands as root. Enable Ubuntu's Universe repository if
+it is not already enabled, then install the packages:
+
+```console
+apt-get update
+apt-get install -y software-properties-common
+add-apt-repository -y universe
+apt-get update
+apt-cache policy php-fpm php-cli mariadb-server nginx
+apt-get install -y nginx mariadb-server rrdtool snmp cron git \
+ php-fpm php-cli php-mysql php-snmp php-xml php-mbstring php-gd php-gmp \
+ php-zip php-ldap php-intl php-curl php-sqlite3 composer
+php -v
+php --ini
+php -m
+```
+
+Use packages from a consistent Ubuntu release and repository set. Do not
+install `libapache2-mod-php` for this nginx/FPM setup. If Apache is already
+bound to the chosen HTTP/HTTPS ports, resolve that conflict before starting
+nginx rather than running two servers on the same address and port.
+
+Set `date.timezone` for the CLI and FPM configurations, normally under
+`/etc/php/8.5/cli/php.ini` and `/etc/php/8.5/fpm/php.ini`. Verify the FPM pool
+at `/etc/php/8.5/fpm/pool.d/www.conf` uses the intended account and socket:
+
+```ini
+user = www-data
+group = www-data
+listen = /run/php/php8.5-fpm.sock
+listen.owner = www-data
+listen.group = www-data
+listen.mode = 0660
+```
+
+Edit the existing entries. The nginx worker must be able to connect to that
+socket. Check the actual pool if you changed the account, PHP version, or
+socket path. Validate FPM configuration and enable the services:
+
+```console
+php-fpm8.5 -t
+systemctl enable --now mariadb php8.5-fpm nginx cron
+```
+
+## Deploy Cacti and create the database
+
+Run dependency installation as the deployment owner in the source directory,
+before installing it under the administrator-owned web root:
+
+```console
+git clone --branch develop --depth 1 https://github.com/Cacti/cacti.git cacti
+cd cacti
+composer install --no-dev
+composer check-platform-reqs --no-dev
+```
+
+Record `git rev-parse HEAD` and deploy that complete tree, including its locked
+dependencies, to `/var/www/html/cacti`. Use administrator privileges only for
+placement, ownership, and system configuration.
+
+Follow [General Installing Instructions][general] to create the new database
+and dedicated application account, load timezone data, import the matching
+`cacti.sql`, and copy/configure `include/config.php`. These are fresh-install
+steps; do not import the default schema over an existing Cacti database.
+
+Use the `www-data` FPM/poller account for this example's runtime permissions.
+Keep code owned by the administrator, configuration readable only by the
+required identities, and write access limited to runtime paths. Grant extra
+installation/import access only where the installer requests it and remove
+that access afterward. Database credentials and OS service accounts are
+separate identities.
+
+## Configure nginx and HTTPS
+
+Provision a certificate for your hostname using your certificate-management
+procedure. Replace `cacti.example.com` and the certificate/key paths below.
+Save this virtual host as `/etc/nginx/sites-available/cacti`:
+
+```nginx
+server {
+ listen 80;
+ server_name cacti.example.com;
+ return 301 https://cacti.example.com$request_uri;
+}
+
+server {
+ listen 443 ssl;
+ server_name cacti.example.com;
+ root /var/www/html;
+ index index.php;
+ ssl_certificate /etc/ssl/certs/cacti.crt;
+ ssl_certificate_key /etc/ssl/private/cacti.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ location = / { return 302 /cacti/; }
+ location = /cacti { return 301 /cacti/; }
+
+ # nginx does not process Cacti's Apache .htaccess restrictions.
+ location ~ (^|/)\. { deny all; }
+ location ~ ^/cacti/(bin|cli|contrib|log|mibs|rra|scripts|service|tests)/ {
+ deny all;
+ }
+ location ~ ^/cacti/cache/(boost|mibcache|realtime|spikekill)/ {
+ deny all;
+ }
+ location ~ ^/cacti/include/(config(_local)?\.php|vendor/.*\.php) {
+ deny all;
+ }
+
+ location ~ ^/cacti/(.+\.php)$ {
+ try_files $uri =404;
+ include /etc/nginx/fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_pass unix:/run/php/php8.5-fpm.sock;
+ }
+ location /cacti/ { try_files $uri $uri/ =404; }
+}
+```
+
+Enable this site once, without overwriting an existing link or configuration:
+
+```console
+ln -s /etc/nginx/sites-available/cacti /etc/nginx/sites-enabled/cacti
+nginx -t
+systemctl reload nginx
+```
+
+Review the packaged default site and other virtual hosts for conflicts. Keep
+private-path rules before the PHP handler, leave required static vendor
+assets accessible, and store backups outside every web root. Confirm over
+HTTP that private files are denied and PHP requests execute rather than
+expose source. Restrict installation access to administrators until complete.
+
+## Complete installation and schedule polling
+
+Open `https://cacti.example.com/cacti/`, complete the installer, and check the
+CLI and web PHP environments separately. Verify executable paths, timezone
+data, filesystem permissions, and optional Spine before enabling collection.
+
+Configure either cron or `cactid`, using the [Ubuntu scheduler guide][polling].
+Do not run both for one collector. For the default five-minute scheduler,
+create `/etc/cron.d/cacti` with mode `644` and this system-cron entry:
+
+```cron
+*/5 * * * * www-data /usr/bin/php /var/www/html/cacti/poller.php >/dev/null 2>&1
+```
+
+Run a manual polling cycle as the poller account before scheduling, then
+verify scheduled execution, collector status, logs, and recent RRD samples.
+Keep AppArmor enforcing and adjust only the specific policy and filesystem
+access required by the deployed services. For reverse proxies, use the
+[trusted-proxy guidance][proxy] rather than trusting arbitrary client headers.
+
+[ubuntu-lts]:
+[ubuntu-interim]:
+[ubuntu-cycle]:
+[ubuntu-php]:
+[ubuntu-php-interim]:
+[general]: General-Installing-Instructions.md#install-and-configure-cacti
+[polling]: Installing-Under-Ubuntu-Debian.md#schedule-polling
+[proxy]: General-Installing-Instructions.md#considerations-when-using-proxies-in-front-of-cacti-cacti-1223
+
+---
+
+Copyright (c) 2004-2026 The Cacti Group
diff --git a/Installing-Under-Windows.md b/Installing-Under-Windows.md
index 46d5bb83..ed261a8e 100644
--- a/Installing-Under-Windows.md
+++ b/Installing-Under-Windows.md
@@ -1,376 +1,371 @@
# Installing Under Windows
-> **Note**: As of Cacti 1.2.31, PHP 8.1 is required and PHP Composer is required.
-> Composer will be used to ensure all libraries are installed and up to date.
-
-BSOD2600, one of the long-term users of Cacti, provides an installer for Windows.
-We recommend using that installer. You can obtain it under the Windows section of
-the Cacti forums. If you prefer to install Cacti manually, follow the instructions
-below.
-
-1. (Optional) Apache - This software is optional if running Windows Internet
- Information Server.
-
-2. Cacti - Install from the zip distribution into the web root of your choice.
- Many choose to install into a `Cacti` subfolder.
-
-3. Spine - Install from the zip distribution into the `c:\cacti` directory.
- Ensure `spine.conf.dist` is located in that directory as well.
-
-4. RRDtool - Install from the Cacti website into the `c:\cacti` directory.
-
-5. PHP 8.x - Install into the `c:\php` folder. If you choose to install into
- `c:\Program Files\php`, you will have to use 8.3 filenames to reference its
- binaries in Cacti.
-
-6. MySQL 8.x or MariaDB 10.5+ - Install into the default locations.
- For MySQL this is typically:
-
- `c:\Program Files\MySQL\MySQL Server X.XX`
-
- For MariaDB it is typically:
-
- `c:\Program Files\MariaDB`
-
- After the database is confirmed running, apply the following settings to the
- `my.ini` file:
-
- ```ini
- [mysqld]
- character-set-server = utf8mb4
- collation-server = utf8mb4_unicode_ci
- max_heap_table_size = 770M # Adjust for your OS memory size
- max_allowed_packet = 500M # Adjust for your OS memory size
- tmp_table_size = 512M # Adjust for your OS memory size
- join_buffer_size = 256M # Adjust for your OS memory size
- sort_buffer_size = 32M # Per-session buffer; keep small to avoid OOM under load
-
- # sql_mode: NO_AUTO_CREATE_USER was removed in MySQL 8.0; omit it on MySQL 8+
- sql_mode = NO_ENGINE_SUBSTITUTION
-
- innodb_flush_log_at_trx_commit = 2
- innodb_flush_log_at_timeout = 3
- innodb_file_per_table = ON
-
- innodb_buffer_pool_size = 4500M # Adjust for your OS memory size
-
- # innodb_file_format and innodb_large_prefix removed in MySQL 8.0 /
- # MariaDB 10.3+; omit those settings on newer releases.
-
- # for SSDs on a multi-core server
- innodb_doublewrite = OFF
- innodb_read_io_threads = 32
- innodb_write_io_threads = 16
- innodb_io_capacity = 10000
- innodb_io_capacity_max = 20000
- innodb_flush_method = O_DIRECT
- ```
-
- Restart MariaDB/MySQL after applying these settings. Once you start the
- installer, Cacti will recommend better values for your hardware.
-
- Write down your MariaDB/MySQL root password and keep a backup copy in a safe
- place.
-
-7. (Optional) Cygwin - Download and execute `setup-x86_64.exe` from the Cygwin
- website. Keep the `setup-x86_64.exe` file for later use. You will need Cygwin
- and its development packages for building RRDtool and Spine.
-
-8. (Optional) Net-SNMP - Install to the `c:\usr` directory. If you choose to
- use `c:\Program Files\net-snmp`, you will have to use 8.3 filenames to
- reference its binaries in Cacti. The default installation location for
- Net-SNMP on Windows is `c:\usr`, which closely aligns with Linux and Unix
- install paths.
-
-## Common OS Changes
-
-The following changes are required regardless of your selected web server.
-
-1. Add the following directory to the existing Windows System `PATH` environment
- variable: `c:\php`. The Windows PATH can be accessed via:
- Control Panel → System → Advanced → Environment Variables → System Variables.
-
-2. Add a new Windows System environment variable `PHPRC` set to `c:\php`.
-
-3. Add a new Windows System environment variable `MIBDIRS` set to
- `c:\php\extrasmibs`.
-
-4. Rename `c:\php\php.ini.dist` to `php.ini`, and make the following changes.
- The Cacti installer will guide you through enabling additional modules.
-
- ```ini
- extension_dir = c:\php\ext
- extension=php_pdo_mysql.dll
- extension=php_snmp.dll
- extension=php_sockets.dll
- cgi.force_redirect = 0
- date.timezone = America/Detroit
- memory_limit = 800M
- max_execution_time = 300
- ```
-
- > **Note**: `php_mysql.dll` (the old `mysql_*` extension) was removed in
- > PHP 7.0. Use `php_pdo_mysql.dll` instead.
-
-5. In earlier PHP installation guides, moving certain DLLs to
- `c:\winnt\system32` was recommended. If you followed those guides, remove
- those files. Review the PHP installation documentation for instructions.
-
-6. To allow template importing, uncomment the following line:
-
- ```ini
- file_uploads = On
- ```
-
-7. Give the user running the scheduled task modify rights to the `.index` file
- in the location pointed to by the `MIBDIRS` environment variable.
-
-## Web Server Configuration
-
-1. Ensure you have stopped any IIS web servers before proceeding with Apache
- installation, or configure Apache on an alternate port.
-
-2. If using Apache 2.x with PHP 8, add the following lines. Adjust values for
- your version of PHP and Apache.
-
- ```ini
- LoadModule php_module "C:\php\php8apache2_4.dll"
- AddHandler application/x-httpd-php .php
- AddType application/x-httpd-php .php
- DirectoryIndex index.html index.htm index.php
- PHPIniDir "C:\php"
- ```
-
-## IIS Specific Steps
-
-PHP 8.0 removed ISAPI support. For IIS with PHP 8, use the FastCGI handler
-instead of ISAPI.
-
-1. Install the **IIS FastCGI module** if it is not already present (available
- via Windows Server roles or Web Platform Installer).
-
-2. Open IIS Manager. At the server level, open **FastCGI Settings** and add a
- new application:
- - **Full Path**: `C:\php\php-cgi.exe`
- - Set **InstanceMaxRequests** to `10000`
-
-3. In the site or server **Handler Mappings**, add a new module mapping:
- - **Request path**: `*.php`
- - **Module**: `FastCgiModule`
- - **Executable**: `C:\php\php-cgi.exe`
-
-4. Under the **Default Document** feature, add `index.php` to the list.
-
-5. Give the IIS application pool identity (or `IUSR`) read and execute
- permissions on `%windir%\system32\cmd.exe`, and read/write/execute on the
- Cacti directories:
-
- ```batchfile
- icacls "C:\windows\system32\cmd.exe" /grant "IUSR:(OI)(CI)(RX,W)"
- icacls "C:\inetpub\wwwroot\cacti\resource\snmp_queries" /grant "IUSR:(OI)(CI)(RX,W)"
- icacls "C:\inetpub\wwwroot\cacti\resource\script_server" /grant "IUSR:(OI)(CI)(RX,W)"
- icacls "C:\inetpub\wwwroot\cacti\scripts" /grant "IUSR:(OI)(CI)(RX,W)"
- icacls "C:\inetpub\wwwroot\cacti\rra" /grant "IUSR:(OI)(CI)(RX,W)"
- icacls "C:\inetpub\wwwroot\cacti\log" /grant "IUSR:(OI)(CI)(RX,W)"
- icacls "C:\inetpub\wwwroot\cacti\cache" /grant "IUSR:(OI)(CI)(RX,W)"
- icacls "C:\inetpub\wwwroot\cacti\include\config.php" /grant "IUSR:(RX,W)"
- copy /b NUL "C:\inetpub\wwwroot\cacti\include\vendor\csrf\csrf-secret.php"
- icacls "C:\inetpub\wwwroot\cacti\include\vendor\csrf\csrf-secret.php" /grant "IUSR:(RX,W)"
- ```
-
-6. Completely stop and start the IIS service:
-
- ```batchfile
- net stop iisadmin
- net start w3svc
- ```
-
-## Cygwin Installation Steps for Spine and RRDtool
-
-1. Installing a single instance of Cygwin and using it for all applications
- is recommended. Multiple Cygwin installations can have conflicting DLL
- versions.
-
-2. Run the `setup-x86_64.exe` you downloaded previously.
-
-3. At the **Select Packages** step, install the following packages (version
- numbers may have changed):
-
- - Base (include all items)
- - Libs
- - libcairo2
- - libcrypt0
- - libfontconfig-common
- - libfontconfig1
- - libfreetype6
- - libgcrypt20
- - libgd3
- - libglib2.0_0
- - libmariadb3
- - libssl1.0
- - libpango1.0_0
- - libpng16
- - libreadline7
- - zlib-devel
- - zlib0
- - Devel
- - autoconf
- - automake
- - binutils
- - clang
- - cygwin-devel
- - gcc-core
- - gcc-g++
- - libmariadb-devel
- - help2man
- - libargp
- - libltdl7
- - libtool
- - net-snmp-devel
- - patch
- - texinfo
- - w32api-headers
- - w32api-runtime
- - windows-default-manifest
- - Web
- - wget
-
-4. Add `c:\cygwin\bin` to your Windows System PATH environment variable.
-
-5. Move `setup-x86_64.exe` to `c:\cygwin` for future use. Update this binary
- periodically, as it is updated from time to time.
-
-## RRDtool Download and Installation
-
-1. Obtain Windows-compatible builds of RRDtool from https://rrdtool.org and
- install to `C:\rrdtool`.
-
-2. Create the MariaDB/MySQL database:
-
- ```sh
- shell> mysqladmin --user=root --password create cacti
- ```
-
-3. Import the default Cacti database:
-
- ```sh
- shell> mysql --user=root --password cacti < c:\apache2\htdocs\cacti\cacti.sql
- ```
-
-4. Create a MySQL username and password for Cacti:
-
- ```sh
- shell> mysql --user=root --password mysql
- ```
-
- ```sql
- MySQL> CREATE USER 'cactiuser'@'localhost' IDENTIFIED BY 'cactiuser';
- MySQL> GRANT ALL ON cacti.* TO 'cactiuser'@'localhost';
- MySQL> GRANT SELECT ON mysql.time_zone_name TO 'cactiuser'@'localhost';
- MySQL> ALTER DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- MySQL> FLUSH PRIVILEGES;
- ```
-
-## Net-SNMP Installation
-
-1. If you plan to use SNMP v2c and are using early versions of PHP, download
- and install the Net-SNMP libraries. Net-SNMP provides an installer.
-
- If you use long directory names, note that Cacti requires 8.3 notation:
-
- | Format | Path |
- | --- | --- |
- | Original | `c:\Program Files\Net-SNMP\bin` |
- | 8.3 notation | `c:\progra~1\net-snmp\bin` |
-
-## Cacti Spine Installation
-
-1. Extract the Spine zip file to `c:\spine` and edit `spine.conf.dist` with
- your database details:
-
- ```ini
- DB_Host 127.0.0.1
- DB_Database cacti
- DB_User cactiuser
- DB_Password cactiuser
- DB_Port 3306
- ```
-
- > **Note**: Use `127.0.0.1` rather than `localhost` for the DB host on Windows.
-
-2. Spine is distributed as a binary. We strongly recommend installing Cygwin
- and removing all DLL files and `sh.exe` from `c:\spine`, keeping only
- `spine.exe` and `spine.conf`.
-
-## Finishing Your Setup
-
-1. Edit `cacti_web_root/cacti/include/config.php` and specify the database
- connection details:
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
+
+These instructions describe a manual installation of Cacti development (1.3) on
+Windows. Use the [requirements](Requirements.md) for your Cacti release and
+supported Windows builds of PHP, your database server and RRDtool. Community
+Windows installers are also discussed in the [Cacti
+forums](https://forums.cacti.net/); check their included versions and
+maintenance status before using them.
+
+The examples use `C:\inetpub\wwwroot\cacti` for Cacti, `C:\php` for PHP,
+`C:\rrdtool` for RRDtool and `C:\spine` for optional Spine. Substitute your
+actual paths throughout. Use a dedicated Windows account for the poller and a
+separate web-server identity. Install software and configure services as an
+administrator; the poller does not normally need administrator privileges.
+
+## Development packaging prerequisite
+
+The current development dependency manifest requires PHP `^8.3`, including
+`ext-pcntl` and `ext-posix` unconditionally. Native Windows PHP cannot supply
+those two extensions. A source checkout therefore cannot currently install its
+Composer dependencies on native Windows. A bundled artifact must also pass its
+generated runtime platform check. Stop if it rejects Windows and use a
+compatible release or a Unix installation. Do not bypass platform checks or
+edit generated vendor files to force an incompatible installation.
+
+The remaining instructions apply only to an artifact that passes its platform
+checks. Read the [PHP PCNTL platform restriction][pcntl] and the selected
+revision's [dependency manifest][manifest] before choosing an artifact.
+
+## Install the software
+
+1. Choose IIS or Apache and install only the web server you intend to use on
+ the selected address and port.
+
+2. Extract the Cacti ZIP distribution into the chosen web directory.
+
+3. Install PHP and its required runtime libraries using the
+ [PHP Windows installation instructions][php-windows]. Match the architecture
+ and build type to your web-server integration. Use a Non-Thread-Safe build
+ for IIS FastCGI; an Apache module requires a compatible Thread-Safe build.
+ A path without spaces, such as `C:\php`, simplifies tool configuration.
+
+4. Install a Windows build of [RRDtool](https://oss.oetiker.ch/rrdtool/) and
+ verify its runtime dependencies. If using Spine, install a compatible
+ [Spine release](Spine.md) and the dependencies supplied or required by that
+ build. The PHP poller can be used without Spine.
+
+5. Install MySQL or MariaDB. Use the server's supported Windows configuration
+ and service-management instructions. Start with its documented defaults,
+ then review the Cacti installer's checks for your actual server and
+ workload.
+
+ Do not copy a tuning block from a different database version or operating
+ system. MySQL 8 removed `NO_AUTO_CREATE_USER`, `innodb_file_format` and
+ `innodb_large_prefix`; these settings can prevent startup. Do not disable
+ InnoDB doublewrite protection or reduce commit durability as an installation
+ shortcut. Size global and per-connection buffers for the available memory
+ and expected concurrency.
+
+6. Install Net-SNMP command-line tools if your collection configuration needs
+ them, for example into `C:\usr`. Cacti uses these tools for SNMPv3
+ requests from the web interface and PHP poller; PHP's SNMP extension alone
+ does not provide that collection path. Verify the installed executable paths
+ instead of assuming a particular short filename or installation directory.
+
+## Configure PHP
+
+Copy `php.ini-production` from the PHP distribution to `C:\php\php.ini`. Set
+the timezone for your installation and enable the required extensions. For
+current PHP Windows builds, an example configuration is:
+
+```ini
+extension_dir = "C:\php\ext"
+extension=curl
+extension=pdo_mysql
+extension=sqlite3
+extension=gd
+extension=gmp
+extension=intl
+extension=ldap
+extension=mbstring
+extension=openssl
+extension=sockets
+extension=com_dotnet
+; Enable if using PHP's SNMP extension:
+extension=snmp
+
+date.timezone = America/Detroit
+file_uploads = On
+```
+
+Use only extensions supplied for the selected PHP build and install their
+required DLL dependencies according to PHP's instructions. Some modules are
+built in. The Cacti installer checks additional modules, including SimpleXML,
+XML and zlib, in both the web and command-line environments. `pdo_mysql` is the
+database driver Cacti uses; the removed `php_mysql.dll` is not a substitute.
+Set memory and execution limits using the installer recommendations for your
+installation rather than copying values sized for another server.
+
+Check the command-line configuration before configuring the web server:
+
+```console
+C:\php\php.exe --ini
+C:\php\php.exe -m
+```
+
+Set `PHPRC` to `C:\php` for the web-server and poller environments if needed to
+select this configuration. An absolute path to `php.exe` avoids depending on
+`PATH` for scheduled tasks. Ensure required DLLs are discoverable by both
+identities; do not copy PHP DLLs into Windows system directories.
+
+If loading external MIBs, set `MIBDIRS` to their actual directory and allow the
+collecting account to update the Net-SNMP index/cache there if needed. This is
+separate from permission to modify executable files.
+
+After changing PHP configuration, recycle the application pool or restart the
+selected web-server service. Confirm the Cacti installer reports the expected
+configuration and modules for both web PHP and CLI PHP.
+
+## Configure the web server
+
+### IIS with FastCGI
+
+Follow the [PHP IIS instructions][php-iis] and Microsoft's
+[FastCGI configuration reference][iis-fastcgi].
+
+1. Enable the IIS CGI role service, which supplies FastCGI support.
+
+2. Create the Cacti site/application and a dedicated application pool. Match
+ the pool architecture to PHP. In Handler Mappings, map `*.php` through
+ `FastCgiModule` to `C:\php\php-cgi.exe`, not `php.exe`. Use the
+ corresponding
+ FastCGI application entry and allow script execution for the application.
+ PHP 8 does not provide `php8isapi.dll`; do not configure an ISAPI filter.
+
+3. Add `index.php` to the site's Default Document list. Apply the PHP CGI
+ settings required by the PHP IIS guide, including `cgi.force_redirect=0`
+ for IIS. Configure authentication/impersonation deliberately so the account
+ accessing Cacti files is known.
+
+4. Configure an HTTPS binding and restrict access during installation. Recycle
+ the affected application pool after configuration changes.
+
+### Apache
+
+Follow the [PHP Apache instructions][php-apache] for a matching Apache/PHP
+build. For Apache 2.4 with a compatible PHP 8 Thread-Safe module, the relevant
+configuration is:
+
+```apache
+LoadModule php_module "C:/php/php8apache2_4.dll"
+
+ SetHandler application/x-httpd-php
+
+DirectoryIndex index.php index.html
+PHPIniDir "C:/php"
+```
+
+Check Apache's configuration before restarting its service. If using FastCGI
+instead of the Apache module, follow that integration's PHP instructions and
+use the appropriate PHP build.
+
+## File permissions
+
+Identify the effective web identity and the scheduled-task account before
+setting ACLs. For IIS, this may be `IIS AppPool\Cacti` for a pool named
+`Cacti`, or another account selected by authentication and FastCGI
+impersonation. See Microsoft's [application-pool identity
+guidance][iis-identity]. Do not assume the account is always `IUSR`.
+
+Give the web and poller identities read access to Cacti's code and
+configuration, and read/execute access to PHP, RRDtool, SNMP and optional Spine
+programs and their dependencies. If PHP requires `cmd.exe` to launch a command,
+allow only the necessary read/execute access. Do not grant either identity
+write access to Windows system executables or to tool installation directories.
+
+The poller needs Modify permission on `rra` and `log` and on the cache
+subdirectories it uses. The web identity also needs Modify permission on `log`,
+its configured temporary/session directories and the Cacti cache subdirectories
+used by features such as real-time graphs. Use the installer's permission
+checks to identify the required paths, including `cache/boost`,
+`cache/mibcache`, `cache/realtime` and `cache/spikekill`. Grant access only to
+the identities and paths that need it, accounting for inherited ACLs.
+
+During installation or signed-package imports, Cacti also needs to write
+queries and scripts under `resource/snmp_queries`, `resource/script_server`,
+`resource/script_queries` and `scripts`. Grant temporary Modify access to the
+identity performing that operation, then remove it when finished. The installer
+also needs to initialize a nonempty CSRF secret, by default
+`include/vendor/csrf/csrf-secret.php`. Allow creation in its containing
+directory during setup, then retain read access to the generated secret and
+remove the temporary directory write permission. Do not create an empty
+placeholder secret.
+
+Edit `include/config.php` as an administrator. Keep it readable by the web and
+poller identities but not writable by them for ordinary operation. If a
+specific installation operation needs to update it, grant temporary write
+access for that operation and remove it afterward.
+
+## Create the database
+
+The following commands are for **Command Prompt**, not PowerShell. Use the
+actual path to `mysql.exe` or the equivalent MariaDB client if it is not on
+`PATH`. The `--password` option prompts for the database administrator's
+password; do not put that password on the command line.
+
+```console
+mysql --user=root --password
+```
+
+Create an empty database and a dedicated application account. Replace
+`REPLACE_WITH_UNIQUE_DATABASE_PASSWORD` with a unique secret before executing
+this SQL. The example account and connection use TCP loopback consistently.
+
+```sql
+CREATE DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE USER 'cacti_user'@'127.0.0.1'
+ IDENTIFIED BY 'REPLACE_WITH_UNIQUE_DATABASE_PASSWORD';
+GRANT ALL PRIVILEGES ON cacti.* TO 'cacti_user'@'127.0.0.1';
+GRANT SELECT ON mysql.time_zone_name TO 'cacti_user'@'127.0.0.1';
+```
+
+Exit the SQL client and import the schema from the same Cacti release you
+extracted:
+
+```console
+mysql --user=root --password --default-character-set=utf8mb4 cacti < "C:\inetpub\wwwroot\cacti\cacti.sql"
+```
+
+Ensure the server's time-zone tables are populated using its documented Windows
+procedure. Granting access to an empty `mysql.time_zone_name` table does not
+populate it. Resolve the database and time-zone checks reported by the Cacti
+installer before completing installation.
+
+## Optional Cygwin and Spine configuration
+
+If your Spine or RRDtool build depends on Cygwin, install the runtime packages
+required by that build using the official
+[Cygwin installer](https://cygwin.com/).
+For a source build, follow the release's build instructions and select its
+current compiler/development dependencies. Do not replace or delete DLLs
+shipped with a binary distribution without checking that distribution's
+requirements. Avoid mixing incompatible Cygwin runtimes.
+
+For Spine, copy `spine.conf.dist` to `spine.conf` and set the connection
+details to match Cacti. Replace the password placeholder with the same
+application secret used above, not a sample password:
+
+```ini
+DB_Host 127.0.0.1
+DB_Database cacti
+DB_User cacti_user
+DB_Pass REPLACE_WITH_UNIQUE_DATABASE_PASSWORD
+DB_Port 3306
+```
+
+Restrict access to `spine.conf` to administrators and the poller account.
+Verify Spine from that account before selecting it as the poller in Cacti.
+
+## Finish the Cacti installation
+
+1. Copy `include/config.php.dist` to `include/config.php` and set its database
+ connection. Replace the password placeholder with your application secret:
```php
- $database_default = "cacti";
- $database_hostname = "localhost";
- $database_username = "cactiuser";
- $database_password = "cactiuser";
- $database_port = "3306";
+ $database_default = 'cacti';
+ $database_hostname = '127.0.0.1';
+ $database_username = 'cacti_user';
+ $database_password = 'REPLACE_WITH_UNIQUE_DATABASE_PASSWORD';
+ $database_port = '3306';
+ $url_path = '/cacti/';
```
-2. Browse to `http://your-server/cacti/` and log in with `admin`/`admin`.
- You will be prompted to change the password immediately.
+ Adjust `$url_path` if Cacti is served at another URL path.
-3. Go to **Settings → Paths** and verify/update all paths to point to the
- correct locations. If using Spine, all paths must use forward slashes.
-
- - PHP Binary Path: `c:/php/php.exe`
- - RRDtool Binary Path: `c:/rrdtool/rrdtool.exe`
- - SNMP Binary Paths: `c:/usr/bin/snmpget.exe`, `c:/usr/bin/snmpwalk.exe`, etc.
- - Cacti Logfile Path: `c:/mycacti/website/cacti/log/cacti.log`
- - Spine Path: `c:/spine/spine.exe`
-
-4. If you enabled automation, once the Cacti poller starts it will discover
- compatible devices using your SNMP settings and default automation rules.
- A Localhost device is created automatically at install time.
-
-5. Log into the account you will use for the scheduled task and verify a
- polling cycle works:
-
- ```sh
- php c:/cacti_web_root/cacti/poller.php
- ```
+2. Open the Cacti URL through HTTPS. For a freshly imported development schema,
+ sign in with application username `admin` and initial password `admin`,
+ then choose a unique administrator password when prompted. These are
+ separate from the database credentials. Complete the installer and resolve
+ its dependency, database, path and permission checks before allowing
+ general access.
- Expected output includes lines like:
+3. In **Console > Configuration > Settings > Paths**, verify the executable
+ paths against your installation. For the example layout:
- ```
- OK u:0.00 s:0.06 r:1.32
- 10/28/2005 04:57:12 PM - SYSTEM STATS: Time:4.7272 Method:cmd.php ...
- ```
-
- After the first run, `cacti.log` will appear in `/cacti/log/` and RRD files
- in `/cacti/rra/`.
-
-6. Schedule a recurring task to run `poller.php` every 5 minutes:
-
- > **Note**: The following instructions apply to most Windows versions.
-
- 1. Open **Task Scheduler** (Control Panel → Scheduled Tasks).
- 2. Click **Add Scheduled Task** and then **Next**.
- 3. Browse to `c:\php` and select `php.exe`. Choose **Daily** and click **Next**.
- 4. Click **Next** without changing the time or date settings.
- 5. Ensure the task account has the correct permissions on:
- - `cacti_web_root/cacti/rra`
- - `cacti_web_root/log`
- - `c:\php`
- - `c:\phpsapi`
- 6. Click **Next** and **Finish** to close the wizard.
- 7. Right-click the task and select **Properties**.
- 8. On the **Schedule** tab, confirm **Daily** is selected and click **Advanced**.
- 9. Check **Repeat**, set to **5 minutes**, and set duration to **24 hours**.
- 10. Click **OK**.
- 11. In the **Run** field, enter:
-
- `c:\php\php.exe c:\mycacti\website\cacti\poller.php`
-
- Set **Start in** to `c:\mycacti\website\cacti`.
+ | Setting | Example |
+ | --- | --- |
+ | PHP binary | `C:/php/php.exe` |
+ | RRDtool | `C:/rrdtool/rrdtool.exe` |
+ | SNMP tools, if used | `C:/usr/bin/snmpget.exe`, `snmpwalk.exe`, `snmpbulkwalk.exe`, `snmpgetnext.exe` |
+ | Cacti log | `C:/inetpub/wwwroot/cacti/log/cacti.log` |
+ | Spine, if used | `C:/spine/spine.exe` |
+
+ Use the CLI PHP executable here, not the IIS FastCGI executable. Verify the
+ separate Spine configuration path if selecting Spine.
+
+4. Create devices and graphs deliberately, or configure discovery and
+ automation
+ rules for the intended network. Installing Cacti does not establish that
+ every discovered device exposes all measurements in its selected template.
+
+## Schedule and verify the poller
+
+Log on as the intended poller account and test the same executable and paths
+that the task will use:
+
+```console
+C:\php\php.exe -q C:\inetpub\wwwroot\cacti\poller.php
+```
+
+Check `log/cacti.log`, data-source polling and graph updates. RRD files are
+created for configured data sources; an installation without graphs need not
+create them. Resolve permission and configuration errors before scheduling.
+
+Open **Task Scheduler** and choose **Create Task**:
+
+1. Select the dedicated poller account and **Run whether user is logged on or
+ not**, with the account rights needed for batch logon. Do not enable
+ **Run with highest privileges** unless a documented local requirement needs
+ it.
+
+2. Add a daily trigger that repeats every **5 minutes** indefinitely for the
+ default five-minute scheduler configuration. If changing Cacti's scheduler
+ interval, adjust this trigger to match it; the scheduler interval and data
+ source polling intervals are separate settings.
+
+3. Add a **Start a program** action with these separate fields:
+
+ - **Program/script:** `C:\php\php.exe`
+ - **Add arguments:** `-q "C:\inetpub\wwwroot\cacti\poller.php"`
+ - **Start in:** `C:\inetpub\wwwroot\cacti`
+
+4. Under **Settings**, choose **Do not start a new instance** if the task is
+ already running. Review any task execution limit against the configured
+ polling cycle; do not terminate a healthy poller prematurely.
+
+Run the task manually, then verify subsequent scheduled runs, Task Scheduler's
+result/history, Cacti's poller statistics and graph freshness. Recheck these
+under the task account after changing PHP, paths, credentials or ACLs.
+
+## References
+
+- [Cacti development (1.3) PHP dependency checks][cacti-extensions]
+- [Cacti development (1.3) installation permission checks][cacti-permissions]
+- [PHP Windows installation][php-windows], [IIS][php-iis] and
+ [Apache][php-apache]
+- [Microsoft FastCGI configuration][iis-fastcgi] and
+ [application-pool identities][iis-identity]
+- [MySQL 8 removed features][mysql-removed]
+- [Microsoft Task Scheduler][task-scheduler]
+
+[pcntl]:
+[manifest]:
+[php-windows]:
+[php-iis]:
+[php-apache]:
+[iis-fastcgi]:
+[iis-identity]:
+[mysql-removed]:
+[task-scheduler]:
+[cacti-extensions]:
+[cacti-permissions]:
+
+[supported-os]: Requirements.md#supported-operating-systems
---
+
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Manual-Index.md b/Manual-Index.md
index 615e07d7..eb806e6b 100644
--- a/Manual-Index.md
+++ b/Manual-Index.md
@@ -10,12 +10,15 @@ show an earlier release or a different theme.
## Install or Upgrade Cacti
Choose the guide for your operating system and installation method.
+Earlier [LAMP][previous-lamp] and [LEMP][previous-lemp] guide URLs point to
+the maintained Enterprise Linux instructions.
- [Requirements](Requirements.md)
- [General Installing Instructions](General-Installing-Instructions.md)
- [Enterprise Linux with Apache (LAMP)](Install-Under-Enterprise-Linux-LAMP.md)
-- [Enterprise Linux with Nginx (LEMP)](Install-Under-Enterprise-Linux-LEMP.md)
+- [Rocky Linux 9 and 10 with Nginx (LEMP)][rocky-lemp]
- [Ubuntu/Debian with Apache (LAMP)](Installing-Under-Ubuntu-Debian.md)
+- [Ubuntu Server 26.04 LTS and 26.10 with Nginx (LEMP)][ubuntu-lemp]
- [Installing Under Windows](Installing-Under-Windows.md)
- [Upgrading Cacti Under UNIX Compatible Operating Systems](Upgrading-Cacti.md)
- [Upgrading Cacti Under Windows](Upgrading-Cacti-Under-Windows.md)
@@ -214,3 +217,8 @@ Find project credits, licensing, support, and additional resources.
---
Copyright (c) 2004-2026 The Cacti Group
+
+[rocky-lemp]: Install-Under-Enterprise-Linux-LEMP.md
+[ubuntu-lemp]: Installing-Under-Ubuntu-LEMP.md
+[previous-lamp]: Install-Under-CentOS_LAMP.md
+[previous-lemp]: Install-Under-CentOS_LEMP.md
diff --git a/Plugin-Syslog.md b/Plugin-Syslog.md
index 627fcd3f..6ccc319e 100644
--- a/Plugin-Syslog.md
+++ b/Plugin-Syslog.md
@@ -89,7 +89,7 @@ $template cacti_syslog,"INSERT INTO syslog_incoming(facility_id, priority_id,
*.* >localhost,my_database,my_user,my_password;cacti_syslog
-for centos/rhel systems you will all need to install the rsyslog-mysql package
+for RHEL, Rocky Linux, or AlmaLinux systems you will all need to install the rsyslog-mysql package
```shell
yum install rsyslog-mysql
diff --git a/Requirements.md b/Requirements.md
index cda67059..88734663 100644
--- a/Requirements.md
+++ b/Requirements.md
@@ -1,299 +1,170 @@
# Requirements
-## Hardware Sizing
-
-The table below covers common deployment sizes. These are starting points;
-actual requirements depend on polling interval, number of data sources per
-device, use of Spine vs cmd.php, and whether remote pollers are used.
-
-| Deployment size | Devices | Data sources | CPU cores | RAM | Disk |
-|---|---|---|---|---|---|
-| Small | < 500 | < 50,000 | 2 | 4 GB | 50 GB SSD |
-| Medium | 500–2,000 | 50,000–500,000 | 4–8 | 16 GB | 200 GB SSD |
-| Large | 2,000–10,000 | 500,000–2,000,000 | 8–16 | 32–64 GB | 1 TB NVMe |
-| Very large | > 10,000 | > 2,000,000 | 16+ | 64+ GB | 2+ TB NVMe |
-
-**Notes:**
-
-- Use SSD or NVMe for the RRD file directory. RRDtool performs many small random
- writes; spinning disk causes polling backlogs on medium and larger installs.
-- The MySQL/MariaDB data directory benefits from SSD as well.
- `innodb_doublewrite` protects against torn page writes during a crash;
- disabling it reduces crash safety on any storage type, including SSD/NVMe.
- Setting `innodb_doublewrite = OFF` is an advanced optimization; only
- consider it when you accept the durability trade-off (e.g. strong
- backup/replication strategy and tolerance for potential data loss on an
- unclean shutdown).
-- Spine is CPU-bound. Each Spine process spawns threads up to your configured
- maximum; allocate 1–2 Spine processes per CPU core for best throughput.
-- Very large deployments (> 10,000 devices) require remote pollers deployed
- close to the devices they poll rather than scaling a single main poller
- vertically.
+This manual follows the unreleased Cacti 1.3 `develop` branch. Use the
+[1.2.x manual][manual-12] for released Cacti 1.2 installations. Verify the
+requirements of the exact revision or release you deploy; development
+requirements can change.
+
+## Supported operating systems
+
+Platform guidance checked on 26 October 2026. Use the current security-updated
+point release in a vendor-supported stable branch. The examples below target
+these maintained operating systems; vendor OS support does not certify every
+Cacti, PHP, database, or third-party binary combination.
+
+| Operating system | Versions used for installation guidance | Lifecycle source |
+| --- | --- | --- |
+| RHEL | Current supported minor release of 9 or 10 | [Red Hat lifecycle][os-rhel] |
+| Rocky Linux | Current minor release of 9 or 10 | [Rocky releases][os-rocky] |
+| AlmaLinux | Current minor release of 9 or 10 | [AlmaLinux releases][os-alma] |
+| Ubuntu Server | 24.04 LTS, 26.04 LTS, or 26.10 | [Ubuntu lifecycle][os-ubuntu] |
+| Debian | 13 stable; 12 only with applicable Debian LTS coverage | [Debian lifecycle][os-debian] |
+| FreeBSD | 14.5-RELEASE or 15.1-RELEASE, with current patches | [FreeBSD security support][os-freebsd] |
+| Windows Server | 2022 or 2025, with current updates | [Server 2022][os-win22], [Server 2025][os-win25] |
+
+Check the linked lifecycle information before deployment. LTS coverage can
+exclude architectures or packages. Use a maintained PHP and database version
+that also meets this Cacti branch's requirements. A supported OS with an
+incompatible default PHP version is not ready for installation. Do not use a
+beta OS or an expired point release for these procedures.
## Software Requirements
-Cacti requires that the following software is installed on your system.
-
-> **Note**: As of Cacti 1.2.31, PHP 8.1 is required. When installing from
-> source or the develop branch, PHP Composer is required to install vendor
-> dependencies. Pre-packaged releases include the required vendor files, so
-> Composer is not needed for standard installs.
-
-- Web server that supports PHP, for example Apache, nginx, or IIS
-
-- Build environment when using Spine (gcc, automake, autoconf, libtool,
- help2man)
-
-- RRDtool 1.5 or greater (Cacti 1.3.x offers version settings for RRDtool 1.5
- through 1.11)
-
-- PHP 8.1 or greater
- - Required modules:
- - ctype, date, dom, filter, gettext, gd, gmp, intl
- - hash, json, ldap, mbstring, mysqlnd, openssl, pcre
- - PDO, pdo_mysql, Phar, session, simplexml, sockets, spl
- - sqlite3, standard, xml, zlib
- - com_dotnet (Windows only)
- - pcntl, posix (Linux only)
-
- - Optional modules:
- - snmp - The PHP SNMP extension is optional and fully supported. Cacti also
- uses the Net-SNMP binaries for SNMPv3 queries, IPv6 targets, bulkwalk,
- and hex-string output. You do not need to remove php-snmp; Cacti selects
- the right method automatically based on query type and device configuration.
-
-- Problematic software and configuration
- - SELinux, AppArmor, and ModSecurity can interfere with ICMP ping, socket
- connections, and RRDtool file writes. Configure appropriate policies or
- exceptions rather than disabling these protections entirely. Disabling
- SELinux or AppArmor system-wide is a security regression and is not
- recommended for production systems.
-
-- MySQL 8.0 or MariaDB 10.6.28 or greater
- - Timezone support must be enabled
-
- - The following are my.cnf recommendations:
-
- - **version >= 8.0 (MySQL) / 10.6.28 (MariaDB)**
-
- MySQL 8.0+ and MariaDB 10.6.28+ are the minimum supported versions.
- MariaDB 11.8.8 or greater is recommended for new installs. Run the
- latest maintenance release for your chosen branch; older patch releases
- have known networking issues that cause intermittent Spine failures.
-
- - **innodb = ON**
-
- Enable InnoDB in any MySQL/MariaDB version greater than 5.1.
-
- - **collation_server = utf8mb4_unicode_ci**
-
- When using Cacti with languages other than English, it is important to
- use the utf8mb4_unicode_ci collation type as some characters take more
- than a single byte. If you are first just now installing Cacti, stop,
- make the changes and start over again. If your Cacti has been running
- and is in production, see the internet for instructions on converting
- your databases and tables if you plan on supporting other languages.
-
- - **character_set_client = utf8mb4**
- - **character_set_server = utf8mb4**
-
- When using Cacti with languages other than English, it is important to
- use the utf8mb4 character set as some characters take more than a single
- byte. If you are first just now installing Cacti, stop, make the changes
- and start over again. If your Cacti has been running and is in
- production, see the internet for instructions on converting your
- databases and tables if you plan on supporting other languages.
-
- - **max_connections >= 100**
-
- Depending on the number of logins and use of the Spine data collector,
- MySQL/MariaDB will need many connections. The calculation for spine is:
-
- ```text
- total_connections = total_processes * (total_threads + script_servers + 1)
- ```
-
- then you must leave headroom for user connections, which will change
- depending on the number of concurrent login accounts.
-
- - **max_heap_table_size >= 5% of system RAM**
-
- If using the Cacti Performance Booster and choosing a memory storage
- engine, you have to be careful to flush your Performance Booster buffer
- before the system runs out of memory table space. This is done two
- ways, first reducing the size of your output column to just the right
- size. This column is in the tables poller_output, and
- poller_output_boost.
-
- The second thing you can do is allocate more memory to memory tables
- with a recommended value of 10% of system memory, but if you are using
- SSD disk drives, or have a smaller system, you may ignore this
- recommendation or choose a different storage engine. You may see the
- expected consumption of the Performance Booster tables under Console ->
- System Utilities -> View Boost Status.
-
- > **Note**: If you are using a recent version of MariaDB or MySQL, using
- > memory tables is no longer a requirement. You may choose to continue
- > to use memory tables to spare your NVMe or SSD drives excessive use
- > wear. However, outside of that, it is no longer a requirement.
- > As such, the value of the **max_heap_table_size** is not as important
- > as in previous releases. If you are using Galera
- > replication with Cacti, all your tables must be in InnoDB format, and
- > the only benefit of MariaDB or MySQL memory tables becomes temporary
- > table space, which may not be dependent on **max_heap_table_size**.
-
- - **table_open_cache >= 200**
-
- Keeping the table cache larger means fewer file open/close operations
- when using innodb_file_per_table. (Note: `table_cache` was renamed to
- `table_open_cache` in MySQL 5.1.3; use `table_open_cache` on all
- current MySQL and MariaDB releases.)
+| Component | Development requirement or recommendation |
+| --- | --- |
+| Web server | PHP-capable Apache, nginx, or IIS FastCGI |
+| PHP | PHP 8.3 or later in the PHP 8 series (`^8.3` in Composer) |
+| Database | MySQL 8.4+ or MariaDB 10.11+ recommended by the installer |
+| RRDtool | Version 1.5 or later |
+| SNMP | Net-SNMP command-line tools for operations using external binaries |
+| Spine | Optional; use a version compatible with Cacti and its runtime libraries |
- - **max_allowed_packet >= 16777216**
+The PHP requirement comes from the [dependency manifest][manifest] and
+[runtime minimum][constants]. The database values are the branch's
+[installer recommendations][checks], rather than a certification of every
+vendor release. Check the actual server and extensions before installation.
- With Remote polling capabilities, large amounts of data will be synced
- from the main server to the remote pollers. Therefore, keep this value
- at or above 16M.
+### PHP extensions
- - **tmp_table_size >= 64M**
+Cacti checks the CLI and web PHP environments separately. Install the
+extensions required by the selected revision's Composer manifest and lock file,
+and satisfy the installer checks. The combined requirements include:
- When executing subqueries, a larger temporary table size keeps those
- temporary tables in memory.
+- `ctype`, `curl`, `date`, `dom`, `filter`, `gd`, `gmp`, `hash`, `intl`,
+ `json`, `ldap`, `mbstring`, `mysqlnd`, `openssl`, `pcre`, `PDO`,
+ `pdo_mysql`, `Phar`, `session`, `simplexml`, `sockets`, `spl`, `sqlite3`,
+ `standard`, `xml`, and `zlib`.
+- `posix` and CLI `pcntl` on Unix.
+- `com_dotnet` for the Windows installer checks.
- - **join_buffer_size >= 64M**
+Some modules are built into PHP. Check `php -v`, `php --ini`, and `php -m` for
+the CLI, then check web PHP through the installer. Enabling an extension in one
+PHP configuration does not enable it in the other.
- When performing joins, if they are below this size, they will be kept in
- memory and never written to a temporary file.
+The PHP SNMP extension is optional. External Net-SNMP tools are still needed
+for collection paths such as some SNMPv3 and bulk requests. Configure their
+paths and verify execution under the actual web and collector accounts.
- - **innodb_file_per_table = ON**
+### Composer and source deployments
- When using InnoDB storage it is important to keep your table spaces
- separate. This makes managing the tables simpler for long-time users of
- MySQL/MariaDB. If you are running with this currently off, you can
- migrate to the per file storage by enabling the feature, and then
- running an alter statement on all InnoDB tables.
+A source checkout or GitHub source archive needs its locked PHP dependencies.
+Run these commands from the Cacti source root as the deployment owner:
- It is already ON by default on every supported version, and MariaDB
- deprecated the variable in 11.0, so only set it where an older my.cnf
- turned it off.
-
- - **innodb_data_file_path = ibdata1:12M:autoextend:autoshrink**
- (MariaDB 11.2.0+)
-
- Long running installs that accumulated blocking queries can end up with a
- very large ibdata1 file that never shrinks back down. The autoshrink
- attribute lets MariaDB truncate the system tablespace back toward its
- minimum size. It is off by default and is enabled by appending
- :autoshrink to innodb_data_file_path, not by a separate variable.
-
- From MariaDB 11.2.0 the shrink runs at server startup. MariaDB 11.2.3
- adds the option of shrinking during a slow shutdown instead, which needs
- innodb_fast_shutdown = 0 set before the server is stopped. MySQL has no
- equivalent.
-
- - **innodb_buffer_pool_size >= 25% of system RAM**
-
- InnoDB will hold as many tables and indexes in system memory as
- possible. Therefore, you should make the innodb_buffer_pool large
- enough to hold as many of the tables and indexes in memory as you can.
- Checking the size of the /var/lib/mysql/cacti directory will help in
- determining this value. We are recommending 25% of your system's total
- memory, but your requirements will vary depending on your system's size.
-
- - **innodb_doublewrite = OFF**
-
- Disables the InnoDB doublewrite buffer. This eliminates a 50% write
- overhead on SSD/NVMe storage, but removes protection against partial page
- writes on an unclean shutdown. Only set this on SSD or NVMe storage with
- battery-backed or capacitor-backed write cache, or when the database is
- on a volume with hardware-level write atomicity guarantees. Do not set on
- spinning disk or consumer SSDs without power-loss protection.
-
- - ~~**innodb_additional_mem_pool_size**~~ (removed in MySQL 5.7.4 /
- MariaDB 10.0)
-
- This setting no longer exists. MySQL/MariaDB manages metadata memory
- internally. Remove it from my.cnf if present; MySQL 8.0+ will error on
- startup.
-
- - **innodb_lock_wait_timeout >= 50**
-
- Rogue queries should not cause the database to go offline to others.
- Kill these queries before they kill your system.
-
- - **innodb_flush_log_at_trx_commit = 2**
-
- Setting this value to 2 means that you will flush all transactions every
- second rather than at commit. This allows MySQL/MariaDB to perform
- writing less often.
-
- - **innodb_flush_log_at_timeout >= 3**
-
- If your MySQL/MariaDB version supports it, you can control how often
- MySQL/MariaDB flushes transactions to disk. The default is 1 second,
- but in high I/O systems setting to a value greater than 1 can allow disk
- I/O to be more sequential.
-
- - **innodb_read_io_threads >= 32**
-
- With modern SSD type storage, having multiple read IO threads is
- advantageous for applications with high IO characteristics.
-
- - **innodb_write_io_threads >= 16**
-
- With modern SSD type storage, having multiple write IO threads is
- advantageous for applications with high IO characteristics.
-
- - **innodb_buffer_pool_instances >= 16** (MySQL only)
+```console
+composer install --no-dev
+composer check-platform-reqs --no-dev
+```
- MySQL will divide the innodb_buffer_pool into memory regions to improve
- performance, up to a maximum value of 64. When your innodb_buffer_pool is
- less than 1GB, you should use the pool size divided by 128MB. Continue to
- use this equation up to the max of 64.
+Use `composer install`, which reads `composer.lock`. Do not run `composer
+update` during installation or upgrade. A complete release bundle can already
+contain `include/vendor/autoload.php`; verify its generated platform checks and
+the release's instructions rather than assuming every archive contains vendor
+files.
- MariaDB 10.5 deprecated this variable and gave it no effect, and MariaDB
- 10.6 removed it. Leave it out of my.cnf on MariaDB 10.6 and later, which
- will not start on an unknown variable.
+The current manifest requires `ext-pcntl` and `ext-posix` unconditionally.
+Native Windows PHP cannot supply these modules. Source dependency installation
+is therefore blocked on native Windows, even though the installer has
+Windows-specific checks. A bundled artifact must also pass its runtime platform
+check. See [Installing Under Windows][windows] before choosing a build. Do not
+bypass platform checks to force installation.
- > **Note**: Some of these recommendations may not be applicable depending
- > on the version of MySQL/MariaDB you are running, and some should be
- > scaled where appropriate.
+## Hardware Sizing
- - Newer MySQL/MariaDB releases use [strict
- modes](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html), which can
- cause unexpected problems when importing dumps of Cacti databases from
- older systems, like **Can't create table `cacti`.`poller_output_boost`
- (errno: 140 "Wrong create options")**.
+Size from the polling interval, number of data sources, retention profiles,
+concurrent graph requests, collector settings, and measured storage latency.
+Device count alone is not a reliable sizing rule. Test representative polling
+and graphing load before increasing the deployment.
- You have several options:
+Use storage that can sustain RRD updates and database writes within the polling
+window. Measure CPU, memory, I/O latency, database connections, and poll
+completion time. Remote collectors can distribute collection work; they also
+require connectivity, synchronization, and operational monitoring. Spine
+process and thread counts should be tuned against those measurements.
- - disable appropriate strict mode - not recommended
+## Database configuration
- - change mysqldump file - remove **ROW_FORMAT=FIXED** from table
- definition
+Enable timezone support and grant the application account `SELECT` access to
+`mysql.time_zone_name`. The grant does not populate that table. Import the
+vendor's timezone data using the procedure for your operating system.
- - before mysqldump run query:
- **ALTER TABLE `poller_output_boost` ROW_FORMAT=DYNAMIC;**
+Use `utf8mb4` and the `utf8mb4_unicode_ci` collation consistently for the Cacti
+database. Changing server defaults does not convert existing tables; back up
+and plan any conversion of an installed database separately.
-To implement the above MySQL recommendations, you can paste the entries below
-into my.cnf
+Start with the database vendor's defaults and review the installer's checks for
+the installed engine and version. Do not copy a fixed `my.cnf` block from
+another server. Size global buffers and per-connection buffers together with
+PHP and operating-system memory. Estimate Spine's connection demand as:
-```console
- innodb_flush_log_at_timeout = 4
- innodb_read_io_threads = 34
- innodb_write_io_threads = 17
- max_heap_table_size = 70M
- tmp_table_size = 70M
- join_buffer_size = 130M
- innodb_buffer_pool_size = 250M
- innodb_io_capacity = 5000
- innodb_io_capacity_max = 10000
+```text
+total_connections = total_processes * (total_threads + script_servers + 1)
```
-> **Note**: MySQL 8.4 raised the default for **innodb_io_capacity** from 200 to
-> 10000, while MariaDB still defaults to 200. On MySQL 8.4 and later the value
-> above lowers the setting rather than raising it, so check your server default
-> before pasting the block in.
+Allow additional connections for web requests, plugins, and maintenance.
+Inspect actual storage engines before applying memory-table sizing guidance.
+
+Keep InnoDB doublewrite protection enabled. Disabling it removes protection
+against incomplete page writes; an SSD alone does not establish atomic page
+writes. Review the durability consequences before changing commit flushing or
+other crash-recovery settings.
+
+Database variables differ by engine and release. Removed settings can prevent
+startup. For example, MySQL 8 no longer accepts `innodb_file_format`,
+`innodb_large_prefix`, or `innodb_additional_mem_pool_size`, and MariaDB 10.6
+removed `innodb_buffer_pool_instances`. Validate settings against the installed
+server's documentation and Cacti's version-aware checks before restarting. See
+the [MySQL reference][mysql] or [MariaDB reference][mariadb].
+
+## Accounts and platform controls
+
+Keep application code owned by the administrator or deployment account. Give
+web and collector identities the read, execute, and runtime-directory write
+access they need. Grant temporary installation or import access only to the
+required paths, and remove it afterward. Keep database credentials, CSRF
+secrets, private caches, RRD files, and backups inaccessible over HTTP.
+
+Configure SELinux, AppArmor, container permissions, or IIS request filtering
+for the required operations. Do not remove confinement globally to make
+installation checks pass. Follow the platform installation guide and
+[Hardening a Cacti Installation](Hardening-Cacti-Installation.md).
+
+[manual-12]:
+[manifest]:
+[constants]:
+[checks]:
+[windows]: Installing-Under-Windows.md#development-packaging-prerequisite
+[mysql]:
+[mariadb]:
+
+[os-rhel]:
+[os-rocky]:
+[os-alma]:
+[os-ubuntu]:
+[os-debian]:
+[os-freebsd]:
+[os-win22]:
+[os-win25]:
---
+
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Spine.md b/Spine.md
index 08bf4aa0..244f9dd2 100644
--- a/Spine.md
+++ b/Spine.md
@@ -1,5 +1,8 @@
# Spine
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
+
Spine is Cacti's C-based, multithreaded data collector. It replaces `cmd.php`
as the collection engine; `poller.php` remains the scheduling entry point.
Actual throughput depends on device latency, scripts, concurrency, database
@@ -180,6 +183,8 @@ engine, not successful collection of every item. Check errors and actual RRD
updates as well. See [Data Source Debugging](Data-Debug.md) and
[The Cacti Log](Cacti-Log.md).
+[supported-os]: Requirements.md#supported-operating-systems
+
---
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Upgrading-Cacti-Under-FreeBSD.md b/Upgrading-Cacti-Under-FreeBSD.md
index 7d1175b2..732e4e49 100644
--- a/Upgrading-Cacti-Under-FreeBSD.md
+++ b/Upgrading-Cacti-Under-FreeBSD.md
@@ -1,57 +1,143 @@
# Upgrading Cacti Under FreeBSD
-1. Back up the old Cacti database.
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
- ```sh
- shell> mysqldump --single-transaction --add-drop-table cacti > mysql.cacti
- ```
+These instructions cover the FreeBSD upgrade procedure. This manual describes
+Cacti development (1.3), while the FreeBSD port currently supplies Cacti 1.2.31.
+Use the [1.2.x manual][manual-12] for release-specific requirements when
+upgrading the packaged release. Determine whether Cacti is maintained by
+`pkg`, by ports or from a source archive. Keep that installation
+method for the upgrade; do not overlay an archive onto package-managed files.
+Review the target Cacti [release notes](Version-Specific-Release-Notes.md),
+[requirements](Requirements.md) and package or port notes before proceeding. Do
+not make an unrelated operating-system, PHP or database major-version upgrade
+part of this procedure without a separate compatibility plan.
+
+## Pause collection and back up
- > **Note**: You will probably need to specify `-u` and `-p` for the MySQL
- > username and password. This user must have permission to read from Cacti's
- > database or you will end up with an empty backup.
- >
- > `--single-transaction` provides a consistent InnoDB snapshot without
- > locking tables, which is the correct approach for Cacti's InnoDB schema.
+1. Clear **Data Collection Enabled** under `Console > Configuration > Settings
+ > Poller`. Disable the Cacti-specific cron entry or stop its configured
+ poller service on every collector. Record what you change; do not stop the
+ system-wide cron service merely to pause Cacti. Wait for pollers, Spine,
+ script servers and other background writers to finish. Restrict web access
+ to the upgrade administrator and pause plugin jobs that write to Cacti.
+ Flush pending RRD-cache writes and confirm that the database and RRD files
+ remain unchanged before taking the backup.
-2. Back up the old Cacti directory.
+2. Use the dump client appropriate to the installed MySQL or MariaDB server.
+ The following example requires an existing, protected backup directory and a
+ database account with the server's required backup privileges. Replace the
+ account, database name and filename for your installation. Use its actual
+ database host, port and TLS options.
```sh
- shell> cd /usr/local/share
- shell> tar -zcf cacti_backup_YYYYMMDD.tgz cacti
+ mysqldump --user=YOUR_BACKUP_USER --password \
+ --lock-tables --quick --routines --events --triggers \
+ --databases cacti --result-file=/protected/backup/cacti-YYYYMMDD.sql
```
-3. Install the new version from compiled packages or FreeBSD ports.
+ The password is prompted. With all Cacti writers paused, this [dump
+ method][dump] uses table locks for the Cacti database, including
+ nontransactional tables. A transaction-only dump does not cover those
+ tables. Verify the command succeeded and test restoring the dump separately;
+ a nonempty file alone is not proof of a complete backup. Use a new filename
+ rather than overwriting a known good backup.
- ```sh
- shell> pkg delete cacti
- shell> pkg install cacti
- ```
+3. Back up the Cacti application files, RRDs and local configuration together
+ with the database dump. Preserve ownership, permissions and hidden files.
+ Include `include/config.php`, custom scripts, query resources, plugins,
+ secret files, including any alternate `path_csrf_secret`, and configured
+ paths outside the application tree. Record symbolic links and back up their
+ targets separately. Also record the Spine configuration, cron/service
+ settings, web-server settings, database grants, certificates/keys and
+ installed versions. Package layouts may keep configuration and data outside
+ `/usr/local/share/cacti`; inspect the installed paths rather than backing up
+ that directory alone. Include `/var/db/cacti/rra` and `/var/log/cacti`
+ when those are the configured package paths, and protect the backup directory
+ from other users because the configuration contains credentials.
- or
+## Upgrade using the existing installation method
- ```sh
- shell> pkg install git
- shell> git clone https://git.FreeBSD.org/ports.git /usr/ports
- shell> git -C /usr/ports pull
- shell> cd /usr/ports/net-mgmt/cacti
- shell> make deinstall clean install
- ```
+For a binary package installation, review the proposed package transaction
+before applying it. The [FreeBSD Handbook][packages] describes package
+upgrades. Run the following with appropriate administrator privileges:
-4. If you are using the optional **Performance → Image Caching** feature,
- recreate the cache folder and set the correct permissions.
+Discover the installed flavor first:
- ```sh
- shell> cd /usr/local/share/cacti
- shell> mkdir cache
- shell> chown -R cacti cache
- ```
+```sh
+pkg info -o -x '^cacti'
+pkg update
+```
+
+For an installed `cacti-php84` package, for example:
+
+```sh
+pkg upgrade -n cacti-php84
+pkg upgrade cacti-php84
+pkg info -D cacti-php84
+```
-5. Browse to `http://your-server/cacti/` and follow the on-screen instructions
- to update the database schema to the new version.
+Replace `cacti-php84` with the installed package name. Keep the PHP flavor
+unless a separate migration is intended. If Spine is installed, review its
+upgrade and verify its version remains compatible with Cacti. See the
+[FreeBSD installation section][freebsd-install] for package paths and the
+`net-mgmt/cacti-spine` port.
-> **Note**: Starting with Cacti 1.0, all Data Collectors upgrade themselves
-> automatically within two polling cycles. If they do not, upgrade them one
-> at a time.
+Check the proposed version and dependency changes before accepting the actual
+upgrade. A package repository normally supplies a release rather than
+development source. Stop if that is not your approved target and select an
+appropriate repository or installation method. Do not delete Cacti first or
+assume that upgrading one package cannot affect its dependencies.
+
+For a ports-managed installation, follow the handbook's [ports upgrade
+procedure][ports] and applicable `/usr/ports/UPDATING` entries. Use the
+existing ports management method; do not switch between ports and binary
+packages without reviewing their options and dependencies. A source
+installation instead follows [Upgrading Cacti](Upgrading-Cacti.md).
+
+Preserve the working configuration and merge required changes from the new
+configuration example. Keep existing database credentials, collector IDs, paths
+and secrets. Review package-generated configuration changes and restore local
+resources only after checking compatibility. Recreate cache or data directories
+only where the installed configuration requires them, with access for the
+actual service account; do not assume a universal account or apply recursive
+ownership changes to the whole installation.
+
+## Check development dependencies
+
+Development source requires PHP 8.3 or later in the PHP 8 series, with the
+extensions declared by the selected revision. Install locked dependencies in
+the staging directory with `composer install --no-dev`, then run `composer
+check-platform-reqs --no-dev`. Preserve this complete dependency tree when
+deploying the staged application. Do not run `composer update` against a live
+installation. A complete release bundle can already include dependencies;
+verify its platform checks instead of assuming that every archive is complete.
+
+## Complete the application upgrade
+
+Open the existing Cacti URL as an administrator and complete its database
+upgrade. Review the installer and logs before resuming collection. Upgrade
+remote collectors' local files and configuration through their installation
+method, complete the applicable upgrade/synchronization, and verify their
+versions, connectivity and logs. Do not rely on a fixed number of poll cycles
+for completion. Check the matching Spine version on collectors using Spine.
+
+After successful checks, re-enable **Data Collection Enabled** and restore the
+recorded Cacti cron entry or service. Verify a complete poll cycle, recent RRD
+samples and representative graphs on every collector. If recovery is needed,
+stop all writers again and restore the matching files, database, RRDs and
+configuration as one set; restoring old application files alone does not undo a
+database upgrade.
+
+[dump]:
+[packages]:
+[ports]:
+
+[supported-os]: Requirements.md#supported-operating-systems
+[manual-12]:
+[freebsd-install]: General-Installing-Instructions.md#freebsd
---
+
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Upgrading-Cacti-Under-Windows.md b/Upgrading-Cacti-Under-Windows.md
index 6a2b1633..f3663846 100644
--- a/Upgrading-Cacti-Under-Windows.md
+++ b/Upgrading-Cacti-Under-Windows.md
@@ -1,77 +1,121 @@
-# Upgrading Cacti Under Windows
-
-Download the [latest stable version](https://www.cacti.net/download_cacti.php)
-of Cacti, referred to as `cacti-xxx.zip` in this document.
-
-1. Stop the poller:
- - Cacti Console → Configuration → Settings → Poller
- - Uncheck **Data Collection Enabled** and save.
-
-2. Run Command Prompt as Administrator and back up the database:
-
- ```sh
- shell> cd Documents
- shell> mysqldump.exe -uroot -p --single-transaction --add-drop-table cacti > cacti-version-YYYYMMDD.sql
- ```
-
- > **Note**: `mysqldump.exe` is located under your MySQL/MariaDB installation
- > bin directory, e.g. `%PROGRAMFILES%\MySQL\MySQL Server X.Y\bin\`.
-
-3. Back up the old Cacti directory:
-
- ```sh
- shell> cd \inetpub\wwwroot
- shell> robocopy cacti cacti-version-YYYYMMDD /s /b /copyall
- ```
-
-4. Run **Windows Update**.
-
-5. Upgrade MySQL/MariaDB:
- - Open **MySQL Installer - Community** (or the MariaDB upgrade tool)
- - Update the catalog
- - Upgrade the server
-
-6. Upgrade PHP:
- - Back up the `C:\php\` folder
- - Download a [supported PHP version](https://www.php.net/supported-versions.php)
- from [PHP for Windows](https://windows.php.net/download/) using the
- appropriate build for IIS (Non-Thread Safe + FastCGI) or Apache
- - Overwrite `C:\php\` with the contents of the new zip file
-
-7. Install the new Cacti version:
- Extract the contents of the `cacti-xxx` folder from `cacti-xxx.zip` to
- `C:\inetpub\wwwroot\cacti\`, replacing existing files.
-
-8. Edit `include/config.php` and verify the database connection details:
-
- ```sh
- shell> notepad cacti/include/config.php
- ```
-
- ```php
- $database_type = "mysql";
- $database_default = "cacti";
- $database_hostname = "localhost";
- $database_username = "cactiuser";
- $database_password = "cacti";
+# Upgrading Cacti under Windows
+
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
+
+These instructions cover upgrading a source/archive installation to Cacti
+1.3-dev. For a managed Windows installation, also follow its package or
+installer upgrade procedure; do not overwrite package-managed files with an
+unrelated archive. Review the [release
+notes](Version-Specific-Release-Notes.md) and [requirements](Requirements.md)
+for the target Cacti version first. An upgrade of Cacti does not automatically
+require upgrading Windows, PHP or the database.
+
+The current source manifest requires `ext-pcntl` and `ext-posix`, which native
+Windows PHP cannot provide. Read the [Windows installation
+prerequisite](Installing-Under-Windows.md#development-packaging-prerequisite)
+before scheduling downtime. Stop if the selected artifact rejects Windows.
+
+## Check development dependencies
+
+Development source requires PHP 8.3 or later in the PHP 8 series, with the
+extensions declared by the selected revision. Install locked dependencies in
+the staging directory with `composer install --no-dev`, then run `composer
+check-platform-reqs --no-dev`. Preserve this complete dependency tree when
+deploying the staged application. Do not run `composer update` against a live
+installation. A complete release bundle can already include dependencies;
+verify its platform checks instead of assuming that every archive is complete.
+
+## Pause collection and take a recoverable backup
+
+1. In `Console > Configuration > Settings > Poller`, clear **Data Collection
+ Enabled** and save. Disable the actual Windows Scheduled Task that launches
+ `poller.php`, or stop the service that manages your poller. Record the task
+ or service settings so you can restore them. Use [Task Scheduler][tasks] to
+ disable future starts; this alone does not finish an already running poll.
+
+2. Wait for running pollers, Spine processes, script servers and background
+ writers to finish. Include remote collectors and plugin jobs. Restrict web
+ access to the upgrade administrator so configuration changes cannot race the
+ backup. Flush pending RRD-cache writes before copying RRD files and confirm
+ that writers have stopped. Do not start a manual poll during this
+ maintenance window.
+
+3. Create a protected backup directory outside the web root. From Command
+ Prompt, use the dump utility matching your database server. Replace the
+ executable path, account, database name and output path in this example. Use
+ the actual database host, port and TLS options for your installation. The
+ account needs the backup privileges required by the installed server;
+ `--password` prompts rather than putting a password in the command.
+
+ ```bat
+ "C:\path\to\mysqldump.exe" --user=YOUR_BACKUP_USER --password ^
+ --lock-tables --quick --routines --events --triggers ^
+ --databases cacti --result-file="D:\CactiBackup\cacti-YYYYMMDD.sql"
```
-9. Browse to `http://localhost/cacti/` and follow the on-screen instructions
- to update the database schema to the new version.
+ With all Cacti writers paused, this [dump example][dump] uses table locks to
+ cover transactional and nontransactional tables in the Cacti database. A
+ transaction-only dump does not protect nontransactional tables. Use a new
+ output filename and verify successful completion: a failed dump may leave a
+ partial file. Do not proceed until the backup can be restored in a separate
+ test environment.
- If any session variables need adjustment, set them from the MySQL/MariaDB
- command-line client:
+4. Back up the existing Cacti tree, including hidden files, using a separate
+ destination outside the web root. For example, [Robocopy][robocopy] can
+ preserve file permissions as well as contents when run with the required
+ privileges:
- ```sql
- SET GLOBAL max_allowed_packet = 16777216;
- SET GLOBAL tmp_table_size = 67108864;
- SET GLOBAL join_buffer_size = 67108864;
- SET GLOBAL innodb_flush_log_at_timeout = 3;
+ ```bat
+ robocopy "C:\inetpub\wwwroot\cacti" "D:\CactiBackup\cacti-YYYYMMDD" /E /COPYALL /SL /XJ /R:2 /W:2
```
-10. Re-enable the poller:
- - Cacti Console → Configuration → Settings → Poller
- - Check **Data Collection Enabled** and save.
+ Inspect its report; exit codes of 8 or greater indicate copy failures.
+ Confirm that the backup includes `include/config.php`, RRDs, custom scripts,
+ query resources, plugins and secret files, including any alternate
+ `path_csrf_secret`. Also save configured paths outside this tree, the Spine
+ configuration, scheduler settings, web-server configuration, database grants
+ and required certificates/keys. Record symbolic links and junctions and back
+ up their external targets separately; the example copies symbolic links and
+ excludes junctions. Preserve permissions and record the installed versions.
+ Keep this file backup and database dump together as one recovery set.
+
+## Install and verify the upgrade
+
+1. Extract the target [Cacti release][download] into a staging directory. Keep
+ the existing tree and verified backup available. Deploy the release files
+ using your existing installation layout, preserving the working
+ `include/config.php` and local resources. Compare the new
+ `include/config.php.dist` for changes; do not replace existing credentials,
+ collector IDs, paths or secrets with example defaults. Check plugin and
+ custom-script compatibility before restoring or enabling them.
+
+2. Verify file permissions for the web server and poller accounts. Open the
+ existing Cacti URL as an administrator and complete the database upgrade.
+ Review installer checks and logs. Use version-appropriate database settings
+ from [Requirements](Requirements.md), rather than applying fixed global SQL
+ tuning commands.
+
+3. For remote collectors, keep their schedulers paused while updating their
+ local application files and configuration and completing the applicable
+ upgrade and synchronization. Verify each collector's reported version,
+ connectivity and logs; completion is not guaranteed after two poll cycles.
+ Check the matching Spine version where it is used.
+
+4. Re-enable **Data Collection Enabled** and restore the recorded scheduler or
+ service only after the upgrade succeeds. Check a complete poll cycle,
+ collector status, new RRD samples and representative graphs. If recovery is
+ necessary, stop writers again and restore the matching application files,
+ database, RRDs and configuration together; copying old PHP files over an
+ upgraded database is not a rollback.
+
+[tasks]:
+[dump]:
+[robocopy]:
+[download]:
+
+[supported-os]: Requirements.md#supported-operating-systems
---
+
Copyright (c) 2004-2026 The Cacti Group
diff --git a/Upgrading-Cacti.md b/Upgrading-Cacti.md
index 2846c568..f7af400f 100644
--- a/Upgrading-Cacti.md
+++ b/Upgrading-Cacti.md
@@ -1,92 +1,165 @@
# Upgrading Cacti Under UNIX Compatible Operating Systems
-To upgrade Cacti under UNIX-style operating systems is very straightforward. To upgrade Cacti on Windows, you should use the instructions in the link below:
-
-[Upgrading in Windows](Upgrading-Cacti-Under-Windows.md)
-
-Before you begin, ensure that both your Apache/NGINX and your Crontab or systemd-based pollers run as the same account. In most Linux operating systems, this will be the apache account. Under SLES, it will be www-run. For this guide, we will use the apache account, but please adjust accordingly.
-
-1. Disable Polling:
-
- Go to Console >> Settings >> Poller >> Data Collection Enabled and switch it off.
-
-2. Backup the Cacti Configuration File:
-
- Backup the config.php file located in /include/.
- ```shell
- shell> cp /include/config.php
- ```
-
-3. Backup the Old Cacti Database:
-
- Create a backup of the current Cacti database.
- ```shell
- shell> mysqldump -l --add-drop-table --lock-tables=false cacti > mysql.cacti
- ```
- On newer versions of MariaDB
-
- ```shell
- shell> mariadb-dump -l --add-drop-table --lock-tables=false cacti > mysql.cacti
-
- ```
-
- You will probably have to specify the -u and -p flags for the MySQL username and password. This user must have permission to read from Cacti's database or you will end up with an empty backup.
-
-4. Backup the Old Cacti Directory:
-
- Backup the old Cacti directory with the exception of the RRD files, which should not need backup.
- ```shell
- shell> tar --exclude=*.rrd -zcf cacti_backup_YYYYMMDD.tgz cacti
- ```
-5. Extract the Distribution Tarball:
- ```shell
- shell> tar -xzvf cacti-version.tar.gz
- ```
-6. Copy the Distribution Tarball Over the Existing Installation:
- ```shell
- shell> /bin/cp -rpf cacti-version cacti
- ```
-7. Set Appropriate Permissions:
-
- Set the appropriate permissions on Cacti's directories for graph/log generation. Execute these commands from inside Cacti's directory to change the permissions.
-
- On RHEL/Rocky Linux/AlmaLinux (Apache runs as `apache`):
- ```shell
- shell> chown -R apache:apache rra/ log/
- ```
-
- On Ubuntu/Debian (Apache runs as `www-data`):
- ```shell
- shell> chown -R www-data:www-data rra/ log/
- ```
-
-8. Recreate the Cache Folder (Optional):
-
- If you are using Performance > Image Caching or Realtime Graphing, recreate the cache folder and correct the permissions.
- ```shell
- shell> mkdir cache
- ```
-
- On RHEL/Rocky Linux/AlmaLinux:
- ```shell
- shell> chown -R apache:apache cache
- ```
-
- On Ubuntu/Debian:
- ```shell
- shell> chown -R www-data:www-data cache
- ```
-
-9. Point Your Browser:
-
- Point your web browser to http://your-server/cacti/ and follow the on-screen instructions to update your database to the new version.
-
-10. Re-enable Polling:
-
- Go to the console and re-enable the poller. It will take two polling cycles to update the remote pollers.
-
-11. If Remote Pollers Fail to Update:
-
- Try to rebuild the Resource Cache by going to Console >> Utilities and wait 2 polling cycles.
-
- If that fails, update the remote pollers that have failed to update.
+Use only the [supported operating systems][supported-os] and maintained
+dependencies compatible with this Cacti branch.
+
+This procedure covers a source installation upgrading to Cacti development
+(1.3). For a
+package-managed installation, use the package maintainer's upgrade procedure
+and configuration-file handling. See the separate guides for
+[Windows](Upgrading-Cacti-Under-Windows.md) and
+[FreeBSD](Upgrading-Cacti-Under-FreeBSD.md).
+
+Review the [release notes][release] and [requirements](Requirements.md) first.
+Schedule time to back up and restore the installation. Test the upgrade on an
+isolated copy of the database and files before changing production. Keep
+dependency upgrades separate unless a prerequisite requires them.
+
+## Stop writers before backing up
+
+Turn off **Data Collection Enabled** under the poller settings. Also suspend
+the actual scheduler on each affected collector: disable only the Cacti cron
+entry, or stop its installed `cactid` service. Preserve the scheduler settings
+so they can be restored later. Do not disable all system cron jobs.
+
+Wait for existing poller, Spine, script-server, Boost and other background jobs
+to finish. Prevent web requests and plugin jobs from changing the installation
+during the backup and upgrade. The application polling switch alone does not
+stop every running process or administrative writer.
+
+If collectors use `rrdcached`, drain its pending writes using the procedure for
+that deployment before taking the RRD snapshot. Keep writers stopped until the
+database and file backups are both complete. Coordinate this on remote
+collectors as well as the main server.
+
+## Back up the database and complete installation
+
+Record the installed Cacti, Spine, PHP and database versions, installation
+paths, service accounts, scheduler entries and remote-collector configuration.
+Store backups outside the web root with access restricted to administrators.
+
+Back up the Cacti database with a client compatible with the database server.
+For example, with the application stopped and a backup account with the
+required privileges:
+
+```sh
+umask 077
+BACKUP_DIR=/srv/backups/cacti-before-1.3-dev
+mkdir "$BACKUP_DIR"
+mysqldump --user=backup_user --password --lock-tables --quick \
+ --routines --events --triggers cacti \
+ > "$BACKUP_DIR/cacti.sql"
+```
+
+Adjust the database name, account and paths before running these examples. Use
+`mariadb-dump` instead of `mysqldump` where appropriate. Enter the password at
+the prompt. Stop if a command fails; an output file alone does not prove a
+successful dump. The account needs the privileges required by the installed
+dump client, including table locks for the example above.
+
+`--single-transaction` provides a consistent snapshot for transactional
+tables; it does not make nontransactional tables consistent. Inspect the
+actual storage engines and choose the backup method accordingly. Keep all
+application writers stopped for the corresponding file snapshot. See the
+[database backup documentation][dump] for the option and privilege details.
+
+Back up the complete installation, including the RRD files. For an example
+installation at `/var/www/html/cacti`:
+
+```sh
+tar -czpf "$BACKUP_DIR/cacti-files.tar.gz" -C /var/www/html cacti
+tar -tzf "$BACKUP_DIR/cacti-files.tar.gz"
+```
+
+Preserve `include/config.php`, plugins, custom scripts, query resources and
+other local configuration. Include CSRF secret material, including an alternate
+`$path_csrf_secret` from the configuration. Back up separately any RRD,
+configuration or resource paths outside the installation tree. A tar archive
+normally preserves a symlink rather than including its external target. Retain
+the permissions and ownership needed for restoration.
+
+Save the database user/grant definitions and any connection certificates needed
+to recreate access. These are not included in a dump of the Cacti database
+alone. Include site or plugin SQL routines and events, as in the example, and
+account for their additional backup privileges.
+
+Back up remote-collector databases and local files where they hold state.
+Verify dump completion and archive contents, then rehearse restoration on an
+isolated system. Excluding `*.rrd` would leave monitoring history outside the
+recovery set.
+
+## Check development dependencies
+
+Development source requires PHP 8.3 or later in the PHP 8 series, with the
+extensions declared by the selected revision. Install locked dependencies in
+the staging directory with `composer install --no-dev`, then run `composer
+check-platform-reqs --no-dev`. Preserve this complete dependency tree when
+deploying the staged application. Do not run `composer update` against a live
+installation. A complete release bundle can already include dependencies;
+verify its platform checks instead of assuming that every archive is complete.
+
+## Install the staged files
+
+Obtain the intended development revision and stage it outside the live
+installation. Record its commit and verify its provenance. If using a release
+archive instead, follow that release's requirements and verification steps.
+Keep the existing installation and its backup until the upgrade has been
+checked.
+
+Copy the contents of the prepared staging directory into the existing
+installation, not the directory itself. For example:
+
+```sh
+STAGING_DIR=/var/tmp/cacti-1.3-dev
+CACTI_DIR=/var/www/html/cacti
+cp -a "$STAGING_DIR"/. "$CACTI_DIR"/
+```
+
+Confirm that the new files are directly under the installation root, such as
+`$CACTI_DIR/poller.php`, rather than a nested `cacti-1.3-dev` directory.
+Preserve the existing `include/config.php` and review new options in
+`include/config.php.dist`. Reconcile local code changes and plugin
+compatibility with the new files; copying the release is not a substitute for
+reviewing those changes.
+
+Check permissions using the accounts that actually run the web server, poller
+and maintenance jobs. Those accounts need not be identical. Give the poller the
+required access to RRD and log paths, and check configured cache, resource and
+script paths. Preserve access needed by installation and package imports. Do
+not make the entire application tree writable as a permissions workaround.
+
+## Run and verify the upgrade
+
+Allow an administrator to open the Cacti URL and follow the database-upgrade
+workflow. Review errors before proceeding. The release also provides
+`cli/upgrade_database.php`; consult its `--help` output if using the CLI
+workflow. Do not manually advance the database version or force a starting
+version merely to bypass an upgrade check.
+
+Confirm the installed version, database-upgrade result, credentials, paths,
+plugin state and collector configuration. Check remote collectors individually
+and follow the applicable synchronization procedure; do not assume that two
+polling cycles prove their files and databases have upgraded successfully.
+
+Restore web access and the saved scheduler configuration only after the upgrade
+checks succeed, then re-enable collection. Use either the configured cron path
+or the daemon for a collector, not both. Verify logs, data freshness and
+representative RRD updates after normal polling resumes.
+
+## Recovery
+
+If the upgrade fails, keep writers stopped while deciding whether to retry or
+restore. Replacing PHP files alone does not undo a database migration. Restore
+the matching pre-upgrade database, application files, RRD data and external
+configuration or secret material, including affected remote-collector state.
+Verify the restored installation before re-enabling its schedulers. Restoring
+an earlier backup discards changes collected after that backup.
+
+[release]:
+[dump]:
+
+[supported-os]: Requirements.md#supported-operating-systems
+
+---
+
+Copyright (c) 2004-2026 The Cacti Group
diff --git a/convert-from-package-to-source-debian-ubuntu.md b/convert-from-package-to-source-debian-ubuntu.md
index a55e3120..9079011d 100644
--- a/convert-from-package-to-source-debian-ubuntu.md
+++ b/convert-from-package-to-source-debian-ubuntu.md
@@ -1,62 +1,60 @@
-# Converting from Debian/Ubuntu Package Install to Cacti Source-Based Install
-
-This guide outlines the steps to convert from a Debian/Ubuntu package install of Cacti to a source-based install.
-
-If you are looking to run the latest version of Cacti a source based installation is the way to go
-Often the cacti team releases feature and updates that the packages lag behind on also source based installs
-provide more control for administrators than a package installation
-
-This document will provide the steps on how to convert a system that has been installed via package on a Debian/Ubuntu system while retaining your settings and data
-
-### Important ! Before running these steps ensure you have a system backup !
-#### Note these steps can vary between Ubuntu/Debian versions however the process flow would be the same
-
-## Step 1: Stop Cron/cactid Daemon
-ensure that cron is stopped to prevent any conflicts during the transition and to prevent the poller from running while backing up the system
-systemctl stop cron
-If you have installed the cactid daemon
-```shell
-systemctl stop cactid
- ```
-
-## Step 2: Backup Configuration File
-```shell
-cp /usr/share/cacti/site/include/config.php /path/to/backup/config.php
-```
-
-## Step 3: Backup Graph Files
-You can copy all of the graph files in `/usr/share/cacti/site/rra` to another folder so you can copy them back later.
-```shell
-cp -r /usr/share/cacti/site/rra /path/to/backup/rra
-```
-
-## Step 4: Dump the Database
-Create a backup of the Cacti database.
-```shell
-mysqldump cacti > cacti.sql
-```
-## Step 5: Uninstall the Package Version of Cacti
-Remove and purge the Cacti package to ensure no conflicts with the source-based install.
-```shell
-apt-get remove cacti && apt-get purge cacti
-```
-
-## Step 6: Install Cacti via Source
-Follow the appropriate steps to install Cacti from source. Refer to the official Cacti https://github.com/bmfmancini/documentation/blob/develop/Installing-Under-Ubuntu-Debian.md
-
-## Step 7: Re-import the Database
-Once Cacti is installed from source, restore your previous settings by re-importing the database.
-```shell
-mysql cacti < cacti.sql
-```
-
-## Step 8: Restore Graph Files
-Copy the backed-up RRA files to the new RRA folder directory in your source installation.
-
-```shell
-cp -r /path/to/backup/rra /new/cacti/source/path/rra
-```
+# Converting a Debian or Ubuntu Package Installation to Source
+
+Use this procedure only on a [supported operating system][supported-os].
+Changing installation ownership can affect paths, service accounts, package
+upgrades, and database management. Test the migration on an isolated copy
+before changing a production server.
+
+## Record the installed layout
+
+Record the Cacti version, database and grants, PHP configuration, web-server
+configuration, scheduler, service accounts, plugins, Spine configuration,
+and actual RRD, log, cache, script, and query-resource paths. Distribution
+packages can keep configuration and data outside the web application tree.
+Inspect symlinks and package-managed files; do not assume that copying the
+web directory includes their external targets.
+
+## Pause writers and take a complete backup
+
+Follow [Upgrading Cacti](Upgrading-Cacti.md#stop-writers-before-backing-up)
+to pause only Cacti's scheduler and other application writers, and take a
+matching backup of the database, files, RRD history, configuration, and
+external state. Do not stop the entire system cron service. Verify the backup
+and rehearse restoring it before changing the package installation.
+
+## Stage and verify the source installation
+
+Use the [source installation guide][install] to select and stage the intended
+Cacti revision and dependencies in a new directory. Its fresh-install schema
+import is for an empty database. Preserve the existing database for this
+migration; do not import `cacti.sql` over it or run the fresh-install procedure
+against production data.
+
+Copy the existing configuration, custom resources, plugins, and RRD data to
+the intended paths, preserving permissions. Reconcile the new configuration
+example, URL path, web restrictions, dependency versions, and service accounts.
+Protect credentials and secret files. Use the package maintainer's documented
+procedure to relinquish package ownership without deleting application data.
+Do not purge the package or accept a database-removal prompt merely to switch
+to source. Keep the old installation and verified backup available.
+
+## Cut over and validate
+
+With writers still paused, update the web mapping and the single Cacti
+scheduler to the source installation. If changing Cacti versions, follow the
+[database-upgrade procedure](Upgrading-Cacti.md#run-and-verify-the-upgrade)
+against the preserved database. Verify paths, permissions, plugins, collector
+connectivity, and any remote-collector upgrades before resuming collection.
+
+Check scheduled polling, logs, RRD updates, and representative graphs.
+Document how future source updates will be applied and prevent a later package
+operation from overwriting the source deployment. If recovery is required,
+restore the matching files, database, RRDs, and configuration as one set;
+restoring application files alone does not undo a database migration.
+
+[supported-os]: Requirements.md#supported-operating-systems
+[install]: Installing-Under-Ubuntu-Debian.md
---
-Once these steps are completed, your Cacti installation will be switched from a package-based install to a source-based one, while retaining your configurations and graphs.
+Copyright (c) 2004-2026 The Cacti Group
diff --git a/template_apache_config.md b/template_apache_config.md
index 7e1e55ef..383e93d1 100644
--- a/template_apache_config.md
+++ b/template_apache_config.md
@@ -7,7 +7,7 @@ statistics and use the endpoint on the server being monitored.

-## CentOS and Red Hat configuration
+## Enterprise Linux configuration
Check whether the installed Apache configuration already loads `mod_status`.
Add the module load only if it is missing, then configure the status location