infra : bundle Git quotidien du dépôt, hors serveur #240

Merged
gabriel merged 1 commit from lenaic/74-bundle-depot into develop 2026-09-09 14:14:14 +00:00
Owner

Ferme le #74.

L'archive de secours emporte les données, pas le code. Si le serveur disparaît, la forge disparaît avec lui : le dépôt, les tickets et l'historique de la chaîne vivent tous les trois dessus.

Ce que ça pose

/usr/local/bin/depot-bundle.sh, tous les jours à 03:10, sept bundles conservés dans /var/backups/depot.

Sous deploy et non sous root. Le dépôt cloné appartient à deploy, et Git refuse d'opérer sur un dépôt dont l'utilisateur courant n'est pas propriétaire depuis CVE-2022-24765. Un cron root échouait sur « detected dubious ownership » — constaté en essai réel sur le serveur, pas déduit. Le script pose quand même safe.directory pour qu'un rejeu à la main sous sudo, le geste naturel en incident, ne casse pas au pire moment.

Le serveur ne pousse rien vers l'extérieur. Le critère « aucun secret en clair dans la conf du cron » se tient le plus simplement en n'en ayant aucun : le cron écrit un fichier local, et c'est le poste d'un équipier qui vient le chercher avec sa propre clé. Une machine compromise ne donne alors accès à rien de plus qu'elle-même.

Deux garde-fous qui ne sont pas décoratifs

Un bundle invalide ne prend pas la place du précédent. Écriture sous un nom temporaire, git bundle verify, renommage seulement après. Un bundle tronqué a la bonne taille apparente et ne se voit qu'au clonage.

La rotation compte des fichiers, pas des jours. Sept jours sans passage de cron laisseraient sinon zéro sauvegarde, ce qui est exactement le cas où on en a besoin.

Les cinq critères

  • cron quotidien produisant git bundle --all horodaté
  • copie hors serveur vers une cible non-Azure — poste de Lénaïc, ~/eadl/secours/depot/, nommée dans le runbook
  • git clone depuis un bundle vérifié, résultat consigné (ci-dessous)
  • rotation gardant au moins sept bundles
  • aucun secret en clair dans la conf du cron — il n'y en a aucun

Éprouvé de bout en bout le 09/09

depot-bundle: /var/backups/depot/enervision-20260909T094739Z.bundle,
              2661167 octets, 1 bundle(s) conserve(s)

Récupération de enervision-20260909T094739Z.bundle…
  OK  enervision-20260909T094739Z.bundle
      584 commits, dernier : 415af1a Merge pull request 'Mise en production…'

Bundle produit sur le serveur, récupéré sur le poste, cloné pour de vrai : 584 commits, 3 branches. Rotation éprouvée séparément — quatre passages avec une garde de deux ne laissent que les deux plus récents.

Un piège évité en route, qui mérite d'être lu

La ligne de cron dépassait cent caractères et ansible-lint la refusait. La couper par un antislash aurait produit une ligne de cron invalide : cron ne connaît pas la continuation de ligne. La sauvegarde quotidienne aurait été cassée en silence pour satisfaire un linter. C'est la variable qui a raccourci, pas la ligne.

Ce que ça débloque

#102 — repasser la forge en réseau bridge. Ce ticket est risqué à deux jours du jury parce qu'un faux pas fait perdre dépôt, tickets et chaîne d'un coup. Avec un bundle vérifié hors serveur, le dépôt survit. Le faire dans cet ordre est ce qui rend #102 tenable.

