Mettre à jour GLPI 11 vers GLPI 12 pas à pas (Linux et Docker), avec ce qui a cassé pendant le test

Nous avons mis à jour pour de vrai une copie de GLPI 11.0.11 vers la 12.0.0, sous Docker et sous Debian 13. La migration a pris 5 secondes. Le travail est venu après : MariaDB 10.6 refusé, plugins suspendus, base de connaissances en erreur 403 et webhooks arrêtés. Commandes et corrections.

Dans cet article8 sections

Nous avons mis à jour deux fois une copie d'un GLPI 11.0.11 vers la 12.0.0 : sous Docker avec l'image officielle, et sous Debian 13 avec l'archive .tgz. La migration de la base a pris environ 5 secondes dans les deux cas. Le travail est venu avant et après : MariaDB 10.6 a été refusé, les plugins ont été suspendus, les catégories de la base de connaissances sont devenues des articles que ni les techniciens ni les utilisateurs ne peuvent ouvrir, et le webhook a cessé d'envoyer, pour deux raisons différentes. Ce guide détaille les deux méthodes pas à pas et la correction de chaque problème, dans l'ordre où ils sont apparus.

Vous hésitez encore à faire la mise à jour ? Lisez d'abord GLPI 12 est sorti : ce qui change, prérequis et quand mettre à jour.

Ce que nous avons testé

Nous avons monté un GLPI 11.0.11 jetable avec les données fictives d'Acme : 120 tickets avec suivis et 40 tâches, un SLA, 9 articles de base de connaissances répartis dans 4 catégories aux permissions différentes, un webhook vers un serveur interne et trois plugins de la communauté (Fields, Tag et Data Injection), avec des données. Nous avons fait une sauvegarde et mis à jour vers la 12.0.0. Puis nous avons restauré la même sauvegarde sur un Debian 13 et refait la mise à jour avec l'archive .tgz.

