GitHub N'est Pas Votre Sauvegarde. Un Compte Suspendu L'a Prouvé Cette Semaine.

9 min read

Un développeur a perdu 104 repos cette semaine. Moi, j'avais déjà arrêté de faire confiance à GitHub pour les miens.

Cette semaine, un développeur a découvert à 9h du matin que ses 104 repos GitHub n'existaient plus. Pas de hack. Pas de bug. Pas de disque dur qui a lâché. Juste un email automatisé : compte suspendu, nous avons réévalué votre Student Pack de 2019, nous pensons maintenant que vous n'étiez pas éligible. Six ans plus tard. 24 de ces repos n'avaient aucune sauvegarde ailleurs. Volatilisés par une décision algorithmique prise un mardi matin.

TLDR : Si vous êtes dans le même cas (tout sur GitHub, pas de miroir, pas de plan B), vous êtes à un classificateur près du même email à 9h du matin. Il y a une solution. Ça ne coûte rien, ça tourne sur un serveur que vous louez probablement déjà, et presque personne ne s'en donne la peine. La question, c'est pourquoi.

Les réponses sous ce post racontent l'autre histoire. Des centaines de devs qui réalisent en temps réel qu'ils sont exactement dans la même situation. Tout sur GitHub. Pas de miroir. Pas de plan B. Et la même question qui revient dans tous les threads : ok mais concrètement, je fais quoi maintenant ?

Moi, je n'ai pas attendu. Pas par paranoïa, pas parce que j'avais une boule de cristal. Juste parce qu'à un moment dans votre carrière de dev, vous arrêtez de confondre "hébergé ailleurs" avec "sauvegardé". GitHub est un excellent outil. C'est une excellente forge. C'est un excellent réseau social pour le code. Ce n'est pas une sauvegarde, ça n'a jamais été leur boulot, et c'est écrit noir sur blanc dans leurs conditions d'utilisation.

Développeur fixant son compte GitHub suspendu tandis qu'un collègue pointe avec assurance vers une configuration de serveur de sauvegarde git en miroir
GitHub a suspendu son compte. Sa stratégie de sauvegarde ? Absolument rien.

104 Repos. Une Décision Automatisée. Aucun Avertissement.

L'histoire qui a tourné cette semaine se raconte en deux phrases. Un développeur s'est inscrit pour un Student Pack gratuit en 2019. Six ans plus tard, une révision automatisée a réévalué l'éligibilité originale, a décidé rétroactivement qu'elle n'était jamais légitime, et a suspendu le compte. 104 repos cachés. 24 d'entre eux jamais poussés ailleurs.

Peu importe si la demande de Student Pack originale était légitime ou pas. Ce qui compte, c'est que des années de travail peuvent disparaître derrière un processus sur lequel vous n'avez aucune prise, selon un calendrier que vous ne pouvez pas prévoir, déclenché par un classificateur de 2026 qui renotе un formulaire qu'un gamin de 19 ans a rempli en 2019.

Les threads sous le post sont pleins de gens qui font le calcul en public. J'ai 60 repos. Je suis sur GitHub depuis 2014. Je n'ai jamais pensé à un miroir. Ceux qui sont confiants sont ceux avec du git auto-hébergé qui tourne quelque part. Il n'y en a pas beaucoup.

Vous n'avez pas d'avertissement avant que ça vous arrive.

Ce Que GitHub Vous Promet Vraiment (C'est Moins Que Vous Croyez)

GitHub ne promet pas de garder vos repos. Ils promettent de faire tourner une plateforme.

Lisez les Conditions d'Utilisation à jeun (c'est chiant, faites-le une fois). Les clauses pertinentes ne sont pas cachées. GitHub peut suspendre ou résilier des comptes à sa discrétion. Votre contenu peut être supprimé s'il viole des politiques, y compris des politiques qui n'existaient pas quand vous avez créé le compte. Et votre obligation en tant qu'utilisateur est de maintenir vos propres copies de tout ce que vous ne pouvez pas vous permettre de perdre.

Il y a même un nom pour ça. L'industrie du cloud l'utilise depuis plus d'une décennie et tous les gros fournisseurs ont une page dessus : le Modèle de Responsabilité Partagée. Le fournisseur fait tourner la plateforme. Le client possède les données. GitHub ne le met pas sur la page d'accueil parce que personne ne s'inscrirait si c'était marqué "vos données sont votre problème", mais le contrat est le même.

L'erreur que presque tout le monde fait est une erreur de catégorie. On traite GitHub comme un système de fichiers. Ça y ressemble (dossiers, fichiers, historique). Ça en a l'air (toujours là, toujours synchronisé). Mais c'est un service managé avec des CGU, et les services managés ont une porte de sortie actionnée par le fournisseur.