Ferme le #74. L'archive de secours emporte les données, **pas le code**. Si le serveur disparaît, la forge disparaît avec lui : le dépôt, les tickets et l'historique de la chaîne vivent tous les trois dessus. ### Ce que ça pose `/usr/local/bin/depot-bundle.sh`, tous les jours à **03:10**, sept bundles conservés dans `/var/backups/depot`. **Sous `deploy` et non sous `root`.** Le dépôt cloné appartient à `deploy`, et Git refuse d'opérer sur un dépôt dont l'utilisateur courant n'est pas propriétaire depuis CVE-2022-24765. Un cron root échouait sur « detected dubious ownership » — **constaté en essai réel sur le serveur, pas déduit**. Le script pose quand même `safe.directory` pour qu'un rejeu à la main sous `sudo`, le geste naturel en incident, ne casse pas au pire moment. **Le serveur ne pousse rien vers l'extérieur.** Le critère « aucun secret en clair dans la conf du cron » se tient le plus simplement en n'en ayant aucun : le cron écrit un fichier local, et c'est le poste d'un équipier qui vient le **chercher** avec sa propre clé. Une machine compromise ne donne alors accès à rien de plus qu'elle-même. ### Deux garde-fous qui ne sont pas décoratifs **Un bundle invalide ne prend pas la place du précédent.** Écriture sous un nom temporaire, `git bundle verify`, renommage seulement après. Un bundle tronqué a la bonne taille apparente et ne se voit qu'au clonage. **La rotation compte des fichiers, pas des jours.** Sept jours sans passage de cron laisseraient sinon zéro sauvegarde, ce qui est exactement le cas où on en a besoin. ### Les cinq critères - [x] cron quotidien produisant `git bundle --all` horodaté - [x] copie hors serveur vers une cible non-Azure — poste de Lénaïc, `~/eadl/secours/depot/`, nommée dans le runbook - [x] `git clone` depuis un bundle vérifié, résultat consigné (ci-dessous) - [x] rotation gardant au moins sept bundles - [x] aucun secret en clair dans la conf du cron — il n'y en a aucun ### Éprouvé de bout en bout le 09/09 ``` depot-bundle: /var/backups/depot/enervision-20260909T094739Z.bundle, 2661167 octets, 1 bundle(s) conserve(s) Récupération de enervision-20260909T094739Z.bundle… OK enervision-20260909T094739Z.bundle 584 commits, dernier : 415af1a Merge pull request 'Mise en production…' ``` Bundle produit sur le serveur, récupéré sur le poste, **cloné pour de vrai** : 584 commits, 3 branches. Rotation éprouvée séparément — quatre passages avec une garde de deux ne laissent que les deux plus récents. ### Un piège évité en route, qui mérite d'être lu La ligne de cron dépassait cent caractères et `ansible-lint` la refusait. **La couper par un antislash aurait produit une ligne de cron invalide** : cron ne connaît pas la continuation de ligne. La sauvegarde quotidienne aurait été cassée en silence pour satisfaire un linter. C'est la variable qui a raccourci, pas la ligne. ### Ce que ça débloque **#102** — repasser la forge en réseau bridge. Ce ticket est risqué à deux jours du jury parce qu'un faux pas fait perdre dépôt, tickets et chaîne d'un coup. Avec un bundle vérifié hors serveur, le dépôt survit. **Le faire dans cet ordre est ce qui rend #102 tenable.**
lenaic self-assigned this 2026-09-09 09:48:23 +00:00
infra: bundle Git quotidien du depot, hors serveur (#74)
All checks were successful
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 45s
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 6s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 18s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m19s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 6m8s
08e5534e04
L archive de secours emporte les donnees, pas le code. Si le serveur disparait,
la forge disparait avec lui : le depot, les tickets et l historique de la chaine
vivent tous les trois dessus. Un « git bundle --all » quotidien repond a la
moitie qui compte le plus, et le ticket assume le reste : ce qui ne se
reconstitue pas, c est le code.

SOUS deploy ET NON SOUS root. Le depot clone appartient a deploy, et Git refuse
d operer sur un depot dont l utilisateur courant n est pas proprietaire depuis
CVE-2022-24765. Un cron root echouait sur « detected dubious ownership » —
constate en essai reel sur le serveur, pas deduit. Le script pose quand meme
safe.directory pour qu un rejeu a la main sous sudo, le geste naturel en
incident, ne casse pas au pire moment.

LE SERVEUR NE POUSSE RIEN VERS L EXTERIEUR. Le critere « aucun secret en clair
dans la conf du cron » se tient le plus simplement en n en ayant aucun : le cron
ecrit un fichier local, et c est le poste d un equipier qui vient le CHERCHER
avec sa propre cle. Une machine compromise ne donne alors acces a rien de plus
qu elle-meme.

Un bundle qui ne passe pas « git bundle verify » NE PREND PAS LA PLACE du
precedent : ecriture sous un nom temporaire, verification, renommage seulement
apres. Un bundle tronque a la bonne taille apparente et ne se voit qu au
clonage.

La rotation compte des FICHIERS et non des jours. Sept jours sans passage de
cron laisseraient sinon zero sauvegarde, ce qui est exactement le cas ou on en a
besoin.

Eprouve de bout en bout le 09/09 : bundle de 2 661 167 octets produit sur le
serveur, recupere sur le poste, CLONE pour de vrai — 584 commits, 3 branches,
dernier commit 415af1a. Rotation eprouvee : quatre passages avec une garde de
deux ne laissent que les deux plus recents.

Un piege evite en route : la ligne de cron depassait cent caracteres et
ansible-lint la refusait. La couper par un antislash aurait produit une ligne de
cron INVALIDE, cron ne connaissant pas la continuation de ligne — la sauvegarde
quotidienne aurait ete cassee en silence pour satisfaire un linter. C est la
variable qui a raccourci.
gabriel approved these changes 2026-09-09 12:52:09 +00:00
gabriel merged commit 1815fff35f into develop 2026-09-09 14:14:14 +00:00
gabriel deleted branch lenaic/74-bundle-depot 2026-09-09 14:14:14 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
g2/enervision!240
No description provided.