GLPI

Rôle

GLPI est l'outil ITSM / gestion de parc (CMDB, tickets, inventaire) de référence de l'infrastructure Indio. Une note interne indique qu'il remplace OCS Inventory NG comme référence CMDB applicative — décision reflétée dans le commentaire du rôle Ansible et la description NetBox de la VM — mais OCS a néanmoins été redéployé en parallèle à la demande du user (voir OCS Inventory NG). GLPI embarque son propre module d'inventaire natif, activé lors du déploiement, ce qui rend la coexistence redondante sur ce point précis.

Architecture

  • VM unique INDSERV025 (10.100.2.155), zone service (seg-service), 2 vCPU / 4 Go, clone du template Rocky 9.6 durci — IP allouée dynamiquement via NetBox.
  • Pile applicative locale, sans conteneurs : MariaDB 10.11 (module AppStream) + PHP-FPM 8.2 (pool dédié) + nginx (reverse proxy TLS local).
  • FQDN support.infra.indio. Certificat TLS émis par la PKI Vault interne (pki_int/roles/infra-indio), déployé en fichiers statiques sous roles/glpi/files/tls/ (voir Procédure manuelle pour son émission).
  • GLPI 10.0.26, installé depuis une archive tarball récupérée sur un dépôt Nexus interne dédié (glpi-tarball) — aucun paquet distro n'est utilisé.
  • Racine documentaire nginx = {{ glpi_install_dir }}/public (front-controller unique public/index.php, recommandé par GLPI 10) : config/, files/, install/, tests/, tools/ vivent hors de public/, donc injoignables au niveau du serveur web quel que soit le chemin demandé — protection structurelle, pas une simple règle deny nginx.
  • Reverse proxy applicatif local uniquement : pas de backend dupliqué sur la VIP HAProxy partagée (règle d'architecture posée le 2026-07-15 — tout service disposant de son propre reverse proxy applicatif reste hors de la VIP HAProxy mutualisée).

Structure du dépôt

Fichier / dossier Contenu
main.tf VM unique vsphere_virtual_machine.glpi, IP résolue via NetBox
ansible/site.yml Rôles mariadb puis glpi
ansible/roles/mariadb Base + utilisateur MariaDB dédiés
ansible/roles/glpi/tasks/main.yml PHP-FPM, nginx, install CLI GLPI
ansible/roles/glpi/templates/glpi.conf.j2 vhost nginx (front-controller)
ansible/roles/glpi/files/tls/ Certificat/clé Vault PKI (statiques, non repris ici)
ansible/group_vars/glpi.yml Versions, FQDN, secrets ansible-vault

Chemin de requête

flowchart LR
    Client(("Navigateur")) -->|"443 TLS<br/>Vault PKI"| Nginx["nginx local<br/>root = glpi/public"]
    Nginx -->|"fastcgi<br/>unix:/run/php-fpm/glpi.sock"| PHPFPM["php-fpm<br/>(pool dédié glpi)"]
    PHPFPM -->|"socket unix<br/>mysql.sock"| MariaDB[("MariaDB 10.11<br/>base glpi (utf8mb4)")]
    PHPFPM -.->|"httpd_can_sendmail actif,<br/>relayhost non configuré"| Postfix["Postfix<br/>(voir postfix.md)"]

Provisioning Terraform

  • main.tf : VM unique vsphere_virtual_machine.glpi, IP résolue via NetBox (data netbox_ip_addresses, filtrée sur dns_name).
  • Variables clés (variables.tf) : vm_name = INDSERV025, vsphere_network = seg-service, vm_cpu = 2, vm_ram = 4096.
  • Providers (versions.tf) : hashicorp/vsphere + e-breuninger/netbox.

Configuration Ansible

Playbook ansible/site.yml, deux rôles appliqués en séquence sur l'hôte glpi :

  1. mariadb — active le module mariadb:10.11, installe le serveur, définit le mot de passe root (check_implicit_admin, idempotent que le compte vienne d'être créé ou déjà positionné), supprime les comptes anonymes et le root distant (root@'%'), purge la base test, crée la base glpi (utf8mb4/utf8mb4_unicode_ci) et l'utilisateur applicatif glpi@localhost (privilèges scopés à cette seule base), charge les tables de fuseaux horaires (mysql_tzinfo_to_sql, condition sur SELECT COUNT(*) FROM time_zone_name).
  2. glpi — active le module php:8.2 puis installe les extensions requises par GLPI 10.0.26 (php-curl, php-gd, php-intl, php-mbstring, php-mysqlnd, php-xml, php-bz2, php-zip, php-ldap, php-opcache) ainsi que nginx ; télécharge et extrait l'archive GLPI depuis Nexus ; vérifie les prérequis via l'outil natif bin/console system:check_requirements et fait échouer la tâche Ansible (assert) si un item [REQUIRED] n'est pas [OK]/[SKIPPED] ; installe le schéma en CLI non interactive (database:install --no-interaction), active les fuseaux horaires et l'inventaire natif (config:set enabled_inventory 1 --context=inventory) ; change le mot de passe du compte admin par défaut en générant le hash côté PHP (password_hash($pass, PASSWORD_DEFAULT), garantie de compatibilité totale avec src/Auth.php) puis en l'écrivant directement en base ; désactive (sans les supprimer, pour préserver l'intégrité référentielle) les comptes de démonstration tech/normal/post-only ; déploie le pool PHP-FPM dédié, les certificats TLS Vault PKI et le vhost nginx ; ouvre les ports 80/443 ; applique un contexte SELinux à deux niveaux (httpd_sys_content_t en lecture seule sur toute l'arborescence, httpd_sys_rw_content_t sur les seuls sous-dossiers dynamiques files/config/marketplace/plugins) et 3 booléens (httpd_can_network_connect, httpd_can_network_connect_db, httpd_can_sendmail) ; verrouille enfin config/ en lecture seule (mode 0550) une fois l'installation terminée.

Secrets (group_vars/glpi.yml, chiffrés ansible-vault) : mariadb_root_password, glpi_db_password, glpi_admin_new_password.

Procédure manuelle

Le certificat TLS utilisé par nginx n'est pas émis par le rôle Ansible lui-même (aucun appel à l'API Vault dans tasks/main.yml) — il est copié depuis roles/glpi/files/tls/, préparé manuellement au préalable :

  1. Émission via l'API/CLI Vault PKI : vault write pki_int/issue/infra-indio common_name=support.infra.indio ip_sans=10.100.2.155 ttl=<durée>.
  2. Récupération de certificate + private_key, et de la chaîne complète (ca_chain, Root + Intermediate — un issuing_ca seul ne suffit pas à établir la confiance jusqu'au Root).
  3. Copie des 3 fichiers (glpi.crt, glpi.key, ca.crt) dans roles/glpi/files/tls/ avant tout ansible-playbook site.yml.
  4. Renouvellement : aucune automatisation (pas d'auto-enrollment côté Linux comme le volet RDP d'ad-hardening) — à repasser manuellement par les mêmes étapes avant expiration.

Procédure de déploiement

  1. terraform apply → provisionne la VM.
  2. Préparer les certificats TLS sous roles/glpi/files/tls/ (voir Procédure manuelle) si pas déjà présents.
  3. ansible-playbook site.yml → applique mariadb puis glpi (tags disponibles : mariadb, glpi).

Contrôle de santé / Vérification

Vérifications intégrées en fin de rôle : https://support.infra.indio/ répond en 200/302 (retry jusqu'à 30 fois, 5 s d'intervalle) ; l'endpoint /front/inventory.php confirme que l'inventaire natif est actif (ne renvoie plus 403 "Inventory is disabled").

systemctl status nginx php-fpm mariadb
curl -sk -o /dev/null -w '%{http_code}\n' https://support.infra.indio/

Points d'attention

  • Connexion base de données en socket unix (glpi_db_host: localhost), pas en TCP — évite d'avoir à activer le booléen SELinux httpd_can_network_connect_db pour un usage qui n'en a pas besoin (activé quand même par anticipation, cf. Configuration Ansible).
  • Extension native sodium absente des dépôts internes (aucune build compatible avec le module php:8.2) : sans incidence, GLPI embarque son propre polyfill pur PHP (vendor/paragonie/sodium_compat) qui définit les mêmes constantes SODIUM_* — confirmé par l'outil natif system:check_requirements lui-même plutôt qu'un test sur php -m, qui aurait donné un faux négatif.
  • Comptes de démonstration GLPI (tech/normal/post-only, identifiants par défaut bien connus) désactivés plutôt que supprimés, sur un outil exposé côté zone service.
  • Verrouillage final de config/ en lecture seule (0550) une fois l'installation terminée — config_db.php/la clé de chiffrement GLPI ne sont réécrits qu'à l'install/upgrade, jamais en usage normal.
  • Aucun script setup.sh interactif ici (contrairement à OCS) : l'installation passe entièrement par l'outil CLI natif GLPI (bin/console), nettement plus robuste à automatiser. Les pièges d'installation interactive (permissions Unix apache/nginx, sefcontext non labellisé, mot de passe DB codé en dur dans des gabarits livrés) rencontrés sur la même stack MariaDB/PHP-FPM/nginx/Vault PKI sont documentés en détail sur la page OCS Inventory NG — ils ne s'appliquent pas à GLPI mais donnent une bonne idée du type de piège à anticiper sur ce genre de déploiement tarball.
  • Postfix (voir Postfix) est identifié comme destinataire probable des notifications de tickets par email (httpd_can_sendmail activé par anticipation), mais aucun relayhost n'est configuré côté GLPI à ce jour — l'intégration n'est pas fonctionnelle.