Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Configurer Forgejo : courrier, LFS et inscriptions

Par mis à jour le

Améliorer cette page

Pour rendre une instance Forgejo 15 utilisable par une équipe, on ajoute à la pile installée trois réglages que l'installation laisse de côté : le courrier sortant, le serveur Git LFS (qui stocke les gros fichiers hors de l'historique Git) et la politique d'inscription. Chaque réglage s'écrit dans un petit fichier Docker Compose qui complète le compose.yaml de la leçon précédente, et chacun se prouve par un geste observable : un courrier reçu, un fichier de 3 Mo retrouvé à l'identique, un compte créé sans inscription publique. Cette leçon s'adresse à un administrateur qui vient d'installer sa forge.

Elle a été exécutée de bout en bout le 2026-10-16 sur AlmaLinux 10.2, avec Forgejo 15.0.10, Docker 29.9.1, Compose v5.6.0, git 2.52.0 et git-lfs 3.7.1. Les sorties citées viennent de cette exécution de référence : les identifiants (commits, empreintes, adresses IP) seront différents chez vous, les messages d'erreur non. Le courrier est capté par Mailpit 1.31.6, un serveur SMTP de test : rien ne quitte la machine. Deux pièges rencontrés pendant cette exécution sont expliqués en détail : un chemin de stockage LFS qui fait boucler le conteneur, et un git push LFS qui échoue alors que tout semble en place.

  • Appliquer un réglage à Forgejo par un fichier Compose de surcharge, et vérifier ce que app.ini a retenu.
  • Brancher le courrier sortant sur Mailpit et diagnostiquer un serveur d'envoi (SMTP) mal réglé, dont l'échec est silencieux.
  • Activer Git LFS avec le bon chemin de stockage, et prouver qu'un gros fichier est stocké côté serveur.
  • Choisir les réglages d'instance recommandés par la documentation de Forgejo v15 pour une instance privée.
  • Gouverner les inscriptions : fermées, comptes créés par l'administrateur, confirmation d'e-mail, adresses privées.
  • Vérifier que ces réglages survivent à un redémarrage complet de la pile.

La leçon suit cet ordre et demande une trentaine de minutes : la méthode d'application, le courrier, LFS, les réglages recommandés, les inscriptions, puis le redémarrage, le dépannage et le nettoyage. Le courrier passe avant les inscriptions, parce que créer un compte envoie un courrier d'accueil. Les réglages recommandés passent avant les comptes, parce que certains ne s'appliquent qu'aux comptes créés après eux.

Il vous faut l'instance de la leçon Installer Forgejo LTS sur PostgreSQL derrière un proxy TLS : trois conteneurs dans /opt/forgejo-lab, le nom forge.lab.test, le compte administrateur fjadmin et son mot de passe dans le fichier .env. Les commandes ci-dessous supposent que cette pile tourne et que la variable ADMIN_PASSWORD existe toujours dans .env.

Deux notions ne sont pas rappelées ici. Le SMTP est le protocole d'envoi du courrier, avec ses ports et ses modes de chiffrement : voir Protocoles email : SMTP, IMAP, POP3. Le credential helper de Git est le mécanisme qui lui fournit un identifiant : voir Stockage des credentials Git.

Comment appliquer un réglage à Forgejo dans cette pile ?

Section intitulée « Comment appliquer un réglage à Forgejo dans cette pile ? »

Chaque réglage s'écrit comme une variable FORGEJO__SECTION__CLE dans un petit fichier Compose de surcharge, que l'on ajoute à la liste COMPOSE_FILE. Un fichier de surcharge est un second fichier Compose que Compose fusionne avec le premier : il ajoute ou remplace des clés sans toucher au compose.yaml (le guide Docker Compose détaille la fusion). L'image Forgejo recopie les variables FORGEJO__... dans app.ini, le fichier de configuration de Forgejo, à chaque démarrage : une variable FORGEJO__mailer__ENABLED devient la clé ENABLED de la section [mailer]. Un point dans le nom de section est conservé : la variable FORGEJO__repository.signing__DEFAULT_TRUST_MODEL vise la section [repository.signing]. Les fichiers de surcharge évitent de grossir le compose.yaml et permettent de retirer un thème de réglages d'un seul geste. Ce format est celui de la documentation d'installation Docker.

Compose lit la variable COMPOSE_FILE dans le .env du répertoire du projet : elle liste les fichiers à fusionner, séparés par des deux-points. On part de la pile seule, puis on ajoute un fichier par thème.

