Drupal : un healthcheck qui contrôle tous les services de votre site

This article is also available in English

Surveiller un site Drupal avec Uptime Kuma (ou n'importe quelle sonde), c'est souvent vérifier que la page d'accueil répond 200. Le problème, c'est que la page d'accueil répond 200 dans beaucoup de cas où le site est mal en point : la page est servie depuis le cache alors que la base est tombée, Redis ne répond plus mais le cache de pages tient encore, le Solr est en panne et la recherche renvoie une page vide, le disque est plein et plus aucun upload ne passe… On l'apprend par un utilisateur, pas par la sonde.

J'ai donc écrit un petit module, kgaut/healthcheck, qui expose une route /health qui interroge réellement les services dont le site dépend, et rend un verdict JSON lisible par une sonde ou par un job de CI.

$ curl -sS https://www.exemple.fr/health
{"status":"ok","checks":{"database":"ok","redis":"ok","search_api":"warning","files":"ok"}}

Installation

composer require kgaut/healthcheck
drush en healthcheck

Aucun réglage n'est nécessaire. Le module demande Drupal 11.1 ou plus et PHP 8.3.

Ce qui est vérifié

VérificationCe qu'elle faitCritique
databaseun SELECT 1 sur la connexion par défautoui
redisun PING via le module redis, si une connexion est déclaréeoui
search_apila disponibilité de chaque serveur Search API actif (un ping pour Solr)non
filesécrit, relit puis supprime un fichier dans public://.healthcheckoui

Chaque vérification rend un verdict parmi quatre :

  • ok : le service a répondu ;
  • failed : une vérification critique a échoué, la réponse passe en 503 ;
  • warning : une vérification non critique a échoué, la réponse reste en 200 (un Solr en panne dégrade la recherche, il ne rend pas le site indisponible) ;
  • not_configured : le site n'utilise pas ce service (pas de Redis, pas de serveur Search API). Ce n'est jamais un échec.

Le corps de la réponse ne contient ni nom d'hôte, ni chemin, ni message d'erreur : la cause d'un échec part dans le journal de Drupal (canal healthcheck). Le verdict est gardé 30 secondes, pour qu'une rafale d'appels ne martèle pas la base ou Redis, mais la réponse HTTP n'est jamais mise en cache (Cache-Control: no-store).

Une règle pour la sonde

Si vous ne retenez qu'une chose : une sonde ne doit tenir pour sain qu'un HTTP 200 dont le corps contient "status":"ok", sans suivre les redirections.

Pourquoi tant de précautions ? Parce qu'une base injoignable au démarrage de Drupal donne un 500 (et pas un 503 du module, Drupal ne démarre même pas), qu'un proxy ou une page de maintenance peut répondre 200 avec son propre contenu, et qu'un site mal configuré peut rediriger /health vers l'installeur ou vers /fr/health. Dans Uptime Kuma, c'est une sonde de type « HTTP(s) - Mot-clé » sur "status":"ok", avec les redirections désactivées.

Réglages par site et par environnement

Tout est dans la config healthcheck.settings, exportée avec le reste de la config du site. On peut par exemple rendre Search API critique sur un site où la recherche est le cœur du métier, ou désactiver une vérification. Et comme toute config, ça se surcharge dans le settings.php :

// Search API critique en production seulement.
$config['healthcheck.settings']['checks']['search_api']['critical'] = TRUE;
// Le test d'écriture dans un autre dossier.
$config['healthcheck.settings']['files_directory'] = 'private://healthcheck';

Ajouter ses propres vérifications

Les vérifications sont des plugins. Un site qui dépend d'une API tierce, d'un serveur de mails ou d'un autre service peut ajouter la sienne depuis n'importe quel module, avec un attribut PHP :

namespace Drupal\mon_module\Plugin\HealthCheck;

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\healthcheck\Attribute\HealthCheck;
use Drupal\healthcheck\CheckResult;
use Drupal\healthcheck\HealthCheckBase;

#[HealthCheck(id: 'mon_service', label: new TranslatableMarkup('Mon service'), critical: TRUE, weight: 40)]
final class MonService extends HealthCheckBase {

  public function check(): CheckResult {
    // Interroger réellement le service, avec un délai court.
    return CheckResult::ok();
  }

}

Côté drush

drush healthcheck:run                 # tableau : vérification, verdict, critique, cause
drush healthcheck:run --format=json   # pour une CI

La commande vérifie à chaque appel (sans le verdict gardé 30 secondes), affiche la cause de chaque échec, et sort en erreur si une vérification critique échoue. Pratique en fin de script de déploiement, ou pour comprendre pourquoi la sonde est rouge sans aller fouiller les logs.

Contrôle post déploiement en CI

C'est l'usage qui m'a fait écrire le module : sur mon infrastructure uzinasit, chaque tag déploie les sites, puis un job de CI vérifie que chacun répond bien sur son point de santé. Le module embarque le script pour ça, scripts/ci-health.sh, qui n'a besoin que de bash et curl :

prod:health:
  stage: postdeploy
  image: wodby/drupal-php:8.3-dev     # toute image avec bash et curl
  needs:
    - job: prod:clear-cache
      artifacts: false
  variables:
    HEALTH_URL: https://www.exemple.fr/health
  script:
    - bash web/modules/contrib/healthcheck/scripts/ci-health.sh "$HEALTH_URL"
  rules:
    - if: $CI_COMMIT_TAG

Le script fait jusqu'à 6 essais espacés de 10 secondes (le temps que les caches se réchauffent après le vidage), applique la règle « 200 + "status":"ok" sans redirection », et affiche le code et le corps de chaque essai en cas d'échec. Il ne bloque rien, le déploiement est déjà fait, mais le pipeline rougit, et on le sait tout de suite.

Où en est le module

Le module est en bêta (1.0.0-beta5 au moment où j'écris), il tourne sur mes sites et la 1.0.0 approche. Le code et la documentation complète (exploitation, écriture d'une vérification, décisions de conception) sont sur GitHub, et le paquet sur Packagist. Les retours sont les bienvenus dans les issues.

Écrit par Kevin Gautreau — développeur & formateur PHP/Drupal freelance en Auvergne. me contacter

Contenus en rapport

article · 29 Mai 2026 Uzinasit : retour d'expérience sur mon usine à site Drupal 11 J'ai profité d'avoir un peu de temps durant l'été 2025 pour commencer à rationaliser l'ensemble de mes sites histoire de m'en simplifier la gestion Pourquoi… article · 13 Oct 2026 Drupal : raw_fields_formatters, des données brutes pour les composants SDC et fronts découplés Je travaille sur des drupal découplés depuis quelques années (back drupal pour la contrib, et front angular ou application mobile par exemple) dans ces cas là… article · 19 Oct 2026 Drupal 11 : une brique de paragraphes réutilisable avec leurs composants SDC Tous les sites Drupal que je maintiens dans mon uzinasit finissent par avoir besoin des mêmes blocs de contenu : un texte riche, un texte avec une image, une…

Commentaires (0)