Frise chronologique du test de mise à jour de GLPI 11.0.11 vers la 12.0.0, avec le résultat de chaque étape : sauvegarde, MariaDB refusé, mise à jour de MariaDB, migration, plugins, base de connaissances, webhook et réseau interne
La migration de la base a pris 5 secondes. Les problèmes sont venus avant (MariaDB) et après (plugins, base de connaissances et webhooks). Test NexTool, 16/10/2026.
Élément Résultat
Migration de la base (de 455 à 460 tables, de 47 à 49,5 Mo) Environ 5 secondes, sans erreur, avec les deux méthodes
Tickets, suivis, tâches, valeurs des champs Fields et étiquettes Tous conservés
Plugins (versions pour GLPI 11) Suspendus puis désactivés : une nouvelle version est requise
Catégories de la base de connaissances Devenues des articles sans permission (erreur 403 pour le technicien et l'utilisateur)
Webhook créé sous GLPI 11 N'envoie plus : méthode « post » en minuscules et réseau interne bloqué

Avant de commencer : les prérequis

Élément GLPI 11 GLPI 12
PHP 8.2 à 8.5 8.3 à 8.5
MariaDB 10.6 ou plus récent 10.11 ou plus récent
MySQL 8.0 ou plus récent 8.0 ou plus récent

Deux points mis en évidence par le test :

  • PHP 8.2 ne donne pas un avertissement, il donne une erreur de syntaxe. La console de GLPI 12 n'arrive même pas à la vérification des prérequis : elle s'arrête sur un « Parse error » dans un fichier de GLPI lui-même. Debian 12 et Ubuntu 22.04 sont livrés avec PHP 8.2 ou plus ancien. Debian 13 (PHP 8.4) et Ubuntu 24.04 (PHP 8.3) conviennent avec les paquets standard. L'image Docker officielle embarque déjà PHP 8.5.
  • Vérifiez la base avant toute chose. Lancez php bin/console system:check_requirements avec le nouveau code pointé sur votre base. Sur notre MariaDB 10.6, la réponse a été claire : version non prise en charge, minimum 10.11.

Étape 0 : la sauvegarde (base, fichiers et clé)

Faites trois copies avant de toucher à quoi que ce soit : la base, le dossier des fichiers et le dossier de configuration. Le dossier de configuration contient glpicrypt.key. Sans lui, les mots de passe stockés par GLPI (collecteur de mails, LDAP, proxy, secrets des webhooks) ne peuvent plus être déchiffrés.

mariadb-dump --single-transaction --routines -u root -p glpi | gzip > glpi11-$(date +%F).sql.gz
tar czf glpi11-arquivos-$(date +%F).tgz /etc/glpi /var/lib/glpi/files /var/www/glpi/marketplace

Sous Docker avec l'image officielle, tout se trouve dans le volume monté sur /var/glpi (config, files, marketplace et logs) : copiez le volume entier. Dans notre test, le dump a pris 5 secondes et la copie du volume 8,5.

Méthode 1 : Docker avec l'image officielle

L'image officielle (glpi/glpi) met à jour la base toute seule quand elle démarre avec une nouvelle version. Il suffit de changer le tag et de démarrer le conteneur : aucune confirmation n'est demandée. C'est pourquoi la sauvegarde se fait avant le changement de tag, jamais après. Si vous préférez lancer la mise à jour à la main, démarrez avec GLPI_SKIP_AUTOUPDATE=true et utilisez la commande de la méthode 2.

1. Mettez à jour MariaDB si nécessaire. Avec MariaDB 10.6, le conteneur GLPI 12 s'est arrêté avec le code 128. Le journal a signalé des prérequis manquants, puis a écrit une phrase qui fait peur : « GLPI is not installed... Starting installation ». Il n'a rien installé. La base est restée intacte, en version 11.0.11, avec les 120 tickets. Il n'a simplement pas passé la vérification des prérequis. Le passage de MariaDB 10.6 à 10.11 a pris 22 secondes grâce à la variable de mise à jour automatique de l'image MariaDB. Démarrez d'abord la base seule (docker compose up -d db) et vérifiez le journal avant de continuer :

services:
  db:
    image: mariadb:10.11          # avant : 10.6
    environment:
      MARIADB_AUTO_UPGRADE: "1"   # lance mariadb-upgrade au démarrage
  glpi:
    image: glpi/glpi:12.0.0       # avant : 11.0.11 (étape 2)
    volumes:
      - glpi-data:/var/glpi

2. Changez le tag et démarrez. docker compose up -d. Le journal affiche « GLPI is installed, and auto-update is enabled. Starting update... », puis le message de bienvenue. Dans le test, il s'est écoulé 17 secondes entre le up et le message de bienvenue dans le journal.

3. Vérifiez. docker compose exec glpi bin/console db:check doit répondre « Database schema is OK ».

Méthode 2 : Linux avec l'archive .tgz

Les commandes ci-dessous suivent l'arborescence de notre guide d'installation de GLPI 11 sous Debian et Ubuntu : code dans /var/www/glpi, configuration dans /etc/glpi et fichiers dans /var/lib/glpi/files.

cd /var/www/glpi && sudo -u www-data php bin/console maintenance:enable
cd /var/www && mv glpi glpi-11-antigo
wget https://github.com/glpi-project/glpi/releases/download/12.0.0/glpi-12.0.0.tgz
tar xzf glpi-12.0.0.tgz
cp glpi-11-antigo/inc/downstream.php glpi/inc/                  # s'il existe
cp glpi-11-antigo/config/local_define.php glpi/config/ 2>/dev/null  # s'il existe
cp -a glpi-11-antigo/marketplace/. glpi/marketplace/
chown -R www-data:www-data glpi
cd glpi
sudo -u www-data php bin/console system:check_requirements
sudo -u www-data php bin/console database:update
sudo -u www-data php bin/console maintenance:disable

Le fichier que tout le monde oublie : inc/downstream.php. C'est lui qui indique à GLPI que la configuration se trouve dans /etc/glpi. Il est rangé dans le dossier du code, donc il disparaît quand vous remplacez ce dossier. Dans le test, sans lui, database:update a répondu « Unable to connect to database ». Le message ne donne pas la vraie cause : GLPI a cherché la configuration au mauvais endroit. Une fois le fichier recopié, la mise à jour est passée tout de suite. Il en va de même pour config/local_define.php, si vous l'utilisez.

Si votre GLPI garde config et files dans /var/www/glpi, copiez aussi config/ et files/ depuis l'ancien dossier. C'était le cas sous Debian 13 (PHP 8.4) : la migration a pris 5 secondes et le db:check est ressorti propre.

Si la mise à jour de la base échoue

Sur le forum GLPI, le 3 novembre, une mise à jour de la 11.0.8 vers la 12.0.1 sous Debian 13 a bloqué : fichiers copiés, propriétaire et droits ajustés, puis maintenance:disable a renvoyé une erreur et la mise à jour de la base a échoué. Nous n'avons pas reproduit ce cas. Une réponse dans le fil a indiqué une cause probable, et le code de la migration confirme qu'elle est possible : en 11, la table qui relie les articles aux catégories de la base de connaissances accepte plusieurs fois le même couple article/catégorie ; la table qui la remplace en 12 ne l'accepte pas. Un seul lien en double suffit à arrêter la migration. Restaurez la sauvegarde de la 11 (la migration a pu s'arrêter en cours de route) et cherchez les doublons :