La première commande supprime une éventuelle ligne COMPOSE_FILE déjà présente, pour que la leçon se rejoue sans doublon dans le .env.

Fenêtre de terminal
cd /opt/forgejo-lab
sudo sed -i '/^COMPOSE_FILE=/d' .env
echo 'COMPOSE_FILE=compose.yaml' | sudo tee -a .env >/dev/null

Après chaque ajout, on relance le service et on attend que Forgejo réponde. Juste après un redémarrage, la migration de la base n'est pas finie et les premières requêtes échouent (les journaux peuvent afficher relation "user" does not exist). La page /user/login est le bon test : elle répond 200 même quand l'accès anonyme est restreint, ce que /api/v1/version ne fera plus une fois REQUIRE_SIGNIN_VIEW activé.

Fenêtre de terminal
attendre() { for i in $(seq 1 60); do c=$(curl -sk -o /dev/null -w '%{http_code}' https://forge.lab.test/user/login); [ "$c" = 200 ] && { echo "prêt"; return; }; sleep 2; done; echo "pas prêt (code $c)"; }

La fonction attendre interroge la page toutes les 2 secondes pendant 2 minutes au plus et affiche prêt dès le premier 200. Elle n'existe que dans le terminal où vous l'avez collée : gardez ce terminal ouvert pendant toute la leçon, car les variables ATK et D de la section LFS y vivront aussi. Une dernière règle vaut pour toute la leçon : retirer une variable FORGEJO__ du fichier Compose ne retire pas la clé de app.ini. Sur cette pile, la clé reste avec sa dernière valeur. Pour revenir en arrière, on fixe donc la valeur inverse ("false"), on ne supprime pas la ligne.

Sans section [mailer], Forgejo n'envoie aucun courrier : la commande forgejo admin sendmail le dit clairement. Les mots de passe oubliés, les confirmations d'inscription et les notifications dépendent tous de ce réglage, il passe donc avant les autres. Voici la commande de contrôle, à lancer avant de rien configurer.

Fenêtre de terminal
sudo docker exec -u git forgejo forgejo admin sendmail --title "Test" --content "Courrier de test" --force

Vous devez obtenir internal API error response, status=500, err=Mail service is not enabled. C'est l'état de départ attendu. Attention à la portée de cette commande : elle écrit à tous les utilisateurs actifs de l'instance. Sur une forge en production, gardez-la pour un test avec un seul compte.

Mailpit est un serveur SMTP factice qui garde chaque message dans une interface web au lieu de le livrer. On l'ajoute à la pile comme quatrième conteneur. Son port SMTP, le 1025, reste dans le réseau Docker ; son interface et son API, sur le 8025, ne sont publiées que sur la boucle locale de la machine (127.0.0.1). L'image est épinglée par digest, comme le reste de la pile. Le guide Mailpit détaille l'outil.

Créez /opt/forgejo-lab/mailpit.yaml :

# Serveur SMTP de test : Mailpit. SMTP 1025 (réseau interne), interface et API 8025 (boucle locale).
services:
mailpit:
image: axllent/mailpit:v1.31.6@sha256:23fe39e81bde596a918000b3135c0f85dc8bb4c9ea6be274b051143f3e300387
container_name: forgejo-mailpit
restart: always
networks:
- forgejo
ports:
- "127.0.0.1:8025:8025"

Quatre clés suffisent dans la section [mailer] : l'activation, le protocole, l'adresse du serveur et son port. Le nom mailpit se résout dans le réseau Docker, comme db pour la base. La clé FROM fixe l'expéditeur, et ENABLE_NOTIFY_MAIL de la section [service] autorise les notifications de tickets et de demandes de fusion par courrier.

Créez /opt/forgejo-lab/mailer.yaml. Le port et le protocole viennent du .env avec une valeur par défaut, pour pouvoir provoquer les pannes plus bas.

# Courrier : Forgejo vers Mailpit. SMTP_PORT et SMTP_PROTOCOL viennent de .env (défauts 1025 et smtp).
services:
server:
environment:
FORGEJO__mailer__ENABLED: "true"
FORGEJO__mailer__PROTOCOL: ${SMTP_PROTOCOL:-smtp}
FORGEJO__mailer__SMTP_ADDR: mailpit
FORGEJO__mailer__SMTP_PORT: ${SMTP_PORT:-1025}
FORGEJO__mailer__FROM: forgejo@forge.lab.test
FORGEJO__service__ENABLE_NOTIFY_MAIL: "true"

On ajoute les deux fichiers à la liste, on relance et on attend.

Fenêtre de terminal
cd /opt/forgejo-lab
sudo sed -i 's#^COMPOSE_FILE=.*#COMPOSE_FILE=compose.yaml:mailpit.yaml:mailer.yaml#' .env
sudo docker compose up -d
attendre

Compose recrée le conteneur forgejo et crée forgejo-mailpit. Il affichera aussi, au démarrage de Forgejo, un avertissement connecting over insecure SMTP protocol to non-local address is not recommended : il vise le SMTP en clair, acceptable ici parce que Mailpit est dans le réseau Docker, pas sur Internet.

Deux contrôles se complètent : ce que app.ini a retenu, et ce que Mailpit a reçu. Le premier prouve que la configuration est lue, le second que le courrier circule. Relancez la commande d'envoi, puis interrogez l'API de Mailpit depuis la machine.

Fenêtre de terminal
sudo docker exec forgejo sed -n '/^\[mailer\]/,/^$/p' /data/gitea/conf/app.ini
sudo docker exec -u git forgejo forgejo admin sendmail --title "Test L3" --content "Courrier de test" --force
sleep 2
curl -s http://127.0.0.1:8025/api/v1/messages | python3 -c 'import sys,json
d=json.load(sys.stdin); print("messages:",d["total"])
for m in d["messages"]: print(" -",m["From"]["Address"],"->",[t["Address"] for t in m["To"]],"|",m["Subject"])'

La première commande doit afficher ENABLED = true, PROTOCOL = smtp, SMTP_ADDR = mailpit et SMTP_PORT = 1025, la deuxième la réponse Sent 1 email(s) to all users. Mailpit liste alors un message de forgejo@forge.lab.test vers fjadmin@example.test intitulé « Test L3 ». Vous pouvez aussi ouvrir l'interface de Mailpit sur le port 8025 de la machine.

Pourquoi un SMTP faux ne produit-il aucune erreur visible ?

Section intitulée « Pourquoi un SMTP faux ne produit-il aucune erreur visible ? »

Parce que l'envoi est asynchrone : la commande met le courrier en file et rend la main avant que Forgejo ait tenté de le livrer. Le code retour vaut 0 et le message « Sent » s'affiche, même si le serveur SMTP est injoignable. L'erreur n'apparaît que dans les journaux de Forgejo, une à trois secondes après l'envoi. Le schéma suit les deux issues du même envoi : regardez que la réponse à l'administrateur part avant l'ouverture de la session SMTP, quelle que soit l'issue.

Envoi d'un courrier par Forgejo : l'administrateur lance forgejo admin sendmail, la commande met le courrier en file et répond Sent 1 email, code retour 0. Ensuite seulement la file ouvre la session SMTP vers Mailpit. Avec le bon port et le bon protocole, Mailpit accepte le courrier ; avec un mauvais port ou protocole, la connexion échoue et l'erreur n'est visible que dans les journaux.Mailpit (SMTP1025)File d'envoide ForgejoForgejo(commande)Administrateu-ralt[Port et protocole corrects][Mauvais port ou mauvaisprotocole]forgejo adminsendmailmettre le courrier enfileSent 1 email(s), coderetour 0ouvrir la sessionSMTPcourrier accepté,visible dans Mailpitconnexion refusée ounégociation TLSimpossibleaucune réponse : l'erreur n'est que dansles journaux
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

Deux pannes provoquées sur la pile de référence le montrent. Pour la première, SMTP_PORT=1026 dans le .env puis sudo docker compose up -d server. La commande répond Sent 1 email(s) avec le code 0, et Mailpit ne reçoit rien de plus. La recherche dans les journaux donne la cause :

Fenêtre de terminal
sudo docker logs --since 5m forgejo 2>&1 | grep 'Failed to send'
[E] Failed to send emails [fjadmin@example.test]: - gomail: could not send email 1: failed to establish network connection to SMTP server: dial tcp 172.30.0.3:1026: connect: connection refused

La seconde panne est un mauvais protocole : SMTP_PROTOCOL=smtps sur le port 1025, qui parle en clair. smtps ouvre le TLS dès le premier octet, ce que Mailpit ne comprend pas, et le journal contient tls: first record does not look like a TLS handshake. Ce message n'est pas toujours visible : si votre fenêtre de journal est trop courte, il manque, alors élargissez --since. Dans les deux cas, remettez SMTP_PORT=1025 et SMTP_PROTOCOL=smtp puis relancez : un nouveau message de test, « Test retour », arrive bien dans Mailpit.

Comment activer Git LFS et où stocker les fichiers ?

Section intitulée « Comment activer Git LFS et où stocker les fichiers ? »

Git LFS (Large File Storage) garde les gros fichiers hors de l'historique Git : le dépôt ne contient qu'un petit pointeur, et le fichier lui-même vit sur le serveur LFS de Forgejo. Un pointeur est un court fichier texte qui contient l'identité du gros fichier (son empreinte et sa taille). Le serveur LFS est désactivé par défaut. On lui donne trois réglages : l'activation, un secret qui signe les jetons d'accès (des JWT, jetons signés de courte durée), et un chemin de stockage.

Voyons d'abord l'état de départ. Dans app.ini, on trouve LFS_START_SERVER = false. Un git push d'un fichier suivi par LFS échoue alors avec batch response: Repository or object not found sur l'adresse .../info/lfs/objects/batch, puis error: failed to push some refs, code retour 1. Le message parle d'un dépôt introuvable, alors que le dépôt existe : c'est le serveur LFS qui manque.

Dans cette pile, le stockage LFS doit se trouver sous /data/gitea, car seuls /data/gitea et /data/git sont inscriptibles dans le volume /data. C'est le premier piège : avec FORGEJO__lfs__PATH: /data/lfs, le conteneur s'arrête en boucle sur [F] storage.Init failed: mkdir /data/lfs: permission denied et Caddy répond 502. Le chemin valide est /data/gitea/lfs.

La clé est [lfs].PATH : la documentation v15 la donne comme remplaçante de l'ancienne [server].LFS_CONTENT_PATH, et décrit aussi un stockage compatible S3 pour un volume plus grand (Storage settings, non testé ici). Le secret se génère avec Forgejo lui-même et se range dans le .env.

Fenêtre de terminal
cd /opt/forgejo-lab
sudo sed -i '/^LFS_JWT_SECRET=/d' .env
echo "LFS_JWT_SECRET=$(sudo docker exec -u git forgejo forgejo generate secret LFS_JWT_SECRET)" | sudo tee -a .env >/dev/null

Créez /opt/forgejo-lab/lfs.yaml, qui lit le secret dans le .env :

# Git LFS : serveur LFS intégré activé, secret JWT généré à l'exécution (.env), stockage explicite dans le volume /data.
services:
server:
environment:
FORGEJO__server__LFS_START_SERVER: "true"
FORGEJO__server__LFS_JWT_SECRET: ${LFS_JWT_SECRET}
FORGEJO__lfs__PATH: /data/gitea/lfs

Ajoutez ce fichier à la liste, relancez le service et contrôlez la configuration retenue.

Fenêtre de terminal
sudo sed -i 's#^COMPOSE_FILE=.*#&:lfs.yaml#' .env
sudo docker compose up -d server
attendre
sudo docker exec forgejo grep -E 'LFS_START_SERVER|^\[lfs\]|^PATH = /data/gitea/lfs' /data/gitea/conf/app.ini

La sortie attendue contient LFS_START_SERVER = true, la section [lfs] et PATH = /data/gitea/lfs. Le serveur redémarre sans boucle.

Comment prouver qu'un gros fichier passe par LFS ?

Section intitulée « Comment prouver qu'un gros fichier passe par LFS ? »

Un push LFS réussi se prouve en quatre points : le pointeur dans le dépôt, le fichier dans le volume du serveur, le téléchargement par l'API, et un clone neuf qui retrouve le fichier à l'identique. Il faut d'abord le client : git-lfs (paquet git-lfs d'AlmaLinux, installé par sudo dnf install -y git-lfs ; Ubuntu n'a pas été testé).

Le piège de l'authentification mérite une explication. Dans la leçon précédente, on passait le jeton à git par -c http.extraHeader=.... Avec git-lfs 3.7.1, cet en-tête n'a pas été repris : le git push envoie le commit, puis git-lfs interroge le serveur sans identifiant et reçoit batch response: Authentication required: Unauthorized. C'est un constat sur cette version : la documentation de git-lfs ne décrit pas cette clé. La parade est de donner le jeton par un credential helper (store, voir git-credential-store), comme le ferait un vrai utilisateur. Les commandes suivantes isolent tout dans un répertoire personnel temporaire pour ne pas toucher au vôtre.

Fenêtre de terminal
D=forge.lab.test
cd /opt/forgejo-lab
ATK=$(sudo docker exec -u git forgejo forgejo admin user generate-access-token --username fjadmin --token-name "lfs-$$" --scopes all --raw)
curl -sk -H "Authorization: token $ATK" -H 'Content-Type: application/json' \
-X POST https://$D/api/v1/user/repos -d '{"name":"lfsdemo","auto_init":true,"default_branch":"main"}'
export HOME=$(mktemp -d); cd "$HOME"
sudo docker cp forgejo-proxy:/data/caddy/pki/authorities/local/root.crt "$HOME/root.crt"
sudo chown "$USER" "$HOME/root.crt"
export GIT_SSL_CAINFO="$HOME/root.crt" GIT_TERMINAL_PROMPT=0
git config --global user.email a@example.test; git config --global user.name a
git config --global credential.helper store
install -m 600 /dev/null "$HOME/.git-credentials"
printf 'https://fjadmin:%s@%s\n' "$ATK" "$D" > "$HOME/.git-credentials"
git lfs install

Le fichier .git-credentials est en mode 600 et le jeton reste dans une variable : rien n'est écrit en clair dans la page ni dans un script versionné. GIT_SSL_CAINFO désigne la CA locale de Caddy, comme dans l'installation. On suit ensuite un fichier binaire de 3 Mo et on le pousse.

Fenêtre de terminal
git clone -q https://$D/fjadmin/lfsdemo.git w && cd w
git lfs track '*.bin'
head -c 3000000 /dev/urandom > big.bin
git add .
git commit -qm "fichier binaire via LFS"
git push origin main

Le git push doit se terminer par une ligne du type df84ea7..8fb6a55 main -> main avec le code 0, accompagnée d'un message sans gravité, « Locking support detected on remote origin ». Les identifiants de commit et d'oid (l'empreinte SHA-256 du contenu, qui identifie l'objet LFS) changent chez vous, puisque le fichier est aléatoire. Les contrôles suivants se lisent un par un.

Fenêtre de terminal
git lfs ls-files
git cat-file -p HEAD:big.bin
sudo docker exec forgejo find /data/gitea/lfs -type f
sudo docker exec forgejo du -sh /data/gitea/lfs
curl -sk -o /dev/null -H "Authorization: token $ATK" -w 'code=%{http_code} size=%{size_download}\n' \
"https://$D/api/v1/repos/fjadmin/lfsdemo/media/big.bin?ref=main"
git clone -q https://$D/fjadmin/lfsdemo.git ../c2 && ls -l ../c2/big.bin | awk '{print $5}'

Voici ce que vous devez observer. git lfs ls-files liste ab4d7ea5ed * big.bin (les dix premiers caractères de l'oid). Le dépôt Git contient seulement le pointeur : version https://git-lfs.github.com/spec/v1, oid sha256:ab4d7ea5ed98... et size 3000000. Côté serveur, le fichier est rangé sous /data/gitea/lfs/ab/4d/7ea5ed98..., le chemin dérivé de l'oid, pour 2,9 Mo. L'API rend code=200 size=3000000 et la somme SHA-256 du téléchargement est identique à celle du fichier d'origine. Le clone neuf donne un big.bin de 3000000 octets, de même empreinte.

Pour une instance privée d'équipe, six réglages valent d'être posés dès le début : trois viennent de la feuille de configuration de Forgejo, trois de la page « Recommended Settings and Tips » de sa documentation v15. Le tableau distingue l'origine de chacun et ce qui a été vérifié. Dans la colonne « Joué », « oui » signifie que l'effet a été constaté, « appliqué » que la clé figure bien dans app.ini sans que son effet ait été vérifié. Les clés service sont décrites dans la feuille de configuration.

RéglageValeurEffetOrigineJoué
[service].REGISTER_EMAIL_CONFIRMtrueconfirmation par courrier à l'inscriptionfeuille de configurationoui
[service].DEFAULT_KEEP_EMAIL_PRIVATEtrueadresse masquée par défaut pour les nouveaux comptesfeuille de configurationoui
[service].REQUIRE_SIGNIN_VIEWtruetout le contenu exige une connexionfeuille de configurationoui
[cache].ADAPTER et HOSTtwoqueue et {"size":100, ...}cache à taille limitée pour une petite instancerecommandations v15appliqué
[repository.signing].DEFAULT_TRUST_MODELcommitterun commit signé par un non-collaborateur s'affiche vérifiérecommandations v15appliqué
[service].USERNAME_COOLDOWN_PERIOD7délai avant réattribution d'un ancien nomrecommandations v15appliqué

Trois réserves sur ce tableau. La documentation recommande USERNAME_COOLDOWN_PERIOD et le captcha ([service].ENABLE_CAPTCHA) pour une instance à inscription ouverte. Le captcha ne protège que le formulaire d'inscription et n'a pas été testé. Le délai de réattribution vise les noms libérés par un renommage : il peut rester utile sur une forge fermée, mais seule sa présence dans app.ini a été vérifiée, pas son effet.

La même page recommande aussi [security].LOGIN_REMEMBER_DAYS à 365 et [ui].ONLY_SHOW_RELEVANT_REPOS pour une forte activité : ils n'ont pas été testés non plus. Enfin, pour la base de données, la page préfère postgres ou mysql à partir d'une forte activité, ce que l'installation a déjà choisi.

Créez /opt/forgejo-lab/service.yaml, ajoutez-le à la liste et relancez.

# Réglages d'instance privée d'équipe (feuille de configuration [service] et recommandations v15).
services:
server:
environment:
FORGEJO__service__REGISTER_EMAIL_CONFIRM: "true"
FORGEJO__service__DEFAULT_KEEP_EMAIL_PRIVATE: "true"
FORGEJO__service__REQUIRE_SIGNIN_VIEW: "true"
FORGEJO__service__USERNAME_COOLDOWN_PERIOD: "7"
FORGEJO__cache__ADAPTER: twoqueue
FORGEJO__cache__HOST: '{"size":100, "recent_ratio":0.25, "ghost_ratio":0.5}'
FORGEJO__repository.signing__DEFAULT_TRUST_MODEL: committer
Fenêtre de terminal
cd /opt/forgejo-lab
sudo sed -i 's#^COMPOSE_FILE=.*#&:service.yaml#' .env
sudo docker compose up -d server
attendre

Que change REQUIRE_SIGNIN_VIEW pour un visiteur anonyme ?

Section intitulée « Que change REQUIRE_SIGNIN_VIEW pour un visiteur anonyme ? »

Un visiteur non connecté ne voit plus rien : l'API répond 403 et les pages redirigent vers la connexion. Trois requêtes anonymes le vérifient.

Fenêtre de terminal
curl -sk -o /dev/null -w 'API repos/search anonyme : %{http_code}\n' https://forge.lab.test/api/v1/repos/search
curl -sk -o /dev/null -w 'explore anonyme : %{http_code} -> %{redirect_url}\n' https://forge.lab.test/explore/repos
curl -sk -o /dev/null -w 'API version anonyme : %{http_code}\n' https://forge.lab.test/api/v1/version

Vous devez lire 403 pour la recherche, 303 vers https://forge.lab.test/user/login pour la page d'exploration, et 403 aussi pour /api/v1/version. C'est le piège : le contrôle de l'installation, qui interrogeait cette route sans jeton, prend désormais la forge pour malade alors qu'elle répond. Testez /user/login, ou passez un jeton.

Sur une forge d'équipe, on ferme l'inscription publique, c'est l'administrateur qui crée les comptes, et la création envoie le courrier d'accueil. La clé DISABLE_REGISTRATION = true figure déjà dans le compose.yaml de l'installation. Il reste à savoir inviter quelqu'un sans rouvrir l'inscription, ce qui suppose que le courrier fonctionne : d'où le courrier en premier dans cette leçon.

Un « compte d'invitation » est simplement un compte créé par l'administrateur avec send_notify à vrai, qui déclenche le courrier d'accueil, et must_change_password à vrai, qui force le changement du mot de passe provisoire à la première connexion. Il se crée par l'API avec le jeton d'administration, le mot de passe provisoire étant tiré au hasard. La commande réutilise les variables ATK (le jeton) et D (le nom de la forge) de la section LFS : si votre terminal les a perdues, recréez-les avec les deux premières commandes du bloc de cette section.

Fenêtre de terminal
curl -sk -H "Authorization: token $ATK" -H 'Content-Type: application/json' -X POST https://$D/api/v1/admin/users \
-d "{\"username\":\"invite1\",\"email\":\"invite1@example.test\",\"password\":\"$(openssl rand -hex 12)\",\"must_change_password\":true,\"send_notify\":true}"

Vous devez obtenir un compte invite1 et, dans Mailpit, un courrier de forgejo@forge.lab.test vers invite1@example.test dont l'objet commence par « Welcome to Forgejo ». Le mot de passe provisoire n'est pas dans ce courrier : transmettez-le par un autre canal.

Pourquoi l'adresse privée ne change-t-elle pas pour les comptes existants ?

Section intitulée « Pourquoi l'adresse privée ne change-t-elle pas pour les comptes existants ? »

Parce que DEFAULT_KEEP_EMAIL_PRIVATE fixe la valeur initiale d'un compte à sa création : il ne modifie jamais un compte existant. Pour le contrôler, interrogez PostgreSQL, qui liste les comptes et leur réglage.

Fenêtre de terminal
sudo docker exec forgejo-db psql -U forgejo -d forgejo -c 'select name, keep_email_private, must_change_password from "user" order by id'

La requête montre que invite1, créé après le réglage, a keep_email_private = t, alors que fjadmin, créé avant, garde f. Pour masquer l'adresse d'un compte existant, il faut agir sur ce compte, dans ses réglages de profil.

La confirmation d'e-mail vise l'inscription : elle oblige le nouvel inscrit à cliquer un lien reçu par courrier avant d'utiliser son compte. Elle se règle par FORGEJO__service__REGISTER_EMAIL_CONFIRM: "true", déjà posé dans le fichier service.yaml, et la feuille de configuration précise qu'elle exige le courrier activé. Sur une instance dont l'inscription est fermée, elle n'a pas d'effet visible : invite1, créé par l'administrateur après ce réglage, n'a reçu que le courrier d'accueil, sans demande d'activation.

Pour l'éprouver, il faut rouvrir temporairement l'inscription par un fichier de surcharge, à retirer ensuite. Il remet DISABLE_REGISTRATION à "false".

# Temporaire : rouvre l'inscription pour prouver la confirmation d'e-mail.
services:
server:
environment:
FORGEJO__service__DISABLE_REGISTRATION: "false"

Enregistrez-le sous /opt/forgejo-lab/reg-test.yaml, ajoutez-le à la liste COMPOSE_FILE et relancez le service.

Fenêtre de terminal
cd /opt/forgejo-lab
sudo sed -i 's#^COMPOSE_FILE=.*#&:reg-test.yaml#' .env
sudo docker compose up -d server
attendre

Une inscription (celle du compte reg1 sur l'instance de référence, postée avec curl ; dans un navigateur, le geste est l'inscription ordinaire) affiche alors la page « Activate your account », et Mailpit reçoit « Please activate your account ». Il reste à refermer l'inscription : retirez le fichier de la liste et relancez.

Fenêtre de terminal
sudo sed -i 's#:reg-test.yaml##' .env
sudo docker compose up -d server
attendre

Retirer ce fichier de COMPOSE_FILE ne referme pas l'inscription par lui-même, d'après la règle vue plus haut : c'est la valeur "true" du compose.yaml, réappliquée au démarrage, qui l'a refermée sur la pile de référence. Gardez donc la vérification finale de l'inscription fermée après cet essai : la section suivante la fait.

Les réglages survivent-ils à un redémarrage complet ?

Section intitulée « Les réglages survivent-ils à un redémarrage complet ? »

Oui : un docker compose down suivi d'un up -d conserve toutes les valeurs, car elles viennent des fichiers Compose et du volume /data. Sans l'option -v, les volumes restent, donc la base, les dépôts et le stockage LFS aussi. Le contrôle final tient en un redémarrage, une lecture d'app.ini et un envoi de courrier.

Fenêtre de terminal
cd /opt/forgejo-lab
sudo docker compose down && sudo docker compose up -d
attendre
sudo docker exec forgejo grep -E '^(DISABLE_REGISTRATION|REGISTER_EMAIL_CONFIRM|DEFAULT_KEEP_EMAIL_PRIVATE|REQUIRE_SIGNIN_VIEW|LFS_START_SERVER|ENABLED|PROTOCOL|SMTP_ADDR|SMTP_PORT)[ =]' /data/gitea/conf/app.ini
sudo docker exec -u git forgejo forgejo admin sendmail --title "Après redémarrage" --content ok --force

Vous devez retrouver DISABLE_REGISTRATION = true, REGISTER_EMAIL_CONFIRM = true, DEFAULT_KEEP_EMAIL_PRIVATE = true, REQUIRE_SIGNIN_VIEW = true, LFS_START_SERVER = true et toute la section [mailer], avec trois clés secrètes présentes (leurs valeurs ne s'affichent pas). Le courrier envoyé après redémarrage arrive dans Mailpit pour les deux comptes actifs, fjadmin et invite1.

Chaque panne de cette leçon laisse une trace précise ; le tableau relie la trace à la cause et à la correction. Pour tout problème de courrier, commencez par les journaux (sudo docker logs --since 5m forgejo 2>&1 | grep 'Failed to send'), pas par la commande d'envoi, dont le code retour ne prouve rien.

SymptômeCauseCorrection
sendmail répond Mail service is not enabledaucune section [mailer]ajouter mailer.yaml et relancer le service
Sent 1 email(s), code 0, mais Mailpit est vide ; journal dial tcp ...:1026: connect: connection refusedSMTP_PORT ne correspond pas au port d'écoute du serveur SMTPcorriger SMTP_PORT (1025 pour Mailpit) et relancer
journal tls: first record does not look like a TLS handshakePROTOCOL=smtps vers un port en clairPROTOCOL=smtp pour Mailpit ; smtps seulement vers un port TLS (465)
le conteneur forgejo boucle, Caddy répond 502, journal mkdir /data/lfs: permission deniedFORGEJO__lfs__PATH hors de /data/giteaFORGEJO__lfs__PATH: /data/gitea/lfs
git push : Repository or object not found sur info/lfs/objects/batchLFS_START_SERVER à falseactiver lfs.yaml et relancer
git push : batch response: Authentication required: Unauthorizedgit-lfs 3.7.1 n'a pas repris http.extraHeader passé par git -ccredential.helper store et un .git-credentials en mode 600
/api/v1/version répond 403 sans jetonREQUIRE_SIGNIN_VIEW est actif, comportement normaltester /user/login ou passer un jeton
une variable FORGEJO__ retirée, la clé reste dans app.inil'image n'écrit que les variables présentes, elle ne supprime rienfixer la valeur inverse plutôt que supprimer la ligne

Pour défaire un réglage, fixez sa valeur inverse puis retirez le fichier de surcharge de COMPOSE_FILE ; pour tout défaire, détruisez la pile. La règle des clés persistantes explique le premier geste : retirer le fichier seul laisse la clé dans app.ini. Le nettoyage complet retire les conteneurs, les volumes (dépôts de test compris), les fichiers de /opt/forgejo-lab et l'entrée /etc/hosts.

Fenêtre de terminal
cd /opt/forgejo-lab && sudo docker compose down -v --remove-orphans
sudo docker ps -a --format '{{.Names}}'; sudo docker volume ls -q
cd / && sudo find /opt/forgejo-lab -delete
sudo sed -i '/forge.lab.test/d' /etc/hosts

L'option -v détruit aussi les volumes : ne lancez ce bloc que sur le lab. Si vous poursuivez la formation sur la même instance, gardez la pile en marche, mais pensez à deux restes de la section LFS : le répertoire temporaire créé par mktemp -d contient un .git-credentials avec votre jeton (supprimez-le), et ce jeton lfs-... reste valide tant que vous ne le révoquez pas dans les réglages du compte fjadmin, rubrique « Applications ».

  • Dans cette pile, un réglage Forgejo est une variable FORGEJO__SECTION__CLE dans un fichier Compose de surcharge, listé dans COMPOSE_FILE du .env.
  • Retirer une variable FORGEJO__ ne retire pas la clé de app.ini : pour revenir en arrière, on fixe la valeur inverse.
  • Sans [mailer], forgejo admin sendmail répond Mail service is not enabled ; avec Mailpit, les courriers sont captés sans rien envoyer.
  • L'envoi de courrier est asynchrone : un code retour 0 et « Sent » ne prouvent rien, l'erreur d'un mauvais port ou protocole n'est que dans les journaux.
  • Le stockage LFS se place sous /data/gitea (/data/gitea/lfs) : /data/lfs fait boucler le conteneur sur permission denied.
  • git-lfs 3.7.1 n'a pas repris http.extraHeader : on l'authentifie par un credential helper, et on prouve le push par le pointeur, le fichier côté serveur et un clone neuf.
  • REQUIRE_SIGNIN_VIEW rend l'API anonyme 403 y compris sur /api/v1/version : le contrôle de santé doit viser /user/login.
  • DISABLE_REGISTRATION ferme l'inscription, l'administrateur crée les comptes avec send_notify, et DEFAULT_KEEP_EMAIL_PRIVATE ne vaut que pour les comptes créés après.

Six questions tirées sur huit : le courrier asynchrone et ce qu'il cache, le chemin du stockage LFS, l'authentification de git-lfs, les inscriptions fermées et les réglages qui ne valent que pour les comptes à venir.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn