Aller au contenu

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

  1. 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.
  2. 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.