Thème d'un ENT — détails techniques
Description et usage de l'éditeur de thème : Configuration ENT › Personnalisation.
Pour le logo et le cachet d'un établissement — qui ne passent pas par un thème : Logo et cachet d'un établissement.
Quelle configuration modifier ?
Selon que la demande concerne l’apparence de l’ENT ou l’identité d’un établissement, les réglages et les étapes diffèrent. Le tableau suivant indique la méthode à suivre pour chaque cas.
| Besoin | Levier | Redémarrage | Où |
|---|---|---|---|
| Changer les couleurs ou le logo d'un ENT existant | Éditeur de thème du dashboard | non | /admin/configuration/ent |
| Ouvrir un nouvel ENT (région, collectivité, département) | Nouveau skin + nouvel hôte | oui | cette page |
| Donner à un établissement son logo, son cachet, ses couleurs | Branding par structure | non | doc dédiée |
| Donner à un établissement un thème entièrement distinct | Hôte dédié + nouveau skin | oui | cette page, §« Cas d'un établissement » |
Le modèle ne lie pas une Structure à un thème. Tenant n'en porte pas non plus. Le thème se
résout par hôte HTTP ; le branding se résout par structure. Un établissement qui doit avoir
un thème à lui a donc besoin de son propre nom de domaine — il n'y a pas d'autre levier, et
chercher un champ « thème » sur l'établissement est une impasse.
Comment un thème est choisi à l'exécution
PortalController#getSkinFromConditions (libs/portal-mui/backend) applique, dans l'ordre :
Deux conséquences pratiques :
- La table
skins:est la seule chose qui rattache un ENT à son habillage. Elle est lue une fois, à l'initialisation du verticle du portail (initAsync), et recopiée danshostSkin. Ajouter une entrée impose donc un redémarrage — c'est la raison pour laquelle un nouveau thème ne peut pas se déployer à chaud, alors que la mise à jour d'un thème existant le peut. - La préférence utilisateur l'emporte sur l'hôte. Un compte qui a un
uac.themehérité d'un autre déploiement verra le mauvais thème, même sur le bon domaine. Le dashboard expose un diagnostic et une réinitialisation par établissement (Configuration ENT › Thème par établissement), dont l'effet n'est visible qu'à la reconnexion.
Anatomie d'un thème
Un thème vit dans le dépôt open-ent/theme-open-ent, sous overrides/<skin>/ :
overrides/<skin>/
├── css/_overridable-variables.scss # $primary, $accent, $hover — la charte
├── img/ # logo.png, logo-text.png, illustrations…
├── i18n/<App>/<langue>.json # libellés propres au déploiement
└── template/directory/ # gabarits de publipostage (massmail)
Le SCSS commun (scss/, skins/) est partagé ; build.sh -o=<skin> écrase les fichiers communs
par ceux de l'override, puis compile chaque skin (default, dyslexic) en dist/skins/<skin>/theme.css.
Le résultat n'est plus embarqué dans l'image assets : il est publié en artefact, un
tar.gz par skin, que l'ENT télécharge lui-même.
La chaîne précédente reconstruisait une image de 195 Mo pour un changement de couleur, puis faisait
kubectl set image avec un KUBE_CONFIG stocké chez GitHub : un workflow déclenchable par un ADML
détenait un accès en écriture à la production. Désormais la CI ne publie qu'une Release sur son
propre dépôt, et aucun identifiant de cluster ne sort du cluster.
Créer le thème d'un nouvel ENT
Les étapes 1 à 4 se font sans toucher à la production ; les étapes 5 à 8 sont la mise en service.
1. Créer l'override
Dans open-ent/theme-open-ent, partir de l'override le plus proche plutôt que de default — les
chartes existantes documentent ce qui se surcharge réellement :
cp -r overrides/eclat-bfc overrides/<nouveau-skin>
$EDITOR overrides/<nouveau-skin>/css/_overridable-variables.scss # $primary, $accent, $hover
Remplacer les images de img/ : au minimum logo.png (marque carrée, icône d'application) et
logo-text.png (logotype horizontal, utilisé en tête des courriers d'identifiants).
logo-text.xcf pèse jusqu'à 4,5 Mo, n'est jamais servi en HTTP et serait téléchargé par chaque
cluster à chaque publication. package-theme.sh les exclut de l'artefact (.xcf, .psd, .ai),
mais ils alourdissent quand même le dépôt.
2. Déclarer le thème dans theme-conf.js
open-ent-mods/starter/assets/theme-conf.js, servi en /assets/theme-conf.js, est ce que lisent
les ThemeProvider React :
{
parent: "theme-open-ent",
child: "<nouveau-skin>",
group: "<nouveau-skin>",
skins: ["default", "dyslexic"],
help: "/help-2d", // ou /help-1d pour un ENT premier degré
bootstrapVersion: "ode-bootstrap-neo", // ou ode-bootstrap-1d
}
Le dernier segment de bootstrapVersion devient l'attribut data-product de la balise
<html>, qui pilote la majeure partie du style des modules React.
data-product="1d" est récentBeaucoup de règles n'existaient que pour neo/one et doivent être étendues explicitement à
1d. C'est la cause de la plupart des écarts visuels sur un thème premier degré — voir
README-THEME.md du dépôt open-ent-mods.
3. Construire et inspecter en local
cd open-ent-mods
./scripts/build-theme.sh <nouveau-skin> # → starter/assets/themes/<nouveau-skin>/
./scripts/build-theme.sh <nouveau-skin> --package # → artifacts/theme-<skin>-<version>.tar.gz
--package appelle exactement le script qu'utilise la CI : ce qui sort de là est bit pour bit ce
que publierait le workflow pour la même source et la même version.
4. Publier l'artefact
Pousser l'override sur la branche par défaut de theme-open-ent (ou passer par l'éditeur de thème,
qui ouvre une PR). Le workflow theme-release.yml construit le thème et publie le tag
theme-<skin>-<version> avec deux fichiers : l'archive et sa somme .sha256.
Une release sans les deux fichiers est ignorée par l'ENT : sans le .sha256, impossible de
vérifier ce qu'on s'apprête à servir.
5. Déclarer l'hôte → thème
Dans open-ent-mods/starter/ent-core.yaml, la table skins: apparaît à trois endroits :
sharedConf, le module infra, et le module portal-mui. Les trois doivent être alignées.
skins:
<nouvel-hote>.ent-scolaire.fr: <nouveau-skin>
<nouvel-hote>.ent-scolaire.fr:443: <nouveau-skin>
:443 n'est pas décorativeLes clés de skins: alimentent aussi la liste des hôtes de confiance de Renders.getHost(). Un
hôte absent de cette liste retombe sur le premier de la table, ce qui casse silencieusement les
URL générées (retours d'authentification, liens des courriels, WOPI).
6. Router l'hôte
Ajouter l'hôte dans helm/openent-monolithe/values.yaml, section ingress.hosts :
ingress:
hosts:
- host: <nouvel-hote>.ent-scolaire.fr
Le DNS doit pointer vers le cluster, et le certificat Traefik couvrir le sous-domaine (le résolveur
ACME du cluster gère *.ent-scolaire.fr).
Sur k3sprd, l'ingress WordPress déclare *.ent-scolaire.fr et renvoie un 302 vers
wp-signup.php, qui atterrit sur l'ENT en 404 — un 404 trompeur, alors que DNS, certificat et
routage sont corrects. Vérifier en une commande :
curl -s -o /dev/null -D - https://<nouvel-hote>.ent-scolaire.fr/ | grep -iE '^HTTP|^location'
Si la location pointe vers wp-signup.php, c'est cela et rien d'autre : poser
traefik.ingress.kubernetes.io/router.priority sur l'Ingress de l'ENT.
7. Épingler la version du thème
themes:
pinned:
- { skin: <nouveau-skin>, version: "<version publiée>" }
C'est ce pin que l'init container sync-themes réinstalle à chaque démarrage : c'est lui qui rend
la production reproductible, pas ce qui se trouve sur le volume.
themes.pinned est videL'image assets n'embarque plus les skins. Un helm upgrade avec un pinned vide donnerait un ENT
sans aucun thème — toutes les feuilles de style en 404. Le garde-fou
templates/_theme-preflight.tpl bloque le rendu avec la marche à suivre. Repli tant qu'aucune
release n'existe : --set themes.enabled=false.
8. Déployer
export KUBECONFIG=~/.kube/config-k3sprd
helm upgrade ent ./helm/openent-monolithe -n ent \
--set-file entCoreConfig=starter/ent-core.yaml
Le redémarrage est nécessaire ici : la table skins: est figée à l'initialisation du verticle.
Mettre à jour un thème existant
C'est le cas courant, et il ne demande aucun redémarrage :
- Publier depuis l'éditeur de thème (Configuration ENT › Personnalisation › Publier) — ou pousser
sur
overrides/<skin>/, ce qui déclenche la même release. - L'installer depuis l'onglet Versions du thème du dashboard. L'ENT télécharge l'archive,
vérifie sa somme de contrôle, l'extrait dans
themes/.store/<skin>/<version>/et permute le lienthemes/<skin>de façon atomique. - Reporter la version dans
themes.pinned(le dashboard signale la dérive) pour qu'un pod recréé la réinstalle.
Les versions précédentes restent sur le volume (themes.keepVersions, 3 par défaut) : revenir en
arrière est immédiat, c'est une permutation de lien sans téléchargement.
Cas d'un établissement qui doit avoir son propre thème
Il n'y a pas de raccourci : c'est un ENT de plus, avec son hôte. La procédure est celle
ci-dessus, l'hôte étant dédié à cet établissement
(<etablissement>.ent-scolaire.fr). Cela entraine :
- un hôte de plus à router, à certifier et à surveiller ;
- les utilisateurs de cet établissement doivent entrer par ce domaine — un lien profond vers le domaine de la région leur servira le thème de la région ;
- un compte rattaché à plusieurs établissements n'aura qu'un seul thème à la fois, celui du domaine par lequel il est entré.
Dans la grande majorité des cas, ce n'est pas ce qu'il faut faire : un établissement qui veut « son identité » veut son logo, son cachet et ses couleurs sur ses documents — ce que couvre le branding par structure, sans hôte, sans artefact et sans redémarrage.
Vérifier
Toujours en GET : les assets de l'ENT répondent 404 en HEAD, ce qui donne un faux diagnostic.
# Le thème est bien associé à l'hôte
curl -s https://<hote>/skin
# La feuille de style du thème est servie, et à jour (200, pas 304)
curl -s -o /dev/null -D - "https://<hote>/assets/themes/<skin>/skins/default/theme.css" \
| grep -iE '^HTTP|^last-modified|^cache-control'
# Ce que le cluster sert réellement, et depuis quelle version
kubectl -n ent exec deploy/ent-openent-monolithe -c launcher -- \
sh -c 'cat /srv/launcher/assets/themes/.installed.json; ls -l /srv/launcher/assets/themes/<skin>'