Je ne conteste pas le contrat. Je ne fais que le lire. Une fois que vous l'avez lu, vous ne pouvez plus l'ignorer.

Je N'Attends Pas Les Incidents. C'est Un Principe de Design.

J'ai une règle pour tout tiers dont je dépends : si le perdre me ferait mal, il a une copie locale. Pas parce que j'attends que le fournisseur plante. Parce que le coût de me tromper sur ce point-là est trop élevé.

C'est de l'hygiène d'infra standard, pas de la paranoïa. Vous ne débattez pas avec le DBA pour savoir si le primaire "pourrait" tomber. Vous montez le réplica parce que c'est comme ça qu'on construit une infra qui survit à un mardi.

Même principe pour lequel j'ai reconstruit toute ma config d'agents IA la semaine où Anthropic a tué ma config OpenClaw à 200$/mois et m'a forcé à la reconstruire pour 15$. Je n'ai pas attendu que l'annonce me morde une deuxième fois. Dès qu'un vendeur change les règles unilatéralement, la bonne réaction n'est pas de renégocier. C'est de posséder la version suivante.

Les gens de la sécurité appellent ça security by design. Les décisions que vous prenez au moment de l'architecture sont des décisions que vous n'avez pas à prendre sous stress. Vous ne concevez pas une sortie de secours pendant l'incendie. Vous n'écrivez pas une stratégie de sauvegarde à 9h du matin en fixant un email de suspension et un café qui a refroidi.

Donc j'avais un miroir. Avant tout ça. Pour une raison : mon code est le seul livrable que je ne peux pas recréer. Les serveurs, je peux les reconstruire. Les configs, je peux les réécrire. Six ans de commits dans 39 repos privés, ça, je ne peux pas.

Le miroir existe pour que je n'aie jamais à écrire un post de blog du dimanche soir intitulé Comment J'ai Récupéré d'une Suspension GitHub.

Ma Config : Miroir Forgejo Derrière un Mesh NetBird

Architecture flow diagram. GitHub on the left, arrow labeled
Architecture du Miroir Git

Deux pièces. C'est toute la config.

Forgejo est une forge git auto-hébergée. Elle a forké de Gitea en 2022 quand Gitea est passé à une structure d'entreprise à but lucratif (oui, c'est le genre de détail qui compte une fois que vous commencez à vous soucier de qui possède vos outils). Ça tourne dans un seul container avec SQLite. Pas de cluster PostgreSQL, pas de Redis, pas de microservices. Ça parle le protocole git nativement, pas d'abstraction de couche web. Si vous cloniez un repo depuis Forgejo, vous ne remarqueriez pas que vous n'êtes pas sur GitHub. Même logique que celle pour laquelle j'ai plaidé dans pourquoi les CLI battent MCP pour les agents IA : la primitive bat le wrapper, à chaque fois.

NetBird est un mesh basé sur WireGuard. Mon laptop, mon VPS et quelques autres appareils sont sur un réseau privé avec des IP privées. Pas d'exposition publique. Pas de reverse proxy. Pas de certificat TLS à renouveler. Si vous n'êtes pas sur le mesh, le port ne répond même pas.

Le container Forgejo ressemble à ça :

services:
  forgejo:
    image: codeberg.org/forgejo/forgejo:11
    container_name: forgejo
    restart: unless-stopped
    ports:
      - "100.69.51.147:3000:3000"
    volumes:
      - forgejo_data:/data
    environment:
      - FORGEJO__server__ROOT_URL=http://forgejo.mesh:3000
      - FORGEJO__server__DISABLE_SSH=true
      - FORGEJO__service__DISABLE_REGISTRATION=true
      - FORGEJO__mirror__DEFAULT_INTERVAL=8h

Quatre choix à souligner :

Le port se bind uniquement sur l'IP du mesh (100.69.51.147). Pas 0.0.0.0. Pas exposé à l'internet public. Le miroir est une ressource privée qui vit derrière la même barrière que mes autres services internes.

SSH est désactivé. Je ne pousse jamais vers le miroir. Il est en lecture seule. Désactiver SSH supprime toute une surface d'attaque dont je n'ai pas besoin.

L'inscription est désactivée. Instance mono-utilisateur. Pas de formulaire d'inscription pour qu'un bot le trouve un mardi.

L'intervalle de sync du miroir est de 8 heures. Forgejo a un support natif de pull mirror : vous lui donnez une URL GitHub et un PAT, et il tire toutes les 8 heures pour toujours. Pas de cron, pas de script, pas de webhook. La forge le fait elle-même.

