8.5 KiB
Comptes, partage et modération
Trois fonctionnalités s'activent indépendamment. Aucune n'est obligatoire : sans base de données, sans OIDC et sans jeton Gitea, Enclume reste l'éditeur qui génère du CLAPI. C'est ce qui permet à n'importe qui de l'auto-héberger sans rien configurer.
| Fonction | Ce qu'il faut | Sans ça |
|---|---|---|
| Partage par lien | ENCLUME_DATABASE_URL |
bouton absent |
| Comptes et projets enregistrés | base + OIDC | site utilisable, sans connexion |
| Soumission de packs | base + OIDC | contributions par pull request uniquement |
| Publication des packs acceptés | jeton Gitea | modération possible, publication non |
/health annonce l'état réel de chacune.
Authentik
Un seul fournisseur est déclaré côté Enclume. C'est Authentik qui fédère GitHub, Google ou tout autre fournisseur social : en ajouter un plus tard ne demande aucun redéploiement.
Créer le fournisseur — Applications → Fournisseurs → Créer → OAuth2/OpenID.
- Type de client : Confidentiel
- URI de redirection, en correspondance stricte :
https://<domaine>/connexion/retour - Portées :
openid,email,profile - Noter l'identifiant client et le secret
Créer l'application — Applications → Applications → Créer. Le slug compte : c'est lui qui apparaît dans l'URL de découverte.
ENCLUME_OIDC_METADATA=https://authentik.<domaine>/application/o/<slug>/.well-known/openid-configuration
ENCLUME_OIDC_CLIENT_ID=...
ENCLUME_OIDC_CLIENT_SECRET=...
En cas de « Redirect URI Error »
Authentik compare au caractère près l'URI reçue à celle déclarée. Demandez à l'application ce qu'elle envoie :
curl -s https://<domaine>/health | python3 -m json.tool | grep uri_de_retour
La valeur renvoyée est exactement celle à déclarer dans le fournisseur, champ « URIs de redirection », en correspondance Stricte. Attention à ne pas la saisir dans « URI de déconnexion », qui est un champ voisin et sans rapport.
La page d'erreur porte aussi dans son adresse le paramètre redirect_uri= : c'est la même
information, vue depuis le navigateur.
- Une barre oblique finale, un
httpau lieu dehttps, un sous-domaine différent : tout écart compte. - Si l'URI reçue est en
http://ou sur un nom d'hôte interne, c'est que les en-têtes du proxy ne sont pas honorés. Vérifier queENCLUME_URL_PUBLIQUEest bien définie dans le compose : elle fait autorité et supprime toute ambiguïté.
Le groupe de modération. Enclume lit la revendication groups du jeton. Depuis
Authentik 2026.8, les correspondances de portée par défaut l'exposent déjà pour certains
fournisseurs ; si ce n'est pas le cas chez vous, créer une correspondance de portée
(Personnalisation → Property Mappings → Scope Mapping), nom de portée groups :
return {"groups": [group.name for group in request.user.groups.all()]}
La relation request.user.ak_groups utilisée dans les exemples plus anciens est dépréciée
depuis la 2026.8 et déclenche un avertissement de configuration.
Rattacher cette portée au fournisseur, puis créer le groupe de modération et s'y inscrire.
Le nom du groupe se règle par ENCLUME_ADMIN_GROUPE, il n'a pas à s'appeler
enclume-admins.
Le temps de mettre ça en place, [email protected] donne l'accès
à la modération sur la seule foi de l'adresse. À vider ensuite.
Qui peut obtenir un compte
Par défaut, ENCLUME_INSCRIPTION_OUVERTE=0 : le site n'affiche aucun bouton de connexion
public, mais un bouton « Contribuer » qui explique que l'éditeur fonctionne sans compte et
que les packs se proposent par demande de fusion. Un lien discret « Se connecter (équipe) »
reste disponible dans cette fenêtre pour les mainteneurs.
Ce réglage existe parce que promettre une connexion à quelqu'un qui ne peut pas obtenir de compte — annuaire sans source externe, inscription fermée — est une impasse silencieuse.
Passez-le à 1 une fois les sources et le flux d'enrôlement en place, ci-dessous.
Ouvrir le site à d'autres que vous
Si Enclume doit accueillir des visiteurs extérieurs, deux points sont à traiter côté Authentik, et aucun n'est automatique :
- Des sources externes. GitHub, Google ou autre, déclarées en tant que sources OAuth. Sans elles, seuls les comptes de votre annuaire peuvent se connecter.
- Un flux d'enrôlement rattaché à ces sources. C'est lui qui crée le compte local à la première connexion. Beaucoup d'installations suppriment le flux d'enrôlement par défaut, précisément parce qu'il ouvre l'auto-inscription : il faut alors en créer un dédié, lié aux sources et non joignable directement par URL.
- Ne pas cloisonner l'application par groupe. Une liaison de groupe sur l'application Enclume interdirait la connexion à tout visiteur qui n'en est pas membre.
Vérifiez aussi ce que votre flux d'authentification impose : une validation MFA obligatoire a du sens pour vos comptes internes, beaucoup moins pour un visiteur qui veut seulement enregistrer un projet.
Rien de tout cela n'est nécessaire si le site reste à usage interne : la connexion demeure facultative, et un visiteur non connecté conserve l'éditeur, la génération et le partage.
Le jeton Gitea
Un jeton d'accès personnel sur le compte qui ouvrira les demandes de fusion, avec la portée
write:repository sur le dépôt du catalogue. Publier un pack accepté crée une branche, y
dépose le fichier YAML et ouvre une pull request — jamais un push sur la branche
principale. Tu relis dans Gitea avant de fusionner.
Si la publication est refusée
Le dépôt du catalogue fait foi : publier crée un fichier, et Gitea refuse d'en créer un qui existe déjà. Un pack proposé sous un identifiant déjà présent doit donc être refusé, avec pour motif la mise à jour du pack existant — qui passe par une pull request ordinaire, pas par la modération.
Si la publication échoue en 403
Une protection placée devant Gitea — Cloudflare et son contrôle d'intégrité du navigateur,
par exemple — rejette les clients qui ne sont pas des navigateurs. Le symptôme est un
HTTP 403 : error code: 1010, et la requête n'atteint jamais Gitea.
La sortie consiste à joindre Gitea directement, sans passer par la protection :
extra_hosts:
- "gitea.exemple.com:192.168.1.10"
Le nom d'hôte est inchangé, donc le certificat reste valide ; seul le chemin réseau change.
Alternative : pointer ENCLUME_GITEA_URL sur une adresse interne, au prix d'un certificat
qui ne correspondra plus.
Ce qui n'est jamais stocké
Les macros marquées « mot de passe » sont vidées avant toute écriture en base : partage, projet enregistré, soumission. Un site public n'a aucune raison de détenir le mot de passe MySQL de quelqu'un. L'avertissement affiché au partage le rappelle à l'utilisateur.
La connexion a la base
Le compose passe l'hôte, le port, la base, l'utilisateur et le mot de passe séparément,
et l'application assemble l'URL en encodant ce qui doit l'être. Un mot de passe contenant
@, :, / ou # ne pose donc aucun problème — alors qu'écrit directement dans une URL,
il la disloquerait silencieusement.
ENCLUME_DATABASE_URL reste accepté et prend le pas, pour pointer une base externe.
Migrations
Le conteneur web exécute alembic upgrade head à son démarrage, puis lance gunicorn. Un
échec de migration arrête le conteneur : une base à moitié migrée derrière une application
qui répond serait pire qu'une indisponibilité visible.
Règle d'écriture des migrations : on ajoute, on ne retire jamais dans la même version que le code qui cesse d'utiliser une colonne. La suppression arrive une version plus tard. Sans cette discipline, revenir à l'image précédente casse l'application — et tout l'intérêt des tags immuables disparaît.
Sauvegarde avant une montée de version qui touche au schéma :
docker compose exec -T db pg_dump -U enclume enclume | zstd > enclume-$(date +%F).sql.zst
Les limites en place
| Réglage | Défaut | Rôle |
|---|---|---|
ENCLUME_PARTAGE_JOURS |
90 | expiration des liens |
ENCLUME_PROJETS_PAR_COMPTE |
50 | projets enregistrés par compte |
ENCLUME_SOUMISSIONS_PAR_JOUR |
10 | soumissions par compte et par jour |
ENCLUME_TAILLE_MAX_PACK |
256 ko | taille d'un YAML soumis |
ENCLUME_TAILLE_MAX_PROJET |
2 Mo | taille d'un projet |
Les identifiants de partage font 12 caractères tirés au hasard, soit 72 bits : ils ne s'énumèrent pas. Les liens expirés sont purgés à chaque nouveau partage.