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

Superviser et dépanner Forgejo : journaux et métriques

Par mis à jour le

Améliorer cette page

Pour superviser Forgejo 15 LTS, on active l'endpoint /metrics protégé par un jeton, on le fait scraper (interroger à intervalle fixe) par Prometheus (le serveur qui collecte et stocke ces mesures), on écrit deux règles d'alerte (up == 0 et gitea_users == 0) et, quand une alerte tombe, on remonte à la cause par le journal du conteneur. Le fait qui change la manière de superviser : quand la base de données s'arrête, l'endpoint répond toujours 200 et la série up reste à 1. La leçon s'adresse à l'administrateur dont la forge tourne déjà et qui veut être prévenu avant ses utilisateurs.

Vous repartez avec cinq preuves : un niveau debug ajouté puis retiré à chaud, un endpoint de métriques qui refuse les requêtes sans jeton, une alerte relevée en train de passer d'inactive à pending puis firing, une panne aveugle (base arrêtée) rattrapée par une seconde règle, et deux pannes diagnostiquées par leur journal. Les commandes ont été exécutées le 2026-10-16 sur la pile de la leçon Installer Forgejo LTS (Forgejo 15.0.10, PostgreSQL 17.11, Caddy 2.11.7), avec Prometheus 3.15.0 épinglé par son digest.

  • Retrouver où Forgejo écrit ses journaux, activer un fichier et un journal d'accès, et monter le niveau en debug sans redémarrer.
  • Activer /metrics, le protéger par un jeton et lire ce qu'il expose, y compris ce qu'il n'expose pas.
  • Configurer Prometheus pour scraper Forgejo avec un jeton lu dans un fichier.
  • Rédiger une règle d'alerte et observer ses trois états.
  • Comprendre pourquoi up == 0 ne voit pas une base arrêtée, et quelle règle la voit.
  • Diagnostiquer une panne par la méthode symptôme, journal, cause, réparation, vérification.

Il vous faut la forge des leçons précédentes : Forgejo 15 LTS sur Docker Compose dans /opt/forgejo-lab, avec PostgreSQL et Caddy (installation). Les notions de fichier de surcharge et de variables FORGEJO__section__CLE viennent de Maintenance courante, la montée de version et ses critères de Mettre à jour Forgejo, la restauration de Sauvegarder et restaurer Forgejo.

Vous devez savoir lancer docker compose et docker logs, lire un code HTTP (401, 424, 502) et du JSON. Les concepts de Prometheus ne sont pas redits ici : ils sont dans Prometheus : monitoring et types de métriques et dans Configuration de Prometheus. Rappel en trois lignes : Prometheus scrape périodiquement des URL de métriques et range chaque valeur dans une série ; une règle d'alerte est une expression PromQL (son langage de requête) évaluée en continu. Cette leçon montre ce qu'il faut en faire pour Forgejo.

Dans cette pile, le service Compose server tourne dans le conteneur forgejo et le service db (PostgreSQL) dans le conteneur forgejo-db. docker compose prend le nom du service, docker logs, docker exec et docker stop celui du conteneur, et Prometheus ne voit que le nom du service sur le réseau Docker (server, db).

Par défaut, Forgejo écrit tous ses journaux sur la sortie standard du conteneur : on les lit avec docker logs forgejo. Dans cette installation, [log] MODE = console et LEVEL = info, et le dossier ROOT_PATH = /data/gitea/log est vide. Chaque ligne a la forme 2026/10/16 11:51:33 chemin.go:ligne:fonction() [I] message, et le niveau se lit entre crochets : [T] trace, [D] debug, [I] info, [W] warning, [E] erreur, [F] fatal.

Le journal du routeur (une ligne par requête HTTP traitée) est actif par défaut au niveau info : router: completed GET /metrics for 172.30.0.4:39218, 200 OK in 14.6ms @ web/metrics.go:16(web.Metrics). Le piège vient de la supervision elle-même : Prometheus, installé plus bas, scrape Forgejo toutes les 5 secondes dans le lab, donc chaque scrape ajoute une ligne. Filtrez ce bruit pour lire le reste (le filtre ne montre que les lignes qui ne contiennent pas GET /metrics) :

Fenêtre de terminal
docker logs forgejo 2>&1 | grep -v "GET /metrics"

Une autre limite se règle ailleurs que dans Forgejo : le pilote Docker json-file de ce conteneur n'a aucune rotation configurée (LogConfig.Config est vide ; la documentation Docker indique que max-size vaut -1, soit illimité, par défaut). Sur une instance qui vit des mois, le journal du conteneur grossit sans borne. La rotation se règle au niveau du démon Docker ou du service, à traiter avant la mise en production.

Comment activer le fichier et le journal d'accès ?

Section intitulée « Comment activer le fichier et le journal d'accès ? »

Pour écrire aussi dans un fichier, on passe FORGEJO__log__MODE à console,file ; pour un journal d'accès au format Apache, on règle FORGEJO__log__LOGGER_ACCESS_MODE à file. On ajoute les deux variables au service server du compose.yaml (ou d'un fichier de surcharge, comme dans la leçon de maintenance), puis on recrée le conteneur.

FORGEJO__log__MODE: console,file
FORGEJO__log__LOGGER_ACCESS_MODE: file
Fenêtre de terminal
docker compose up -d server
docker exec forgejo ls /data/gitea/log

La commande doit lister gitea.log et access.log. Le journal principal s'appelle bien gitea.log : le nom n'a pas changé en 15.0.10 et il n'y a pas de forgejo.log. La documentation 15 donne gitea.log par défaut, mais celle de la branche la plus récente annonce forgejo.log : ce nom dépend de la version, vérifiez-le avant une montée de version. Le journal d'accès est écrit dans access.log, avec des lignes comme 172.30.0.1 - - [16/Oct/2026:11:53:35 +0000] "GET /inexistant HTTP/1.1" 404 11 "" "curl/8.5.0".

L'ancienne option ENABLE_ACCESS_LOG est dépréciée et ne crée rien : si vous l'essayez, le journal affiche [E] Deprecated config option [log] ENABLE_ACCESS_LOG present. Use [log] LOGGER_ACCESS_MODE instead. Aucune des rotations évoquées dans cette section n'a été testée : ni celle du démon Docker vue plus haut, ni celle des fichiers (ROTATE, MAX_SIZE).

Un piège de persistance rend ce message tenace : les variables FORGEJO__* sont écrites dans app.ini au démarrage et y restent quand on les retire du compose. La clé dépréciée a donc continué d'être signalée jusqu'à sa suppression à la main, avec la commande suivante.

Fenêtre de terminal
docker exec forgejo sed -i '/^ENABLE_ACCESS_LOG/d' /data/gitea/conf/app.ini
docker restart forgejo

Après cette commande et le redémarrage, la ligne [E] Deprecated config option ne revient plus dans docker logs forgejo. Un message deprecated isolé est resté une fois dans le journal sans que son origine soit identifiée : un reste d'avant le nettoyage, à surveiller plutôt qu'à chercher.

La commande forgejo manager logging add file ajoute un écrivain de journal à chaud, au niveau debug, et forgejo manager logging remove le retire : aucun redémarrage, aucun changement d'app.ini. C'est le bon outil pour une panne qu'on observe en direct, parce qu'un niveau debug permanent noie le disque.

Fenêtre de terminal
docker exec -u git forgejo forgejo manager logging add file \
--logger default --writer debug-temp --level debug \
--filename /data/gitea/log/debug-temp.log

La réponse est Added. L'option se nomme --writer (il n'y a pas de --name). Seuls les types file et conn s'ajoutent ainsi, pas console. Pour l'observer, demandez une page inexistante avec curl -sk -o /dev/null https://forge.lab.test/inexistant, puis lisez debug-temp.log dans /data/gitea/log. La requête y produit [D] GetUserByName: user redirect does not exist [name: inexistant], suivi d'une pile d'appels Go de plusieurs dizaines de lignes (76 lignes au total dans le fichier pour cette seule requête). Les lignes du routeur n'y figurent pas : elles appartiennent à un autre logger. Quand vous avez fini d'observer, retirez l'écrivain :

