Journal des travaux¶
2026-07-27 — compte rendu des travaux qui ont mis en place cette plateforme documentaire, modifié le modèle de propriété de la configuration de l'edge, refermé les points faibles d'exploitation et traduit toute la documentation en sept langues.
L'objet de cette page n'est pas de noter ce qui a été fait mais pourquoi cela a été décidé ainsi. Le raisonnement est l'information qui vieillit le plus lentement : le code peut changer, la justification d'une décision demeure.
Périmètre
Les détails d'exploitation — adresses d'hôtes, chemins, valeurs de configuration secrètes — ne figurent pas sur ce site public ; ils se trouvent dans un runbook fermé, à l'intérieur du dépôt concerné.
Cinq axes¶
| # | Travail | Résultat |
|---|---|---|
| 1 | Mettre en place la plateforme documentaire | docs.gerege.mn est entré en service |
| 2 | Éclater la propriété de la configuration de l'edge | Chaque domaine a rejoint son propre dépôt |
| 3 | Refermer les points faibles d'exploitation | Suppression accidentelle et angles morts éliminés |
| 4 | Traduire la documentation en sept langues | Mongol + les six langues officielles de l'ONU, couverture complète |
| 5 | Consigner le passage à Nexus | Le nouveau modèle de l'écosystème documenté en sept langues |
1. La plateforme documentaire¶
Ce qui a été fait¶
Un portail MkDocs Material rassemblant en un seul endroit la documentation au niveau de l'écosystème Gerege : 25 pages, mongol par défaut, diagrammes Mermaid, CSS de marque. La couverture linguistique a ensuite été portée à sept langues — voir la section 4.
Le contenu a été rassemblé depuis les README, les répertoires docs/ et les
documents d'architecture des dépôts de l'écosystème, puis organisé en quatre
parties : couches · plateformes · standards · exploitation.
Décisions clés¶
Servir le site statique depuis un conteneur distinct. Ajouter un montage au conteneur de l'edge nginx impose de le recréer — et à ce moment-là tous les domaines tombent brièvement. En le servant depuis son propre petit conteneur, l'edge n'a besoin que d'un ajout de configuration et d'un reload.
Déployer sur place, avec rsync. Le répertoire du site est monté en bind
dans le conteneur. Remplacer le répertoire en bloc (mv) laisse le conteneur
pointer encore sur l'ancien inode, et le nouveau contenu n'apparaît jamais.
rsync met les fichiers à jour sur place, donc le montage reste valide.
Ancres des titres en cyrillique. Le slugify standard de l'extension toc de
Python-Markdown supprime les caractères non ASCII : le titre ## Танилт
reçoit un id vide et les liens internes cassent silencieusement. Nous sommes
passés au pymdownx.slugs.slugify, qui préserve l'unicode.
validation.anchors activé. Dans MkDocs, la vérification des ancres est
désactivée par défaut. Sans elle, un lien cassé pointant vers #section
passe la construction et atteint la production. Désormais il fait échouer
--strict.
Tout ce qui entre dans docs/ devient public. Les détails d'exploitation ont
donc été placés à part, dans un répertoire qui ne fait pas partie du site.
2. La propriété de la configuration de l'edge¶
C'est le plus gros changement d'architecture.
La situation antérieure¶
Les vhosts de tous les domaines vivaient dans un unique fichier central.
Conséquence : modifier un petit réglage pour docs.gerege.mn supposait d'envoyer
une PR dans un autre dépôt et d'attendre le déploiement d'une autre équipe.
Propriété floue, changements lents.
La situation actuelle¶
le répertoire de configuration de l'edge nginx
├── (fichiers partagés) ← propriété du dépôt de la stack combinée
│ sso · dan · gsign · xyp
├── docs.gerege.mn.conf ← docs-gerege-mn
├── developer.gerege.mn.conf ← developer-gerege-mn
└── template.gerege.mn.conf ← template-gerege-mn
Le vhost de chaque domaine vit désormais dans le dépôt du service concerné, et c'est son propre déploiement qui l'installe. Une modification se termine dans un seul dépôt.
Pourquoi cela fonctionne¶
Le répertoire de configuration se trouve physiquement dans la copie de travail
d'un autre dépôt, et le déploiement de ce dépôt exécute git reset --hard. Or
git reset --hard ne restaure que les fichiers suivis — il ne touche pas aux
fichiers non suivis. Le fichier installé depuis un dépôt extérieur survit donc.
Trois conditions pour une autonomie complète¶
Un vhost ne doit dépendre en rien des fichiers partagés :
| Condition | Pourquoi |
|---|---|
Sa propre limit_req_zone |
Recourir à un fichier de zones partagé crée une dépendance |
Son propre bloc listen 80 (ACME + redirection) |
Le renouvellement du certificat fonctionne alors seul |
| Réinstallation à chaque déploiement | Si le fichier disparaît, il se rétablit de lui-même |
Un ordre de migration sans interruption¶
- D'abord installer le nouveau fichier. À cet instant un même domaine est
défini en deux endroits, mais nginx n'en fait qu'un avertissement
conflicting server name— le comportement ne change pas, les deux pointent vers le même upstream. - Ensuite le retirer du fichier central. Le doublon disparaît et le nouveau fichier prend effet.
En procédant à l'envers, le domaine tombe entre les deux étapes.
Pas de chemin d'hôte dans un dépôt open source¶
template-gerege-mn est open source, et la convention en place voulait que les
informations serveur ne figurent que dans les secrets de la CI. L'installateur
déduit donc lui-même le chemin du répertoire de configuration des montages du
conteneur edge :
docker inspect <edge> --format \
'{{range .Mounts}}{{if eq .Destination "/etc/nginx/conf.d"}}{{.Source}}{{end}}{{end}}'
C'est plus fiable que de coder le chemin en dur ; ce procédé a donc ensuite été adopté dans les trois dépôts — il continue de fonctionner quand l'hôte ou le chemin change.
Un préalable de sécurité¶
Le certificat D'ABORD, le vhost ensuite. Ajouter un vhost HTTPS sans
certificat en place fait échouer nginx -t, et à cet instant tous les domaines
sont en danger. Le challenge ACME passe par le default server général du port 80,
si bien qu'obtenir un certificat n'exige aucune modification de configuration.
Avant le push, la configuration finale a été vérifiée par nginx -t dans un
conteneur temporaire, avec le réseau et les certificats réels.
3. Durcissement de l'exploitation¶
Protection contre la suppression accidentelle¶
Des fichiers dont dépend la production n'étaient suivis dans aucun dépôt.
git reset --hard ne les touche pas, mais git clean -fd les supprime.
| Fichier | En cas de perte | Solution |
|---|---|---|
| Les vhosts des trois domaines | 3 domaines tombent d'un coup | .gitignore |
| L'override compose de l'hôte | Le conteneur se détache du réseau edge → 502 | .gitignore + un fichier d'exemple |
Pourquoi .gitignore règle le problème : sans -x, git clean ignore les
fichiers ignorés. Cela les protège sans avoir à les suivre.
L'override compose ne doit pas être suivi : compose le lit automatiquement,
donc les réglages de production s'imposeraient dans l'environnement local de
chaque développeur. Le fichier vivant reste donc non suivi sur l'hôte, et seul un
exemple de restauration est conservé dans le dépôt. Que l'exemple produise le
même résultat que la configuration vivante a été confirmé en comparant la sortie
de docker compose config.
Surveillance de l'état de santé¶
Un script de surveillance existait déjà sur l'hôte, mais deux défauts se sont cumulés : il n'était pas enregistré du tout dans cron, et certains conteneurs qu'il nommait avaient été renommés et n'existaient plus. Le script ignore silencieusement un conteneur absent : personne ne savait donc que la surveillance s'était complètement arrêtée.
Décisions clés de la nouvelle version :
Le healthcheck propre au conteneur passe en premier. Son interval et ses retries sont déjà ajustés à ce service précis.
Le probe HTTP se fait depuis l'intérieur du conteneur. Tout vérifier via l'edge ferait paraître tous les services tombés dès que l'edge tombe, déclenchant un redémarrage massif et masquant la vraie panne. Chaque contrôle est désormais autonome.
Un seuil d'échecs consécutifs et un cooldown. Un ralentissement passager (déploiement, GC, charge) ne provoque pas de redémarrage, et un service réellement cassé n'est pas redémarré en boucle.
Ne jamais redémarrer automatiquement l'infrastructure stateful. Bases de données et caches sont seulement surveillés et journalisés. Un redémarrage ne corrige pas une cause réelle comme un disque plein ; il coupe les transactions de plusieurs stacks et ne fait qu'ajouter des dégâts. Dans ce cas, c'est un humain qui décide.
Un conteneur absent est enregistré comme une erreur — pour ne pas répéter le défaut principal de la version précédente.
Seuil · cooldown · politique stateful · reprise · conteneur absent : les cinq comportements ont été vérifiés pour de vrai sur un conteneur de test isolé.
Renouvellement des certificats¶
Voir une entrée cron ne suffit pas : le fait que le renouvellement s'exécute
réellement a été testé avec --dry-run, confirmant que tous les domaines se
renouvellent correctement. C'est le type de risque qui reste muet jusqu'à la date
d'expiration.
4. Couverture en sept langues¶
Ce qui a été fait¶
Toutes les pages du site ont été traduites en mongol plus les six langues officielles des Nations unies : العربية · 中文 · English · Français · Русский · Español. La traduction anglaise était auparavant partielle (accueil, introduction, couches, liste des plateformes, authentification) ; elle a été complétée et cinq langues supplémentaires ajoutées.
Décisions clés¶
Le mongol reste la source. Les six autres sont des traductions : l'original est rédigé en mongol et converti depuis là. Avec deux langues « sources », le contenu commence à diverger en silence.
Traduire page par page, non langue par langue. Convertir un même document en six langues à la fois garde la terminologie, les lignes de tableaux et la structure identiques. À l'inverse — « d'abord l'anglais pour toutes les pages » — les langues traduites plus tard courraient après un texte source déjà modifié.
La notation technique n'a pas été traduite. Domaines, noms de dépôts, code, YAML, chemins d'endpoints et noms de standards (OIDC · PKCE · RFC 3161) restent tels quels dans toutes les langues. Les traduire les rendrait impossibles à copier et à exécuter.
Les noms de fichiers ne sont pas traduits. C'est platforms/sso.ru.md, pas
платформы/sso.md. Ainsi le chemin de l'URL reste identique d'une langue à
l'autre, et les liens profonds venus d'autres dépôts continuent de fonctionner.
Le RTL arabe n'a pas été fait à la main. Material reconnaît la locale ar,
pose <html dir="rtl"> et inverse lui-même le menu et le flux du contenu. Les
blocs de code et les diagrammes ASCII restent en LTR — et c'est correct, car
commandes et URL perdent leur sens si l'on en inverse le sens.
Le slugify unicode est devenu trois fois plus important. Le
pymdownx.slugs.slugify introduit pour les titres cyrilliques tient désormais
aussi les ancres des titres arabes, chinois et russes. Avec le slugify standard,
tous les liens internes des six locales auraient cassé silencieusement.
fallback_to_default reste activé. Toutes les pages sont traduites, donc le
repli ne se déclenche jamais — mais il demeure la garantie que le site reste
complet lorsqu'une page est ajoutée et que sa traduction tarde.
Périmètre¶
Cette politique s'applique à la documentation au niveau de l'écosystème, c'est-à-dire à ce site seul. La documentation technique approfondie d'une plateforme donnée (schémas d'endpoints, référence des SDK) reste en MN + EN dans son propre dépôt : ses lecteurs sont des ingénieurs qui travaillent déjà dans ce dépôt, si bien qu'élargir la couverture rapporterait peu.
5. Consigner le passage à Nexus (2026-08-07)¶
Ce qui s'est passé¶
Le dépôt open-gerege-nexus a été créé le 2026-08-05 et, le 08-07, la plateforme
a été rebaptisée Gerege Nexus et déplacée sur nexus.gerege.mn. Deux forks
ont suivi : sso-gerege-nexus (Gerege SSO) et eduge-mn-nexus (eduge.mn).
Comme cela change le modèle de diffusion de l'écosystème, la documentation a
été mise à niveau dans les sept langues.
Décisions clés¶
Aucune page de plateforme existante n'a été supprimée. Template, Gerege Platform, SSO et Kiosk sont tous encore en production. Une nouvelle page a été ajoutée et les pages existantes portent un avertissement indiquant quel état fait foi. Supprimer une page aurait effacé la documentation d'un système en service.
La couche 3 a été scindée en deux générations. Nexus ne remplace pas la Template : les deux occupent la couche 3 en même temps. Ajouter une couche aurait vidé de son sens la règle même des couches (« ne jamais court-circuiter une couche »).
Le fournisseur OIDC propre à Nexus n'est PAS la couche 2. Nexus embarque un fournisseur OAuth2/OIDC, mais celui-ci sert les locataires et les clients tiers de ce déploiement. La voie de l'écosystème pour identifier un citoyen reste Gerege SSO. Sans le préciser, un lecteur conclurait que « Nexus a remplacé le SSO ».
Chaque domaine a été vérifié à la main. nexus.gerege.mn, eduge.mn et
geregekiosk.mn ont été confirmés en service via DNS, HTTP et leurs certificats
TLS. Deux choses en sont ressorties : geregekiosk.mn sert désormais Nexus, et
open.gerege.mn a été retiré du certificat de cet hôte, si bien que HTTPS
échoue sur une non-correspondance de nom.
Une promesse périmée a été corrigée. La page Template affirmait que l'autosync propage quotidiennement les changements en aval ; cette automatisation a été arrêtée pour toute la flotte le 2026-08-06. Une fausse promesse est pire qu'un fait manquant : un ingénieur attend qu'un correctif circule tout seul.
Deux lacunes de traduction ont été comblées. La section « Domaines de marque autonomes » de la cartographie des domaines était entièrement absente des six traductions ; les sept sont désormais alignées.
Synthèse des décisions¶
| Décision | Justification |
|---|---|
| Site statique dans son propre conteneur | Recréer l'edge fait tomber tous les domaines |
rsync, pas mv |
Un bind mount reste sur l'ancien inode |
| Slugify unicode | Le slugify standard détruit les ancres des titres cyrilliques |
Activer validation.anchors |
Sinon les liens cassés atteignent la production |
| Le vhost dans le dépôt du service | Une modification se termine dans un seul dépôt |
| Un vhost entièrement autonome | Dépendre d'un fichier partagé ôte tout sens à la séparation |
| Installer avant, retirer après | Dans l'autre sens, le domaine tombe |
| Découvrir le chemin automatiquement | Plus fiable qu'en dur ; ne laisse aucun chemin dans un dépôt open source |
Protéger par .gitignore |
git clean ignore les fichiers ignorés |
| Ne pas suivre l'override | Compose le lit automatiquement — la config de prod s'appliquerait en local |
| Probe depuis l'intérieur du conteneur | Évite un redémarrage massif quand l'edge tombe |
| Ne pas redémarrer le stateful | Un redémarrage ne corrige pas la cause, il ajoute des dégâts |
| Le mongol comme unique langue source | Avec deux « sources », le contenu diverge en silence |
| Traduire par page, non par langue | Terminologie et structure restent identiques dans six langues |
| Ne pas traduire code, domaines ni noms de dépôts | Traduits, ils deviennent impossibles à copier et exécuter |
| Ne pas traduire les noms de fichiers | Le chemin d'URL reste le même, les liens profonds fonctionnent |
Chaque langue sur un sous-chemin (/ar/) |
Avec des sous-domaines, SAN · vhost · hreflang augmenteraient d'un coup |
Volontairement non fait¶
Les domaines sso · dan · gsign · xyp n'ont pas été détachés. Leur code
réside dans le dépôt de la stack combinée : le fichier central est donc déjà
leur propre dépôt. Aucune raison de séparer.
Aucun montage distinct n'a été ajouté au conteneur edge. Cela aurait imposé de modifier le fichier compose de la stack combinée et, en plus, de recréer le conteneur — faisant tomber brièvement tous les domaines.
Aucun index de recherche mongol n'a été forcé. lunr.js ne prend pas le
mongol en charge ; la recherche dans la locale par défaut fonctionne donc avec la
tokenisation standard. Écrire un stemmer dédié coûterait plus qu'il ne rapporte
aujourd'hui.
Aucun domaine ni sous-domaine distinct par langue. Des chemins du type /ar/
et /zh/ se règlent avec un seul certificat, un seul vhost et un seul
déploiement. Passer aux sous-domaines aurait fait grossir d'un coup le SAN du
certificat, la configuration de l'edge et le hreflang.
Risque résiduel¶
Les vhosts des trois domaines et les fichiers d'override de l'hôte sont protégés
par .gitignore, mais si quelqu'un lance git clean -fdx (qui inclut les
fichiers ignorés), ils seront supprimés. Le remède est de relancer le script
d'installation du dépôt concerné — c'est noté dans le runbook de chacun des trois
dépôts.