Puis un petit script enregistre tous mes repos GitHub comme miroirs via l'API Forgejo. C'est idempotent : il liste les repos, vérifie lesquels ont déjà un miroir, et ne crée que ceux qui manquent. Lancez-le une fois à l'installation. Relancez-le à chaque fois que vous créez un nouveau repo GitHub. Ou planifiez-le hebdomadairement, à vous de voir. L'appel API unique par repo ressemble à ça :

curl -X POST "$FORGEJO_URL/api/v1/repos/migrate" \
  -H "Authorization: token $FORGEJO_TOKEN" \
  -d '{
    "clone_addr": "https://github.com/myorg/repo.git",
    "repo_name": "repo",
    "mirror": true,
    "private": true,
    "auth_token": "'$GITHUB_PAT'",
    "service": "github"
  }'

Enrobez ça dans une boucle sur gh repo list myorg, avec une vérification sur l'existence du miroir, et c'est fini. Le PAT et le token Forgejo viennent d'un gestionnaire de secrets auto-hébergé au runtime, jamais sur disque.

Empreinte totale des ressources : environ 100MB de RAM, 2GB de disque pour 39 repos. Le container redémarre en deux secondes. La sync de 8h tourne en arrière-plan et j'oublie qu'elle existe pendant des semaines d'affilée.

Ce Que Ça Couvre, et Ce Que Ça Ne Couvre Pas

C'est la partie que la plupart des articles "auto-hébergez votre git" sautent. Un pull mirror n'est pas une sauvegarde GitHub complète.

Ce que le miroir sauve, c'est le côté git des choses : chaque commit, chaque branche, chaque tag, historique complet sur toutes les branches. Les submodules et LFS marchent aussi si vous prenez l'étape supplémentaire de les configurer, et vous devriez si vous les utilisez.

Ce que le miroir ne sauve PAS, c'est tout ce qui vit en dehors du protocole git. Les issues. Les pull requests et commentaires de review. Les pages wiki. Les logs de runs Actions (les fichiers YAML oui, l'historique des runs non). Les paramètres de repo, webhooks, clés de déploiement, listes d'accès des collaborateurs. Tout ça, c'est de la métadonnée spécifique à GitHub, stockée dans leur base de données, pas dans votre répertoire .git. Si GitHub disparaît demain, mes 39 repos sont intacts, avec jusqu'à 8 heures de retard. Mes issues et PR ne le sont pas.

Pour mon cas d'usage (repos privés, principalement travail solo, code d'infrastructure), c'est un compromis acceptable. Pour une équipe plus large qui fait tourner la moitié de son workflow dans GitHub Issues, la conversation est différente. Vous voudriez l'outil officiel de sauvegarde de repos GitHub, ou un tiers qui tape l'API pour les issues et PR aussi, en plus du miroir git.

Il y a aussi le cas où je supprime un repo sur GitHub par accident. Le pull mirror remarque que l'upstream a disparu, mais Forgejo ne supprime pas automatiquement la copie locale. Le dernier état synchronisé reste. C'est en fait une fonctionnalité : une action destructive en amont ne se propage pas. (Je ne vais pas prétendre que j'ai conçu ça exprès. Je l'ai remarqué la première fois que j'ai nettoyé une vieille org et que j'ai vu le miroir encore assis là un mois plus tard. Filet de sécurité gratuit, je l'ai gardé.)

Sachez ce que fait votre filtre et ce qu'il ne fait pas. Ne vous vendez pas une histoire de sauvegarde qui ne correspond pas au contrat que vous avez réellement avec vos outils.

Vous N'Avez Pas à Attendre Votre Propre Incident

L'histoire des 104 repos n'est pas exceptionnelle. Elle est juste visible. La même chose arrive chaque semaine à des gens dont l'audience est trop petite pour que le post voyage. Suspensions de compte, takedowns DMCA erronés, disputes de facturation, faux positifs de classificateur, méthode de paiement expirée dans un pays que le système de facturation de GitHub gère bizarrement. La liste est longue. La solution est la même dans tous les cas.

Dans six mois, GitHub publiera un post de blog sur "l'amélioration de notre communication des actions de compte". Il y aura un nouveau dashboard, une FAQ rafraîchie, une page de statut plus jolie. Personne ne la lira avant la prochaine vague.

Pendant ce temps, les devs qui livrent continueront à livrer. Avec un miroir. Sur leur propre infra. Accessible quand GitHub est down, quand un classificateur se plante, quand un Student Pack de 2019 devient soudain un problème de 2026. Pas grand-chose. Juste un docker-compose et trois heures de config un dimanche.

Git est distribué par design. C'est nous qui avons décidé d'oublier.

Sources

(*) La couverture est générée par IA. Aucun repo GitHub réel n'a été blessé dans la création de cette image.