/ OpenBSD

Easy system monitoring with Cacti under OpenBSD and nginx

Cacti is a great monitoring tool based on RRDTool and SNMP, I use this solution for more than 10 years, the project is very active, easy to manage and to maintain.


But... when you want to run it under OpenBSD with a chrooted httpd it can be very painfull to setup and it will make you want to break stuff.

So today we'll take the easy way !

Here, Cacti is just used by myself, so I need to restrict access to the service for more security, and to make sure that everything is running without privileges.

So... what do we need to make this wonderful project a reality ?

  1. An Operating System ("Do you have any others jokes like that ?" - "Plenty !"), we'll take OpenBSD, what else ?
  2. A chrooted http server, what about nginx ? seems perfect to me as it's chrooted by default on OpenBSD
  3. A snmp daemon, net-snmp is a great tool your can use to collect your datas
  4. RRDTool to generate your graphs
  5. PHP / MySQL, should I explain why ?
  6. Cacti

Install and configure what we need !

1. All the components we need :

# pkg_add nginx mariadb-server net-snmp php-snmp php-pdo_mysql php-gd php-gmp php-ldap rrdtool
# ln -s /usr/local/bin/php-7.0 /usr/local/bin/php

For PHP packages, I took the 7.x versions.

2. Setup net-snmp

We are using net-snmp in local, so we just bind it on the localhost, snmp v1 protocol will be enough.

# vi /etc/snmp/snmpd.conf

agentAddress   udp:
sysLocation    Somewhere in a dark and creepy place
sysContact     Lina Sovereign <lina@cagedmonster.net>

# rcctl enable netsnmpd && rcctl start netsnmpd

3. Setup MariaDB (MySQL)

# rcctl enable mysqld && mysql_install_db && rcctl mysqld start
# mysql_secure_installation


In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): [ENTER]
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] Y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] Y
... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] Y
... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] Y
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] Y
... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

Configuration tuning :

# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
# vi /etc/my.cnf
max_allowed_packet = 32M
tmp_table_size = 64M
innodb_doublewrite = OFF
innodb_additional_mem_pool_size = 80M
innodb_flush_log_at_timeout = 3
innodb_read_io_threads = 32
innodb_write_io_threads = 16
default_time_zone = Europe/Paris

# rcctl restart mysqld

4. Setup PHP

# rcctl enable php70_fpm
# cp /etc/php-7.0.sample/* /etc/php-7.0/
# rcctl start php70_fpm

5. Cacti

We'll create a dedicated user to Cacti :

# adduser
Ok, let's go.
Don't worry about mistakes. There will be a chance later to correct any input.
Enter username []: cacti
Enter full name []: cacti user
Enter shell bash csh ksh nologin sh [bash]:
Uid [1001]:
Login group cacti [cacti]:
Login group is ``cacti''. Invite cacti into other groups: guest no
Login class authpf bgpd daemon default pbuild staff unbound
Enter password []:
Enter password again []:

Name:        cacti
Password:    ****
Fullname:    cacti user
Uid:         1001
Gid:         1001 (cacti)
Groups:      cacti
Login Class: default
HOME:        /home/cacti
Shell:       /usr/local/bin/bash
OK? (y/n) [y]: y
Added user ``cacti''
Copy files from /etc/skel to /home/cacti
Add another user? (y/n) [y]: n

# su cacti
$ cd ~/
$ wget http://www.cacti.net/downloads/cacti-1.1.16.tar.gz
$ tar xvzf cacti-1.1.16.tar.gz
$ mv cacti-1.1.16 cacti
$ cd cacti

Time to create our SQL user/database :

$ mysql -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 32
Server version: 10.0.30-MariaDB OpenBSD port: mariadb-server-10.0.30v1

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> create database cacti;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> CREATE USER 'cacti'@'localhost' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> grant create,delete,insert,select,update,alter ON cacti.* TO 'cacti'@'localhost';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> use mysql;
Database changed

MariaDB [mysql]> GRANT SELECT ON mysql.time_zone_name TO 'cacti'@'localhost';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> quit

Configure our database :

$ mysql -u cacti -p cacti < cacti.sql
Enter password:

Configure Cacti :

$ vi include/config.php

$database_type     = 'mysql';
$database_default  = 'cacti';
$database_hostname = 'localhost';
$database_username = 'cacti';
$database_password = 'password';
$database_port     = '3306';
$database_ssl      = false;
$url_path = '/';

Now we'll use the built-in PHP server to start our service.

$ /usr/local/bin/php-7.0 -S
PHP 7.0.16 Development Server started at Fri Aug  4 09:21:53 2017
Listening on
Document root is /home/cacti/cacti
Press Ctrl-C to quit.

6. nginx

Our goal is to redirect http to https, use ssl, connect to our local php server running on localhost:9000 and restrict the access to our localnet, in my case : & 2a01:cb06:3e0:eb00::/56.

# vi /etc/nginx/nginx.conf

server {
   listen 80;
   listen         [::]:80;
   server_name    cacti.cagedmonster.net;
   return         301 https://$server_name$request_uri;

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name  cacti.cagedmonster.net;
    ssl_certificate /etc/letsencrypt/live/cagedmonster.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cagedmonster.net/privkey.pem;
             location / {
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    allow   2a01:cb06:3e0:eb00::/56;
                    deny    all;

# rcctl start nginx

7. Last step : Cacti interface and automation

Now you can check with your web browser if everything is fine. You should see something like this :


Follow the installation steps, you'll be able to configure your device here :


Finally, we configure our spooler to collect datas every 5 minutes with crontab and make sure our local PHP server runs at system startup :

$ crontab -e
@reboot cd ~/cacti/ && /usr/local/bin/php-7.0 -S > /dev/null 2>&1
*/5 * * * * /usr/local/bin/php-7.0 /home/cacti/cacti/poller.php > /dev/null 2>&1

Need help ?