Pourquoi sortir de GitLab.com pour une instance self-managed
Quand les tarifs d'un outil SaaS bougent, comme la récente hausse d'Atlassian Cloud détaillée dans notre article sur le double choc tarifaire, les équipes réévaluent tout leur outillage de développement. Pour une agence, la question est concrète : le code de dix clients vit sur un compte unique, chez un tiers, avec une rétention et des accès que l'on ne règle pas soi-même.
Une instance auto-gérée déplace ces décisions chez vous : où sont stockés les dépôts, combien de temps on garde les artefacts, qui peut se connecter, et ce que cela coûte chaque mois. Le prix de cette liberté est un travail de migration que GitLab ne fait pas entièrement à votre place.
Ce guide ne reprend ni le choix de la forge, traité dans le comparatif des forges, ni l'installation, décrite dans le guide d'installation de GitLab CE. Il part d'une instance GitLab déjà en ligne et s'occupe uniquement du passage de GitLab.com vers elle.
Ce que vous gagnez en reprenant l'hébergement
- Des accès sous votre contrôle — comptes, groupes et rôles se gèrent sur votre instance, pas sur un compte SaaS partagé entre clients.
- Une rétention que vous fixez — durée de conservation des artefacts et des journaux, volume du registre, tout se règle dans l'administration.
- Une facture qui suit votre VPS — le coût dépend de la machine que vous dimensionnez, pas d'un nombre de sièges.
- Un nom de domaine à vous — le dépôt répond sur
git.votre-domaine.com, avec votre certificat et votre pare-feu. - Une migration par étapes — l'ancien projet reste en place, en lecture seule, tant que le nouveau n'est pas validé.
Ce que la migration n'emporte pas, à inventorier avant tout
La documentation officielle de l'export de projet liste ce qui n'est pas exporté : l'historique des pipelines enfants, les déclencheurs de pipeline, les traces et artefacts de jobs CI/CD, les images du registre de conteneurs et de paquets, les variables CI/CD, les webhooks, les jetons chiffrés, le nombre d'approbations requises, les clés de déploiement autorisées sur les branches protégées, les fichiers sécurisés et les variables des planifications de pipeline. Les clés de déploiement ne sont pas non plus importées : il faut les réactiver dans le projet importé.
Le direct transfer a sa propre liste d'exclusions, qui recoupe la première : variables CI/CD, webhooks, images du registre, registre de paquets, journaux et artefacts de jobs. Au niveau du groupe, les variables CI/CD, les jetons de déploiement et les règles de push ne suivent pas non plus.
Écrivez cet inventaire dans un tableau avant de commencer : une ligne par projet, une colonne par élément manquant, une colonne pour la personne qui le recrée. C'est ce document, plus que l'export lui-même, qui vous protège le jour où l'ancien accès ferme.
Export de projet ou direct transfer : ce que chaque méthode couvre
Faites défiler le tableau
| Élément | Export de projet (fichier) | Direct transfer |
|---|---|---|
| Granularité | Un projet à la fois, via un fichier téléchargé | Groupes entiers, avec ou sans leurs projets, depuis l'interface |
| Variables CI/CD | Non exportées | Non migrées |
| Images du registre de conteneurs | Non exportées | Non migrées |
| Webhooks | Non exportés | Non migrés |
| Journaux et artefacts de jobs | Non exportés | Non migrés |
| Membres | Rattachés si l'e-mail public source correspond à l'e-mail principal de destination | Rattachés si l'e-mail public source correspond à un e-mail confirmé de destination |
| Ce qu'il faut côté instance | Un administrateur réalise l'import | Fonction activée par un administrateur, jeton avec le scope `api` côté source |
Prérequis : versions, droits et ressources de votre instance
Première règle, la version. L'import d'un fichier accepte des exports issus d'une version jusqu'à deux versions mineures en arrière de la destination, et la documentation demande que la destination soit au moins à la version de la source. Pour le direct transfer, la documentation recommande GitLab 16.8 ou plus récent des deux côtés, et demande qu'une source ne retarde pas de plus de deux versions mineures sur la destination. GitLab.com avance en continu : visez la dernière version stable disponible pour votre instance, mettez-la à jour avant de migrer, pas après, et relisez l'écart toléré dans la documentation le jour J.
Côté droits, il vous faut le rôle Owner sur le groupe source, un administrateur sur l'instance cible, et un jeton d'accès personnel avec le scope api créé sur GitLab.com. Les deux instances doivent se joindre en HTTPS, avec de l'espace libre dans /tmp.
Côté ressources, notre recommandation éditoriale : 4 vCPU et 8 Go de RAM pour une instance qui héberge aussi le registre, un disque NVMe dimensionné sur la taille cumulée des dépôts et des images, et des runners sur un VPS à part dès que les builds sont lourds. L'installation elle-même est décrite dans le guide GitLab CE sur VPS.
Planifier et exécuter la migration, de l'inventaire à la bascule
Inventorier groupes, projets et dépendances
Listez chaque groupe, chaque projet, ses variables, ses webhooks, ses runners et ses intégrations. Notez qui en est propriétaire côté client.
Mettre l'instance cible à jour
Vérifiez la version dans l'administration, et visez la dernière version stable disponible, au moins égale à celle de GitLab.com, avant tout import.
Créer les utilisateurs sur la cible
Les membres ne se créent pas pendant la migration. Créez les comptes avant, avec l'e-mail principal que chaque personne utilise sur GitLab.com.
Prévoir un groupe par client
Créez sur la cible un groupe ou sous-groupe par client, avec les droits minimaux, avant d'importer.
Faire publier les e-mails côté source
Chaque membre renseigne un e-mail public dans son profil GitLab.com, au moins jusqu'à la fin de l'import.
Activer le direct transfer sur l'instance cible
Un administrateur active la migration de groupes par direct transfer dans les paramètres de l'application. Elle est désactivée par défaut sur une instance auto-gérée.
Lancer l'import du groupe
Sur la cible, choisissez Create new puis New group puis Import group, saisissez
https://gitlab.comet votre jeton, puis Connect instance. Sélectionnez les groupes avec Import with projects.Exporter à la main les projets isolés
Pour un projet hors groupe, ouvrez Settings puis General puis Advanced puis Export project, téléchargez le fichier et importez-le sur la cible.
Suivre l'import et relire les erreurs
La colonne Status indique l'avancement. Sur un import en échec ou partiel, Show errors détaille la cause. Comptez plusieurs heures pour un grand nombre de projets.
Brancher la suite sur le registre et la CI
Reconstituez variables et images comme décrit plus bas, puis relancez un pipeline complet sur la cible avant de toucher à l'ancien projet.
Membres et assignees : la règle de rattachement
Sur une instance auto-gérée, la règle publiée est la suivante : les utilisateurs doivent déjà exister sur la destination, et l'e-mail public du compte source doit correspondre à l'e-mail principal du compte de destination. Si les conditions sont réunies, la personne est ajoutée comme membre direct. Sinon, l'association passe à l'utilisateur qui réalise l'import : vos auteurs de commentaires et vos assignees se retrouvent tous à votre nom.
Avant l'import, vérifiez sur chaque profil GitLab.com le champ Public email. Pour un export de projet, vous pouvez aussi ajouter des e-mails publics en éditant le fichier project_members.ndjson de l'archive. Le propriétaire du groupe de premier niveau doit lancer l'export pour que les membres directs et hérités soient inclus, et un administrateur doit réaliser l'import.
Avec le direct transfer, les adhésions importées sont d'abord associées à des utilisateurs substituts, avant réaffectation. Une case Import user memberships permet aussi de ne pas importer les adhésions. Dans ce cas, c'est l'e-mail public source face à un e-mail confirmé de destination qui décide du rattachement, pas l'e-mail principal comme pour l'import de fichier.
Pour une agence, structurez la cible avant d'importer : un groupe de premier niveau par client, ou un sous-groupe par client sous un groupe d'agence. Donnez à chaque client le rôle minimal sur son seul groupe (Reporter ou Developer plutôt qu'Owner), gardez le rôle Owner pour l'équipe interne, et vous pourrez plus tard sortir un client en lui transférant son groupe ou en exportant ses projets, sans toucher aux autres.
Variables CI/CD et registre de conteneurs : reconstituer à la main
Les variables ne voyagent pas, parce que GitLab les considère comme sensibles. Listez-les côté source avec l'API : curl --header "PRIVATE-TOKEN: <jeton>" "https://gitlab.com/api/v4/projects/<id>/variables". La liste donne clé, attributs masked et protected et, en général, la valeur ; mais toutes les valeurs ne sont pas forcément relisibles, selon la version et la façon dont la variable a été créée.
Recréez-les ensuite sur la cible avec curl --request POST --header "PRIVATE-TOKEN: <jeton>" --form "key=NOM" --form "value=valeur" "https://git.votre-domaine.com/api/v4/projects/<id>/variables". La clé accepte 255 caractères parmi A-Z, a-z, 0-9 et _. Quand la valeur manque ou reste masquée, recréez le secret chez son fournisseur et notez-le dans le coffre de l'agence.
Les variables de groupe se recréent depuis les réglages CI/CD du groupe. Les runners, eux, se réenregistrent sur la nouvelle instance : leurs jetons ne suivent pas.
Transférer les images du registre vers la nouvelle URL
Activer le registre sur l'instance cible
Dans
/etc/gitlab/gitlab.rb, définissezregistry_external_urlen HTTPS, par exemplehttps://registry.votre-domaine.com, puis lancezsudo gitlab-ctl reconfigure. Le registre exige un certificat TLS.Créer un jeton pour chaque côté
Un jeton avec
read_registrysuffit pour tirer les images, etwrite_registryen plus pour les pousser.Tirer chaque image depuis l'ancienne URL
Connectez-vous avec
docker login registry.gitlab.com, puisdocker pull registry.gitlab.com/groupe/projet/image:tag.Retaguer puis pousser vers la cible
Exécutez
docker tag registry.gitlab.com/groupe/projet/image:tag registry.votre-domaine.com/groupe/projet/image:tag, puisdocker login registry.votre-domaine.cometdocker push registry.votre-domaine.com/groupe/projet/image:tag. Les chemins de dépôt du registre s'écrivent en minuscules.
Gardez la marche arrière ouverte
Ne supprimez rien à la source. Passez l'ancien projet en archivé ou retirez les droits d'écriture, gardez-le lisible, puis relancez un pipeline et un git clone complet depuis la cible. Tant que la validation n'est pas signée par le client, la bascule reste réversible : il suffit de réouvrir l'ancien projet.
Dépannage : les erreurs d'authentification et d'import
Au docker login ou au docker push, le message access forbidden signifie, selon la documentation, que l'en-tête Authorization a été retiré avant d'atteindre GitLab, souvent par un proxy placé devant l'instance. Vérifiez la configuration du reverse proxy.
Une erreur UNAUTHORIZED (401) indique des identifiants faux ou expirés, des scopes manquants, ou un mot de passe utilisé avec la double authentification activée : utilisez alors un jeton. Un DENIED (403) veut dire que les identifiants sont valides mais sans droit sur le registre.
Sur une grosse image, unauthorized: authentication required signale un jeton expiré avant la fin du push. Un administrateur peut allonger sa durée.
Côté import, un titre de jalon déjà existant reçoit un suffixe unique du type 18.0 (imported-…) : renommez le jalon avant la migration pour l'éviter.
Contrôles avant de couper l'ancien accès
- Dépôts identiques — comparez les branches et les tags, puis faites un clone complet depuis la cible.
- Pipeline complet vert — un pipeline sur la branche principale avec les variables recréées et les runners réenregistrés.
- Images présentes — chaque tag utilisé par un déploiement existe dans le nouveau registre.
- Membres et rôles relus — aucun auteur ni assignee n'a basculé sur le compte qui a lancé l'import.
- Webhooks et clés de déploiement recréés — intégrations de chat, de déploiement et de supervision comprises.
- Validation écrite par le client — l'ancien projet ne se ferme qu'après cet accord.
La documentation officielle
Les règles de ce guide viennent de la documentation GitLab : export et import de projet, migration de groupes par direct transfer, éléments migrés, API des variables de projet, authentification au registre et registre sur une instance auto-gérée. Relisez-les à la date de votre migration : les listes d'éléments migrés évoluent.
Et ensuite : consolider autour de votre instance
Une fois les projets validés, l'instance devient le point central du portefeuille de l'agence. Pour un registre plus lourd, Harbor sur un VPS peut prendre le relais. Si votre migration vient d'un autre outil de tickets, le guide Jira vers OpenProject ou Plane suit la même logique d'inventaire. Et si vous hésitez encore sur la forge, le passage de GitLab vers Gitea reste une option plus légère.