Fenêtre de terminal
docker exec -u git forgejo forgejo manager logging remove debug-temp --logger default

La réponse est Removed. L'autre voie, FORGEJO__log__LEVEL: debug avec recréation du conteneur, n'a pas été rejouée : elle écrit dans app.ini et impose de penser à la défaire.

Forgejo expose ses métriques sur /metrics, désactivé par défaut, protégé par un jeton, et elles sont toutes préfixées gitea_ : aucune forgejo_* n'existe en 15.0.10. Deux variables suffisent dans le service server du compose. Le jeton est une valeur aléatoire (par exemple openssl rand -hex 24) rangée dans le .env, jamais dans le YAML.

FORGEJO__metrics__ENABLED: "true"
FORGEJO__metrics__TOKEN: ${JETON_METRIQUES}

Le .env porte la ligne JETON_METRIQUES=<valeur aléatoire de votre choix> (gabarit : ne copiez aucune valeur d'un exemple). Le client présente ce jeton dans l'en-tête HTTP Authorization: Bearer <jeton> : c'est un jeton bearer (« porteur »), que n'importe quel porteur peut utiliser, d'où le soin à ne pas l'afficher. Après docker compose up -d server, trois requêtes sur https://forge.lab.test/metrics montrent que l'endpoint se protège :

RequêteCode
sans en-tête401
Authorization: Bearer faux401
Authorization: Bearer <jeton>200, environ 11 100 octets, 66 familles

Pour rejouer les trois requêtes sans afficher le jeton, lisez-le dans le .env depuis /opt/forgejo-lab (la taille varie de quelques octets d'un appel à l'autre) :

Fenêtre de terminal
cd /opt/forgejo-lab
JETON=$(grep '^JETON_METRIQUES=' .env | cut -d= -f2)
curl -sk -o /dev/null -w '%{http_code}\n' https://forge.lab.test/metrics
curl -sk -o /dev/null -w '%{http_code}\n' \
-H "Authorization: Bearer faux" https://forge.lab.test/metrics
curl -sk -o /dev/null -w '%{http_code} %{size_download}\n' \
-H "Authorization: Bearer $JETON" https://forge.lab.test/metrics

La sortie attendue est 401, 401, puis 200 suivi de la taille.

Sans [metrics] ENABLED, l'endpoint n'existe pas (réglage par défaut false, non rejoué). Le contenu appartient à deux groupes de métriques. Les jauges applicatives gitea_* (une jauge est une valeur qui monte et descend) comptent les objets de l'instance : gitea_users, gitea_repositories, gitea_organizations, gitea_teams, gitea_issues, gitea_issues_open, gitea_comments, gitea_releases, gitea_webhooks, gitea_publickeys, gitea_mirrors, gitea_attachments, et gitea_build_info (étiquettes version, goversion). Sur l'instance propre, gitea_users vaut 1 et le reste 0. Le Go standard apporte go_*, process_* (dont process_start_time_seconds, process_resident_memory_bytes, process_open_fds) et promhttp_*. Deux réglages facultatifs, ENABLED_ISSUE_BY_LABEL et ENABLED_ISSUE_BY_REPOSITORY (faux par défaut), ajoutent des séries de tickets par étiquette ou par dépôt ; ils n'étaient pas activés ici.

Il faut aussi savoir ce qui manque : aucune métrique de file de tâches, de latence HTTP ni de runner. Une file qui grossit n'est donc pas alertable dans cette version ; elle se lit avec forgejo manager flush-queues ou dans l'administration web (non rejoué ici). Pour le runner, voir Exploiter le runner.

Comment Prometheus scrape-t-il Forgejo avec le jeton ?

Section intitulée « Comment Prometheus scrape-t-il Forgejo avec le jeton ? »

Prometheus lit le jeton dans un fichier grâce à authorization.credentials_file et interroge Forgejo directement sur son port interne 3000, sans passer par Caddy. Le jeton circule alors en clair sur le réseau Docker, pas sur le LAN : c'est un compromis assumé, à refaire autrement si Prometheus tourne sur une autre machine. Le répertoire /opt/prometheus-lab/ contient quatre fichiers : compose.yaml, prometheus.yml, regles.yml et forgejo.jeton. Le dossier appartient à root : écrivez ces fichiers avec sudo tee ou un éditeur lancé par sudo.

Le fichier forgejo.jeton contient le jeton seul, sans retour à la ligne, appartient à l'utilisateur 65534 (celui du conteneur) et a le mode 0400. Le conteneur rejoint le réseau externe de la pile, forgejo-lab_forgejo, et publie son port seulement sur 127.0.0.1:9090. On crée le dossier et le fichier du jeton (copié depuis le .env, sans l'afficher) :