SELECT knowbaseitems_id, knowbaseitemcategories_id, COUNT(*) AS n
FROM glpi_knowbaseitems_knowbaseitemcategories
GROUP BY knowbaseitems_id, knowbaseitemcategories_id
HAVING n > 1;

Si une ligne ressort, supprimez les copies en gardant un lien par couple. L'article reste dans sa catégorie :

DELETE l1 FROM glpi_knowbaseitems_knowbaseitemcategories l1
JOIN glpi_knowbaseitems_knowbaseitemcategories l2
  ON l1.knowbaseitems_id = l2.knowbaseitems_id
 AND l1.knowbaseitemcategories_id = l2.knowbaseitemcategories_id
 AND l1.id > l2.id;

Si la requête ne renvoie rien, la cause est ailleurs. Vérifiez que le dossier des fichiers et celui de la configuration (dans notre organisation, /var/lib/glpi/files et /etc/glpi) appartiennent à www-data, lancez system:check_requirements et lisez php-errors.log dans le dossier _log des fichiers ainsi que le journal d'erreurs du serveur web. Lancez database:update en ligne de commande, qui affiche l'erreur à l'écran, et seulement ensuite maintenance:disable.

Après la migration : ce qui a cassé et comment le corriger

1. Les plugins sont suspendus (et la commande de liste ne le montre pas)

Après la mise à jour, GLPI 12 suspend l'exécution de tous les plugins. plugin:list a continué d'afficher les trois comme « Enabled ». Mais le paramètre plugins_execution_mode valait « suspended_by_update », et aucun plugin ne s'exécutait. Pour les réactiver :

php bin/console plugin:resume_execution

À la réactivation, GLPI a vérifié les versions et a désactivé les trois (« Installed / not activated »). Les versions pour la 11 acceptent au maximum GLPI 11.0.99, et les versions pour la 12 exigent au minimum la 12.0.0. Autrement dit : impossible de mettre à jour ces plugins avant GLPI. D'abord GLPI, ensuite les plugins :

Plugin Version sous GLPI 11 Version sous GLPI 12
Fields (champs supplémentaires) 1.24.6 1.25.0
Tag 2.14.8 2.15.0
Data Injection 2.15.12 2.16.0

Pour chacun : remplacez le dossier dans marketplace/ par la nouvelle version, puis lancez plugin:install et plugin:activate. Les données sont restées : les 5 valeurs du champ « Centre de coûts » de Fields et les 10 étiquettes de Tag étaient toujours là. Avant de fixer la date, vérifiez que tous vos plugins ont déjà une version pour la 12 (comment choisir ses plugins sans bloquer la mise à jour).

2. Les catégories de la base de connaissances deviennent des articles sans visibilité

GLPI 12 n'a plus de catégories dans la base de connaissances : les 4 catégories sont devenues 4 articles « parents », et un article racine (« Home ») a été créé au-dessus d'eux. Les 9 articles ont gardé leurs permissions. Mais les 4 articles qui étaient des catégories se sont retrouvés sans aucune règle de visibilité. Nous avons testé via l'API avec un technicien et un utilisateur Self-Service : tous les deux ont reçu une erreur 403 en ouvrant « Procédures », « Réseau », « Wi-Fi » et « FAQ utilisateur ». Chacun a continué à ouvrir uniquement les articles qu'il voyait déjà.

Correction : ouvrez chaque ancienne catégorie et donnez-lui le public qu'avait le dossier (entité, profil ou groupe). Sous GLPI 12, un article hérite de la visibilité des articles situés au-dessus de lui. Dans le test, ouvrir l'ancienne catégorie « FAQ utilisateur » à l'entité Acme a permis au technicien d'ouvrir le dossier et les deux articles qu'il contient, qui renvoyaient auparavant une erreur 403. Pour l'utilisateur Self-Service, il y a une étape de plus : il ne voit que les articles marqués FAQ, et les anciennes catégories arrivent sans cette marque. Avec la visibilité et la marque FAQ, le dossier est apparu pour lui aussi. Faites-le avant d'ouvrir le système aux utilisateurs.

3. Le webhook s'est arrêté : méthode « post » en minuscules

Le webhook créé sous GLPI 11 est entré dans la file d'attente et a échoué. Le journal webhook.log a donné la cause : Invalid HTTP method "post", only uppercase letters are accepted. GLPI enregistre la méthode en minuscules, et le client HTTP de la 12 n'accepte que les majuscules. Cela touche tous les webhooks, y compris ceux créés sous la 12. Le problème est signalé sur le GitHub de GLPI (issue 25883), avec un correctif proposé. Lors de notre test, le 16 octobre, le correctif n'était encore ni dans la 12.0.0 ni dans la version de développement de la 12.0.1.

En attendant le correctif, le contournement consiste à passer la méthode en majuscules directement dans la base (après une sauvegarde) :

UPDATE glpi_webhooks SET http_method = UPPER(http_method);
UPDATE glpi_queuedwebhooks SET http_method = UPPER(http_method);

Si quelqu'un enregistre à nouveau le webhook depuis l'interface, le champ repasse en minuscules. Relancez alors la commande, et suivez les notes de version des 12.0.x : une fois le correctif intégré, le contournement ne sera plus nécessaire.

4. Ensuite, le blocage du réseau interne

Avec la méthode corrigée, l'erreur a changé : Host "glpiup-hook" is blocked. GLPI 12 bloque par défaut les appels du serveur vers les réseaux privés (10.x, 172.16-31.x, 192.168.x). Cela concerne les webhooks, les calendriers externes, les flux RSS et la connexion à GLPI Network. Par défaut, seuls les appels vers l'agent d'inventaire et l'authentification externe restent autorisés. Si votre webhook pointe vers un n8n, un ERP ou une API du réseau interne, il va s'arrêter.

Pour n'autoriser que le nécessaire, créez le fichier config/local_define.php dans le dossier du code de GLPI :

<?php
define('GLPI_SERVERSIDE_URL_ALLOWED_PRIVATE_NETWORKS_CONTEXTS', [
    \Agent::class,    // par défaut
    \Auth::class,     // par défaut
    \Webhook::class,  // autorise les webhooks vers le réseau interne
]);

Le piège de Docker : GLPI lit ce fichier dans /var/www/glpi/config/, qui se trouve dans l'image, et non dans le volume /var/glpi/config. Placé dans le volume, le fichier n'a eu aucun effet. Monté en tant que fichier, il a fonctionné :

    volumes:
      - glpi-data:/var/glpi
      - ./local_define.php:/var/www/glpi/config/local_define.php:ro

Après cela, les deux webhooks en file d'attente ont été livrés avec le statut 200. Pour configurer un webhook de zéro, voir les webhooks natifs de GLPI 11.

5. L'avertissement sur les documents

La migration a laissé un seul avertissement dans le journal warning_during_migration_to_12.0.0.log : « Rights have been given for document, you should review ACLs after update ». GLPI a accordé de nouveaux droits sur les documents. Vérifiez-les dans Administration > Profils, onglet Gestion > Documents, en particulier sur les profils des utilisateurs finaux.

Checklist de la mise à jour

Quand Que faire
Avant Vérifier PHP (8.3+) et la base (MariaDB 10.11+ ou MySQL 8.0+) avec system:check_requirements
Avant Lister les plugins et confirmer que chacun a une version pour la 12
Avant Lister les webhooks et les intégrations qui pointent vers des adresses internes
Avant Chercher les liens en double entre articles et catégories de la base de connaissances
Avant Sauvegarder la base, les fichiers et le dossier de configuration (avec glpicrypt.key)
Pendant Mode maintenance, remplacement du code (ou du tag), database:update
Pendant Avec le .tgz : copier inc/downstream.php et config/local_define.php depuis l'ancien dossier
Après db:check, plugin:resume_execution et mise à jour de chaque plugin
Après Donner une visibilité aux anciennes catégories de la base de connaissances (et la marque FAQ, pour le Self-Service)
Après Corriger la méthode des webhooks et autoriser le réseau interne, si besoin
Après Revoir les droits sur les documents dans les profils
Après Ouvrir un ticket de test, déclencher un webhook, se connecter en tant qu'utilisateur final

Et les modules NexTool ?

Le plugin NexTool et ses 37 modules fonctionnent sous GLPI 11 et sous GLPI 12 avec la même version. C'est pourquoi, contrairement aux plugins ci-dessus, vous pouvez les mettre à jour avant, encore sous la 11, dans NexTool > Modules > Tout mettre à jour. Après la migration, ils sont suspendus comme les autres plugins : lancez plugin:resume_execution et vérifiez la liste dans NexTool > Modules. Le tableau module par module se trouve dans NexTool sous GLPI 12 : compatibilité. Si vous souhaitez de l'aide pour planifier ou réaliser la mise à jour, parlons-en.


Test réalisé par NexTool le 16 octobre 2026, sur une copie jetable avec des données fictives : image officielle glpi/glpi 11.0.11 vers 12.0.0 (PHP 8.5), MariaDB 10.6 vers 10.11, et archive .tgz sous Debian 13 (PHP 8.4). L'environnement a été supprimé à la fin. GLPI est une marque déposée de Teclib'. NexTool n'est pas affiliée à Teclib'.

Questions fréquentes

Sur notre copie de test (120 tickets, base de 47 Mo), la migration de la base a pris environ 5 secondes, sous Docker comme sous Linux. Les bases plus volumineuses prennent plus de temps. Le temps qui compte se trouve dans la sauvegarde, la mise à jour des plugins et les vérifications après la migration.

S'il est en dessous de la 10.11, oui. GLPI 12 exige MariaDB 10.11 ou MySQL 8.0, et PHP 8.3 à 8.5. Dans le test, GLPI 12 a refusé MariaDB 10.6, que GLPI 11 acceptait, sans toucher à la base.

Pas avec la même version. Après la migration, GLPI suspend les plugins et, à la réactivation, désactive ceux qui ne déclarent pas la prise en charge de la 12. Installez la version pour la 12 de chaque plugin après la migration. Les données des plugins ont été conservées dans le test. NexTool et ses modules fonctionnent sous la 11 et la 12 avec la même version.

Sous GLPI 12, les catégories de la base de connaissances deviennent des articles, et ces articles arrivent sans aucune règle de visibilité. Donnez à chaque ancienne catégorie le public qu'elle avait et, pour le Self-Service, marquez-la aussi comme FAQ.

Dans le test, il y avait deux raisons. Dans la 12.0.0, la méthode « post » enregistrée en minuscules est refusée par le client HTTP (issue 25883 sur le GitHub de GLPI). Et GLPI 12 bloque par défaut les appels vers les réseaux internes. La correction de chacun est dans l'article.

Oui. Quand elle démarre avec une nouvelle version, elle lance la mise à jour de la base sans demander de confirmation. Faites la sauvegarde avant de changer le tag, ou démarrez avec GLPI_SKIP_AUTOUPDATE=true et lancez la mise à jour à la main.

Commentaires

Les commentaires de cet article proviennent de GitHub (giscus). En les chargeant, votre navigateur se connecte à GitHub, qui reçoit votre adresse IP et peut enregistrer ses propres cookies.

Pour les charger automatiquement, activez les cookies fonctionnels

Besoin d'aide ?