# ADR 0009 — Elasticsearch interne, sécurité x-pack désactivée - **Date** : 2026-10-14 - **Statut** : accepté ## Contexte Bloc C du CLAUDE.md : « ElasticSearch : recherche plein texte dans les cours et les labs (seulement si le besoin est réel). » Adam a confirmé le besoin explicitement (« fonce »). Catalogue minuscule (quelques labs, un seul `cours.md` aujourd'hui) : aucun besoin d'un cluster, d'un cache de répertoires exotique ou d'une bibliothèque cliente PHP dédiée. ## Décisions **Une instance Elasticsearch 8.19, locale, jamais exposée.** Installée depuis le dépôt APT officiel Elastic (clé GPG vérifiée, même principe que Ceph/ADR 0007). Consommée uniquement par le portail, en PHP, sur `127.0.0.1:9200` — jamais par un navigateur. **Sécurité x-pack désactivée (`xpack.security.enabled: false`).** L'installation standard active TLS + authentification par défaut depuis la 8.x (mot de passe généré, certificats auto-signés) — pertinent pour un cluster multi-nœuds exposé, disproportionné pour une instance mono-nœud qui ne parle qu'à elle-même sur la boucle locale. Cohérent avec le reste de ce serveur : l'API OpenStack interne (`10.10.0.1`) et le MariaDB/Redis dédiés au portail (`127.0.0.1:3307`/`6380`) n'ont pas non plus de TLS entre services — l'isolation vient du pare-feu (`policy drop` par défaut) et de l'écoute en local, pas d'une authentification par service. Désactiver x-pack évite aussi de devoir stocker et faire tourner un mot de passe Elasticsearch supplémentaire pour rien. **Tas JVM réduit à 512 Mo (`-Xms512m -Xmx512m`), pas le calcul automatique d'Elasticsearch.** Par défaut, Elasticsearch vise jusqu'à 50 % de la RAM système — sur ce serveur à 31 Go réels (voir ADR 0007), cela aurait pu réserver ~15 Go à un service qui indexe quelques dizaines de documents. Mesuré après coup : ~900 Mo de RSS au total pour le processus, RAM disponible du serveur restée stable (~6 Go) pendant tout le chantier. **Appels HTTP directs (`Illuminate\Support\Facades\Http`), pas le client PHP officiel `elastic/elasticsearch`.** Le besoin se limite à indexer des documents et faire une recherche plein texte avec surlignage — deux appels REST simples. Ajouter une bibliothèque cliente complète (et ses dépendances) pour ça aurait été une techno sans besoin réel (CLAUDE.md, section 8). **Analyseur `french` d'Elasticsearch sur les champs `titre`/`contenu`.** Livré avec Elasticsearch, pas un plugin à installer : améliore réellement la pertinence sur du contenu pédagogique en français (élision, racines des mots) sans coût d'exploitation supplémentaire. **Reconstruction complète de l'index à chaque synchronisation** (`labs:synchroniser`, `cours:synchroniser`), pas une mise à jour incrémentale. Volume du catalogue trop faible pour que ça coûte quoi que ce soit ; plus simple et plus sûr (jamais de document orphelin si un lab est retiré). ## Conséquences - Recherche vérifiée en réel avec un compte élève jetable : les deux vrais documents existants (labs catalogués + `08-deux-lan-routeur/cours.md`, contenu réel) retrouvés par recherche plein texte, extrait surligné affiché, compte supprimé ensuite. - `App\Services\Recherche\IndexRecherche::disponible()` renvoie `false` si `ELASTICSEARCH_HOTE` n'est pas renseigné : la page de recherche affiche alors un message d'indisponibilité au lieu d'une erreur — même principe que `StockageTravauxEleves::disponible()` pour le S3. - En dette : pas de pagination des résultats (taille de catalogue bien en dessous du besoin), pas de recherche à facettes (niveau, compétence) — à ajouter si le catalogue grossit réellement.