Fenêtre de terminal
sudo mkdir /opt/prometheus-lab && cd /opt/prometheus-lab
grep '^JETON_METRIQUES=' /opt/forgejo-lab/.env | cut -d= -f2 \
| tr -d '\n' | sudo tee forgejo.jeton > /dev/null
sudo chown 65534 forgejo.jeton && sudo chmod 0400 forgejo.jeton

Voici le fichier compose.yaml. L'image est épinglée par son digest (le docker compose up -d qui la tire vient plus bas, après l'écriture des deux fichiers de configuration) :

services:
prometheus:
image: quay.io/prometheus/prometheus:v3.15.0@sha256:efd719c99d83b060d9daefdcf00360461adf279f45ef5391f8d111892118753e
ports:
- "127.0.0.1:9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./regles.yml:/etc/prometheus/regles.yml:ro
- ./forgejo.jeton:/etc/prometheus/forgejo.jeton:ro
- prom-data:/prometheus
networks:
- forgejo
networks:
forgejo:
name: forgejo-lab_forgejo
external: true
volumes:
prom-data:

Le scrape se déclare dans prometheus.yml : le job forgejo présente le jeton du fichier monté et interroge la cible server:3000. L'intervalle de 5 secondes sert à observer vite les changements d'état pendant la démonstration ; en production, gardez l'intervalle habituel de votre Prometheus.

global:
scrape_interval: 5s
evaluation_interval: 5s
rule_files:
- /etc/prometheus/regles.yml
scrape_configs:
- job_name: forgejo
authorization:
type: Bearer
credentials_file: /etc/prometheus/forgejo.jeton
static_configs:
- targets: ["server:3000"]

Avant de démarrer, créez aussi regles.yml avec la règle ForgejoInjoignable donnée dans la section suivante : si ce fichier n'existe pas, Docker crée à sa place un dossier de ce nom et Prometheus échoue. Puis lancez la pile et laissez 10 secondes au premier scrape :

Fenêtre de terminal
docker compose up -d
docker compose exec -T prometheus promtool check config /etc/prometheus/prometheus.yml

promtool doit répondre SUCCESS: 1 rule files found puis SUCCESS: 1 rules found. La commande suivante interroge l'API de Prometheus pour vérifier la cible : elle doit afficher health: up, scrapeUrl à http://server:3000/metrics, et la série up{job="forgejo"} doit valoir 1.

Fenêtre de terminal
curl -s http://127.0.0.1:9090/api/v1/targets

Comment déclencher une alerte quand Forgejo s'arrête ?

Section intitulée « Comment déclencher une alerte quand Forgejo s'arrête ? »

Une règle d'alerte compare une expression à un seuil, et passe par trois états : inactive (condition fausse), pending (vraie depuis moins de la durée for) puis firing (vraie assez longtemps). La durée for évite qu'un scrape raté une fois réveille quelqu'un. La règle de base surveille la série up, que Prometheus fabrique lui-même : 1 si le scrape a réussi, 0 sinon. L'expression PromQL up{job="forgejo"} == 0 sélectionne la série up du job forgejo et ne garde que les valeurs égales à 0. Ce bloc est le contenu de regles.yml :

groups:
- name: forgejo
rules:
- alert: ForgejoInjoignable
expr: up{job="forgejo"} == 0
for: 20s

Avec un scrape et une évaluation à 5 secondes, un for: 20s laisse quelques relevés en pending. L'action déclenchante est l'arrêt du service server, depuis le dossier de la forge ; on relit ensuite l'état des alertes par l'API de Prometheus, à répéter toutes les quelques secondes :

