Tuning a Linux server for GLPI performance

Tuning a Linux server for GLPI performance

GLPI is a PHP application with a MariaDB backend. The default install is fine for a few dozen assets, but at 500+ assets and an active helpdesk it starts to feel slow — pages loading in 2 – 5 seconds, dashboards in 10+, users frustrated. This article is the tuning that returns GLPI to sub-second responsiveness. Concrete values for two reference deployments: small (200 assets) and medium (2000 assets).

The four-layer tuning profile

Four layers where performance is most often lost:

  1. OPcache — the PHP bytecode cache. Without it, every PHP file is parsed on every request. Single biggest win.
  2. PHP-FPM pool — the worker count for concurrent requests. The default is often too low for a helpdesk under load.
  3. MariaDB innodb_buffer_pool — how much RAM the DB has for caching. The default 128M is laughably small.
  4. Cron paths — log purging, optimize tables, scheduled actions. Without maintenance the DB grows unbounded.

OPcache

In /etc/php/8.2/fpm/conf.d/10-opcache.ini:

opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256       ; MB for bytecode cache
opcache.interned_strings_buffer=32   ; MB for interned strings
opcache.max_accelerated_files=20000  ; max PHP files in cache
opcache.revalidate_freq=60           ; how often to check for changes (sec)
opcache.fast_shutdown=1
opcache.validate_timestamps=1        ; 0 in dev, 1 in production

With 20+ plugins, GLPI has several thousand PHP files. max_accelerated_files=20000 gives headroom. After reloading FPM (systemctl reload php8.2-fpm) the difference is immediately visible — typically 30 – 50% faster page renders.

PHP-FPM pool

In /etc/php/8.2/fpm/pool.d/glpi.conf or www.conf:

# Small deployment (200 assets, ~10 concurrent users)
pm = dynamic
pm.max_children = 25
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500

# Medium deployment (2000 assets, ~50 concurrent users)
pm = dynamic
pm.max_children = 60
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 20
pm.max_requests = 1000

Rule of thumb: pm.max_childrenRAM / average_PHP_worker_size. A PHP worker with GLPI typically takes 50 – 150 MB. For a 4 GB RAM box max_children=25 is sensible; more starts swapping and paradoxically slows the system down.

pm.max_requests recycles a worker after N requests — protection against memory leaks in long-running PHP processes.

MariaDB

In /etc/mysql/mariadb.conf.d/50-server.cnf:

# Small deployment (4 GB RAM box)
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
max_connections = 100
query_cache_type = 0    ; do not use on MariaDB 10.5+
table_open_cache = 4000

# Medium deployment (16 GB RAM box)
[mysqld]
innodb_buffer_pool_size = 8G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 1G
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
max_connections = 200
table_open_cache = 8000

The most important value: innodb_buffer_pool_size. Rule: 50 – 70% of RAM if the server is dedicated to GLPI + MariaDB. The default 128M means 99% of queries go to disk — which even on NVMe is 10 – 100× slower than RAM.

GLPI cron and maintenance

Beyond application tuning, GLPI's scheduled actions must run so the DB doesn't grow indefinitely:

# System cron for GLPI
*/2 * * * * www-data php /var/www/glpi/front/cron.php

# Monthly maintenance — purge old logs + optimize tables
0 3 1 * * www-data php /var/www/glpi/bin/console glpi:logs:purge --no-interaction
0 4 1 * * mysql -e "OPTIMIZE TABLE glpi.glpi_logs, glpi.glpi_tickets, glpi.glpi_computers;"

Under Setup → General → Automatic actions, set purgelogs, purgesessions, purgeoldnews to weekly. Otherwise the glpi_logs table will hit millions of rows after a year and queries will slow.

Monitoring

Watch these metrics:

  • PHP-FPM busy workers — if persistently near max_children, raise the limit or scale.
  • MariaDB slow query log — enable slow_query_log = 1, long_query_time = 2. Read regularly; any query > 2s is a signal for an index or refactor.
  • Buffer pool hit rateSHOW ENGINE INNODB STATUS, value over 99% is good. Below 95%, raise the buffer pool.
  • OPcache hit rateopcache_get_status() in PHP, hit rate over 99% is normal.

Paired with a reverse proxy (see the reverse proxy configuration), these four tuning layers keep GLPI fast even at thousands of assets and dozens of concurrent users. Without tuning, the default GLPI install is fast at 20 people and slow at 200 — that's not a flaw of GLPI, it's default values that aren't production-tuned.

Need help with this topic?

Get in touch