Aller au contenu
Sylvain Joffraud l4w
Retour

Double Gitea mirror : 3 pièges API GitHub & perm `gitea.db`

Double mirror de mes 28 repos GitHub : Gitea principal sur srv-a (accès VPN), Gitea backup sur le NAS (DR si srv-a down). Modèle PULL : chaque Gitea tire les commits de GitHub, jamais l’inverse. PAT fine-grained read-only. 3 pièges.

Piège 1 : gitea.db owned root au 1er start

Wizard d’install sur http://nas:3000, étape « Install » :

The database settings are invalid: migrate: sync: attempt to write a readonly database

Pas « readonly » : le fichier SQLite existe (0 byte) mais owned root, alors que Gitea tourne en git (uid 1000). La directive USER_UID/USER_GID: "1000" n’agit qu’à l’init du container (création du user interne) : elle ne chown pas le volume host. Fix :

chown -R 1000:1000 /srv/.../appdata/gitea/data/
docker restart gitea

Piège 2 : affiliation et type mutuellement exclusifs (GitHub API)

Pour ne lister que mes repos perso, mon script faisait /user/repos?affiliation=owner&type=owner :

$ curl -fsS ".../user/repos?per_page=100&affiliation=owner&type=owner"
curl: (22) ... error: 422

Le body (curl -v) :

{"message":"You can either filter by visibility or affiliation, not both."}

Exclusifs au runtime, pas documenté. Fix : garder affiliation=owner, filtrer côté script :

[r['name'] for r in repos if r['owner']['login'] == GH_USER]

Piège 3 : scope write:repositoryread:organization

Pour vérifier mes orgs sur Gitea srv-a :

$ curl -H "Authorization: token $GITEA_TOKEN" "http://10.8.0.1:3000/api/v1/orgs/github-mirror"
HTTP 403

Le PAT a write:repository (créer des mirrors), mais lire les métadonnées d’org demande read:organization. Pas bloquant : POST /repos/migrate avec repo_owner=github-mirror marche avec write:repository seul. Mais 5 min perdues à croire que les orgs n’existaient pas.

Architecture finale

Les 2 Gitea pull GitHub indépendamment (~2× bande passante, négligeable pour 28 repos en mirror_interval 24h). Vraie double source : une Gitea perd son disque → l’autre a tout, et GitHub aussi. Pas de cascade A→B. Le PC clone/push uniquement sur srv-a via WireGuard.

Lessons learned


Partager cet article :

Article précédent
Gitea : `mirror=true` et `issues=true` incompatibles
Article suivant
Backup PULL : clé SSH restreinte avec `from=` + `no-pty`