Fenêtre de terminal
cd /opt/forgejo-lab && docker compose stop server
curl -s http://127.0.0.1:9090/api/v1/alerts

La réponse JSON ne liste aucune alerte avant l'arrêt, puis porte ForgejoInjoignable avec son champ state. Voici les relevés obtenus, jusqu'au redémarrage par docker compose start server :

HeureÉtat de ForgejoInjoignable
11:50:48 (avant l'arrêt)aucune alerte, donc inactive
11:50:55, 11:51:01, 11:51:07pending (activeAt à 11:50:51)
11:51:13 et suivantsfiring
après docker compose start server (11:51:38)disparue, up = 1

Pendant l'arrêt, /api/v1/targets donne la cause du scrape raté dans lastError : lookup server on 127.0.0.11:53: server misbehaving, c'est-à-dire que le nom server ne se résout plus puisque le conteneur n'existe plus sur le réseau. Une règle de plus, hors des deux de regles.yml, compare l'âge du processus à un seuil : time() - process_start_time_seconds{job="forgejo"} < 120 signale « redémarré récemment », et elle est passée en firing à chaque recréation du conteneur.

L'envoi de la notification (courriel, chat, astreinte) revient à Alertmanager, présenté dans Alertmanager : il n'a pas été testé dans cette leçon, qui s'arrête à l'alerte firing visible dans Prometheus. Pour écrire des expressions plus fines, voir PromQL.

Pourquoi une base arrêtée ne fait-elle pas tomber up ?

Section intitulée « Pourquoi une base arrêtée ne fait-elle pas tomber up ? »

Quand PostgreSQL s'arrête, l'endpoint /metrics de Forgejo répond encore 200, donc up reste à 1 et la règle up == 0 ne dit rien : il faut une seconde règle sur gitea_users == 0. C'est le résultat le plus important de la leçon. Le schéma suivant montre les deux chaînes. En haut, la panne qui fait tomber la cible (conteneur arrêté, mot de passe faux) déclenche la règle up == 0, nommée ForgejoInjoignable. En pointillés, la panne aveugle : la base s'arrête, l'endpoint répond 200 avec des compteurs à zéro, ForgejoInjoignable reste muette, et seule la règle gitea_users == 0, nommée ForgejoBaseVide, alerte.

Chaîne de supervision de Forgejo : Forgejo expose /metrics avec un jeton, Prometheus le scrape toutes les 5 secondes et produit les séries up et gitea_*. La règle ForgejoInjoignable (up == 0) passe en pending puis firing quand le conteneur est arrêté ou le mot de passe de base faux. Quand PostgreSQL est arrêté, /metrics répond 200 avec up égal à 1 et gitea_users égal à 0 : ForgejoInjoignable reste muette et aucune alerte ne part, tandis que la règle ForgejoBaseVide (gitea_users == 0) passe en pending puis firing.scrape toutes les 5 sconteneur arrêté,mot de passe fauxmuetteouiForgejo/metrics + jetonPrometheussérie up et gitea_*Règleup == 0 ?pending puis firingForgejoInjoignablePostgreSQL arrêtémetrics répond 200up = 1, gitea_users = 0Aucune alerteRèglegitea_users == 0 ?pending puis firingForgejoBaseVide
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

Le relevé le confirme. Arrêtez PostgreSQL, attendez 5 secondes, puis relisez les deux compteurs avec le jeton (la variable JETON posée plus haut) :

Fenêtre de terminal
docker stop forgejo-db
curl -sk -H "Authorization: Bearer $JETON" https://forge.lab.test/metrics \
| grep -E '^gitea_(users|repositories) '

L'endpoint répond 200 avec gitea_users 0 et gitea_repositories 0 : le collecteur n'arrive plus à compter, il publie zéro. Le journal de Forgejo se remplit d'une rafale de [Error SQL Query] SELECT count(*) …. La règle qui fonctionne est celle-ci, avec for: 20s. Elle s'ajoute dans la liste rules de regles.yml, à la suite de la première, avec la même indentation :

- alert: ForgejoBaseVide
expr: gitea_users == 0
for: 20s

Modifiez le fichier en place (sans mv, voir les pièges plus bas), puis demandez à Prometheus de relire ses règles : il ne le fait pas tout seul.

Fenêtre de terminal
cd /opt/prometheus-lab
docker compose exec -T prometheus promtool check rules /etc/prometheus/regles.yml
docker compose kill -s HUP prometheus

promtool doit annoncer SUCCESS: 2 rules found. Le message Killing / Killed de Compose est trompeur : le signal HUP demande seulement un rechargement, le conteneur reste actif. Avec la base arrêtée, la règle passe en pending (quatre relevés à 5 secondes d'intervalle au rejeu du 2026-10-16, de 12:10:03 à 12:10:18) puis firing (12:10:23) ; au premier essai, elle était passée en pending à 11:57:09 et en firing à 11:57:27.

Après docker start forgejo-db, gitea_users revient à 1 et /api/healthz répond 200 sans qu'on touche à Forgejo : la base revient et le pool de connexions (les connexions à la base que Forgejo garde ouvertes) se rétablit seul. Cette règle suppose que l'instance compte au moins un utilisateur ; sur une forge vide, elle serait toujours en alerte.

/api/healthz est un contrôle de santé public, sans jeton, qui ne vérifie que la base et le cache : il répond 200 {"status":"pass", …} ou 424 si un contrôle échoue. Il ne dit rien de Git, de SSH, du runner ni du disque. Chaque appel écrit une ligne PING DATABASE pgx et une ligne du routeur dans le journal.

On peut être tenté de le donner à Prometheus comme cible : l'essai a échoué. Prometheus 3 marque la cible down en permanence, même en bonne santé, avec l'erreur received unsupported Content-Type "application/json" and no fallback_scrape_protocol specified. Ce point d'accès est fait pour un contrôleur HTTP (un équilibreur, un script, un blackbox_exporter, l'exporter de Prometheus qui sonde des URL), pas pour un scrape. Prometheus propose bien un réglage fallback_scrape_protocol, mais la documentation le décrit pour un Content-Type vide, illisible ou invalide ; le corps de /api/healthz est du JSON et non le format d'exposition de Prometheus. Ce contournement et le blackbox_exporter n'ont pas été essayés ici, et le premier ne donnerait sans doute pas de métriques exploitables. Utilisez /api/healthz à la main ou dans un script pour confirmer une réparation, et laissez /metrics à Prometheus.

La méthode tient en cinq temps : le symptôme observé, le journal qui le confirme, la cause, la réparation, la vérification. On ne devine pas, on ne redémarre pas au hasard : on lit d'abord ce que Forgejo dit de lui-même (docker logs forgejo), puis ce que PostgreSQL dit de son côté quand la base est en cause (docker logs forgejo-db). Deux pannes réelles, provoquées sur le lab, servent d'exemples.

Symptôme : /api/healthz répond 424 et les pages qui lisent la base répondent 500, alors que la page d'accueil répond encore 200. Mesuré 5 secondes après docker stop forgejo-db :

URLCode
/api/healthz424, database:ping en fail
/user/login, /explore/repos, /api/v1/repos/search, /api/v1/users/search500
/, /api/v1/version200 (pas d'accès à la base)
/metrics avec jeton200, gitea_users 0

Le journal nomme la cause : checkDatabase() [E] database ping failed with error: failed to connect to user=forgejo database=forgejo: hostname resolving error: lookup db on 127.0.0.11:53: server misbehaving. Le mot à retenir est lookup db : le nom db ne se résout plus, donc le conteneur forgejo-db n'existe plus sur le réseau. La réparation est de le redémarrer (docker start forgejo-db), et la vérification est /api/healthz en 200 et gitea_users revenu à 1. L'alerte à surveiller est ForgejoBaseVide, pas ForgejoInjoignable.

Que faire quand Forgejo n'arrive pas à se connecter à la base ?

Section intitulée « Que faire quand Forgejo n'arrive pas à se connecter à la base ? »

Symptôme : le conteneur est Up mais Caddy répond 502 partout, y compris sur /api/healthz. La panne a été provoquée en changeant le mot de passe FORGEJO__database__PASSWD dans le compose, puis docker compose up -d server. Pour provoquer la panne, remplacez la valeur de FORGEJO__database__PASSWD par une chaîne quelconque. Forgejo tente alors 10 fois de se connecter, puis le processus sort, et restart: always le relance. Le compteur de redémarrages le montre (1 ou 2 en moins d'une minute) :

Fenêtre de terminal
docker inspect forgejo --format '{{.RestartCount}}'

Le journal de Forgejo donne la cause : InitDBEngine() [E] ORM engine initialization attempt #3/10 failed. Error: failed to connect to user=forgejo database=forgejo: 172.30.0.2:5432 (db): failed SASL auth: FATAL: password authentication failed for user "forgejo" (SQLSTATE 28P01). Le journal de PostgreSQL (docker logs forgejo-db) la confirme de l'autre côté : FATAL: password authentication failed for user "forgejo", suivi de Connection matched file ".../pg_hba.conf" line 128: "host all all all scram-sha-256". Le code SQLSTATE 28P01 (le code d'erreur normalisé que PostgreSQL renvoie pour un mot de passe invalide) présent des deux côtés est la signature d'un mauvais mot de passe.

La réparation est de remettre ${POSTGRES_PASSWORD} dans le compose, puis docker compose up -d server. Vérification : /api/healthz répond 200 avec "pass" en moins de 15 secondes. Contrairement à la panne précédente, la cible tombe ici : l'alerte ForgejoInjoignable passe en pending puis firing.

Quels pièges attendent la supervision de Forgejo ?

Section intitulée « Quels pièges attendent la supervision de Forgejo ? »

Trois pièges de la supervision méritent une explication : un fichier monté seul qui reste figé, un contrôle de syntaxe qui échoue hors de la pile, et un jeton qui s'affiche. Le tableau de dépannage plus bas les reprend avec leur correction, ainsi que ceux déjà vus plus haut (le bruit des scrapes dans le journal, la clé dépréciée).

Un fichier monté seul dans le conteneur (./regles.yml:/etc/prometheus/regles.yml) est lié à son inode, l'identifiant du fichier sur le disque. Si vous le remplacez sur l'hôte avec mv, l'inode change : le conteneur garde l'ancienne version, et un kill -HUP ne suffit pas. Il faut docker compose restart prometheus, ou éditer le fichier en place.

Pour contrôler la syntaxe, promtool check config lancé dans un conteneur éphémère (docker run --rm --entrypoint promtool -v ...) échoue si les chemins listés dans rule_files ne sont pas montés : la sortie est FAILED: "/etc/prometheus/regles.yml" does not point to an existing file. Montez le fichier des règles dans ce conteneur aussi, ou lancez promtool avec docker compose exec -T prometheus, comme plus haut.

Enfin, un jeton affiché par un sed ou un grep -A finit dans vos captures : masquez-le avant toute capture d'écran ou copie de session.

Que faire quand la supervision ne se passe pas comme prévu ?

Section intitulée « Que faire quand la supervision ne se passe pas comme prévu ? »

Chaque échec de cette leçon se lit dans un code HTTP, une ligne de journal ou l'état d'une alerte. Le tableau relie le symptôme à sa cause et à la correction qui a été appliquée sur le lab.

SymptômeCauseCorrection
La cible /api/healthz est down en permanencePrometheus 3 refuse le Content-Type application/json (sans fallback_scrape_protocol)ne pas la scraper ; l'utiliser à la main ou dans un script
Base arrêtée, aucune alerte up == 0/metrics répond 200, up reste à 1règle gitea_users == 0
/api/healthz répond 424 et les pages 500PostgreSQL arrêté (lookup db dans le journal)docker start forgejo-db
502 partout, conteneur Up, RestartCount qui montemot de passe de base faux (SQLSTATE 28P01)remettre ${POSTGRES_PASSWORD}, docker compose up -d server
[E] Deprecated config option [log] ENABLE_ACCESS_LOGl'option est dépréciée et sa clé reste dans app.iniLOGGER_ACCESS_MODE: file et suppression de la clé avec sed
docker logs noyé de lignes GET /metricsscrape toutes les 5 s, journal du routeur à infogrep -v "GET /metrics"
Règle modifiée sur l'hôte, ancienne version activefichier monté seul, inode changé par mvdocker compose restart prometheus
promtool check config en conteneur éphémère : FAILED: ... does not point to an existing filele fichier des règles n'est pas monté dans ce conteneurle monter aussi, ou docker compose exec -T prometheus promtool ...
forgejo manager logging add : option inconnuel'option --name n'existe pasutiliser --writer
Pas de forgejo.log dans /data/gitea/logle fichier s'appelle gitea.log en 15.0.10lire gitea.log

Le diagnostic commence toujours par la même question : la panne fait-elle tomber la cible (up == 0) ou seulement les compteurs (gitea_users == 0) ? La réponse oriente vers le bon journal, celui de Forgejo ou celui de PostgreSQL.

On détruit la pile Prometheus avec son volume, on retire du compose.yaml et du .env ce que la leçon y a ajouté, puis on recrée Forgejo. Les variables metrics et log retirées du compose restent dans app.ini (voir le piège de persistance plus haut) : il faut aussi les retirer à la main de ce fichier.

Fenêtre de terminal
cd /opt/prometheus-lab && docker compose down -v
cd /opt/forgejo-lab
sed -i '/FORGEJO__metrics__/d;/FORGEJO__log__/d' compose.yaml
sed -i '/^JETON_METRIQUES/d' .env
docker exec forgejo sed -i -e '/^MODE = console,file/d' \
-e '/^LOGGER_ACCESS_MODE/d' -e '/^\[metrics\]/,/^$/d' /data/gitea/conf/app.ini
docker compose up -d --force-recreate server

Contrôlez le résultat avec curl -sk https://forge.lab.test/api/healthz, qui doit répondre 200, et avec docker exec forgejo grep -c '^\[metrics\]' /data/gitea/conf/app.ini, qui doit afficher 0. Attention : le sed sur compose.yaml supprime toutes les lignes FORGEJO__log__* et FORGEJO__metrics__*, y compris celles que vous auriez ajoutées pour un autre usage ; sur une forge qui n'est pas un lab, retirez-les une à une.

Supprimez ensuite le dossier avec sudo rm -r /opt/prometheus-lab (il ne contient plus que des fichiers de configuration et le jeton). Les fichiers gitea.log, access.log et debug-temp.log restent dans le volume /data/gitea/log. Sur un lab jetable, ce geste ramène la pile à l'état de la leçon d'installation.

  • Les journaux de Forgejo sortent par défaut sur la console du conteneur (docker logs forgejo), niveau info, sans rotation du pilote json-file configurée.
  • MODE: console,file écrit gitea.log (le nom reste gitea.log en 15.0.10) ; le journal d'accès se règle par LOGGER_ACCESS_MODE: file, pas par ENABLE_ACCESS_LOG, déprécié. Les variables FORGEJO__* retirées du compose restent dans app.ini : il faut supprimer la clé à la main.
  • forgejo manager logging add file --writer … ajoute un niveau debug à chaud, remove le retire, sans redémarrage.
  • /metrics se protège par un jeton (401 sans, 200 avec) ; ses familles sont gitea_* plus le Go standard, sans file, latence ni runner.
  • Prometheus scrape server:3000 avec credentials_file ; une règle passe de inactive à pending puis firing, lisible dans /api/v1/alerts.
  • Base arrêtée : /metrics répond 200 et up reste à 1. Alerter aussi sur gitea_users == 0 (ForgejoBaseVide), en plus de up == 0 (ForgejoInjoignable).
  • /api/healthz (base et cache seulement, 424 en panne) n'est pas scrapable tel quel par Prometheus 3 : il sert à confirmer une réparation, à la main ou dans un script.
  • Un diagnostic suit symptôme, journal, cause, réparation, vérification : lookup db pour une base arrêtée, SQLSTATE 28P01 des deux côtés pour un mauvais mot de passe.

Six questions tirées sur huit : les journaux de Forgejo, l'endpoint /metrics et son jeton, les règles d'alerte Prometheus et le diagnostic de deux pannes par le journal.

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