Por qué salir de GitLab.com hacia una instancia self-managed
Cuando cambian las tarifas de una herramienta SaaS, como la reciente subida de Atlassian Cloud detallada en nuestro artículo sobre el doble golpe tarifario, los equipos reevalúan todo su entorno de desarrollo. Para una agencia la cuestión es concreta: el código de diez clientes vive en una única cuenta, en un tercero, con una retención y unos accesos que usted no fija.
Una instancia autogestionada traslada esas decisiones a su lado: dónde se almacenan los repositorios, cuánto tiempo se guardan los artefactos, quién puede entrar y cuánto cuesta cada mes. El precio de esa libertad es un trabajo de migración que GitLab no hace del todo por usted.
Esta guía no repite la elección de la forja, tratada en el comparativo de forjas, ni la instalación, descrita en la guía de instalación de GitLab CE. Parte de una instancia de GitLab ya en línea y solo cubre el paso de GitLab.com hacia ella.
Lo que gana al recuperar el alojamiento
- Accesos bajo su control — cuentas, grupos y roles se gestionan en su instancia, no en una cuenta SaaS compartida entre clientes.
- Una retención que usted fija — duración de los artefactos y registros, tamaño del registro: todo se ajusta en la administración.
- Una factura que sigue a su VPS — el coste depende de la máquina que dimensiona, no de un número de puestos.
- Un nombre de dominio propio — el repositorio responde en
git.su-dominio.com, con su certificado y su cortafuegos. - Una migración por etapas — el proyecto antiguo sigue en su sitio, en solo lectura, hasta validar el nuevo.
Lo que la migración no lleva, que hay que inventariar antes
La documentación oficial de la exportación de proyectos enumera lo que no se exporta: el historial de pipelines hijos, los disparadores de pipeline, las trazas y artefactos de trabajos CI/CD, las imágenes del registro de contenedores y de paquetes, las variables CI/CD, los webhooks, los tokens cifrados, el número de aprobaciones requeridas, las claves de despliegue autorizadas en ramas protegidas, los archivos seguros y las variables de las programaciones de pipeline. Las claves de despliegue tampoco se importan: hay que reactivarlas en el proyecto importado.
El direct transfer tiene su propia lista de exclusiones, que coincide en parte con la primera: variables CI/CD, webhooks, imágenes del registro de contenedores, registro de paquetes, registros y artefactos de trabajos. A nivel de grupo, las variables CI/CD, los tokens de despliegue y las reglas de push tampoco acompañan.
Escriba este inventario en una tabla antes de empezar: una fila por proyecto, una columna por elemento ausente, una columna para la persona que lo recrea. Ese documento, más que la propia exportación, le protege el día que se cierre el acceso antiguo.
Exportación de proyecto o direct transfer: qué cubre cada método
Desplace la tabla
| Elemento | Exportación de proyecto (archivo) | Direct transfer |
|---|---|---|
| Granularidad | Un proyecto cada vez, mediante un archivo descargado | Grupos enteros, con o sin sus proyectos, desde la interfaz |
| Variables CI/CD | No se exportan | No se migran |
| Imágenes del registro de contenedores | No se exportan | No se migran |
| Webhooks | No se exportan | No se migran |
| Registros y artefactos de trabajos | No se exportan | No se migran |
| Miembros | Se asocian si el correo público de origen coincide con el correo principal de destino | Se asocian si el correo público de origen coincide con un correo confirmado de destino |
| Lo que exige la instancia | Un administrador realiza la importación | Función activada por un administrador, token con el scope `api` en el origen |
Requisitos: versiones, permisos y recursos de su instancia
Primera regla, la versión. La importación de un archivo acepta exportaciones de una versión hasta dos versiones menores por detrás del destino, y la documentación pide que el destino esté al menos en la versión del origen. Para el direct transfer, la documentación recomienda GitLab 16.8 o posterior en ambos lados, y pide que un origen no se retrase más de dos versiones menores respecto al destino. GitLab.com avanza de forma continua: apunte a la última versión estable disponible en su instancia, actualícela antes de migrar, no después, y relea la diferencia tolerada en la documentación el mismo día.
En cuanto a permisos, necesita el rol Owner en el grupo de origen, un administrador en la instancia de destino y un token de acceso personal con el scope api creado en GitLab.com. Las dos instancias deben comunicarse por HTTPS, con espacio libre en /tmp.
En cuanto a recursos, nuestra recomendación editorial: 4 vCPU y 8 GB de RAM para una instancia que además aloja el registro, un disco NVMe dimensionado según el tamaño acumulado de repositorios e imágenes, y runners en un VPS aparte en cuanto los builds sean pesados. La instalación se describe en la guía de GitLab CE en un VPS.
Planificar y ejecutar la migración, del inventario al cambio
Inventariar grupos, proyectos y dependencias
Enumere cada grupo, cada proyecto, sus variables, webhooks, runners e integraciones. Anote quién es el responsable de cada uno en el cliente.
Actualizar la instancia de destino
Compruebe la versión en la administración y apunte a la última versión estable disponible, al menos igual a la de GitLab.com, antes de cualquier importación.
Crear los usuarios en el destino
Los miembros no se crean durante la migración. Cree las cuentas antes, con el correo principal que cada persona usa en GitLab.com.
Prever un grupo por cliente
Cree en el destino un grupo o subgrupo por cliente, con permisos mínimos, antes de importar.
Hacer publicar los correos en el origen
Cada miembro indica un correo público en su perfil de GitLab.com, al menos hasta que termine la importación.
Activar el direct transfer en la instancia de destino
Un administrador activa la migración de grupos por direct transfer en los ajustes de la aplicación. Está desactivada por defecto en una instancia autogestionada.
Lanzar la importación del grupo
En el destino, elija Create new y después New group y Import group, introduzca
https://gitlab.comy su token, y pulse Connect instance. Seleccione los grupos con Import with projects.Exportar a mano los proyectos sueltos
Para un proyecto fuera de un grupo, abra Settings, General, Advanced y Export project, descargue el archivo e impórtelo en el destino.
Seguir la importación y leer los errores
La columna Status indica el avance. En una importación fallida o parcial, Show errors detalla la causa. Cuente con varias horas si hay muchos proyectos.
Conectar el registro y la CI
Reconstruya variables e imágenes como se describe más abajo y lance un pipeline completo en el destino antes de tocar el proyecto antiguo.
Miembros y asignados: la regla de asociación
En una instancia autogestionada, la regla publicada es esta: los usuarios deben existir ya en el destino, y el correo público de la cuenta de origen debe coincidir con el correo principal de la cuenta de destino. Si se cumplen las condiciones, la persona se añade como miembro directo. Si no, la asociación pasa al usuario que realiza la importación: los autores de comentarios y los asignados acaban todos a su nombre.
Antes de importar, compruebe el campo Public email de cada perfil de GitLab.com. En una exportación de proyecto también puede añadir correos públicos editando el archivo project_members.ndjson del paquete. El propietario del grupo de primer nivel debe lanzar la exportación para que se incluyan los miembros directos y heredados, y un administrador debe realizar la importación.
Con el direct transfer, las pertenencias importadas se asocian primero a usuarios sustitutos, a la espera de reasignación. Una casilla Import user memberships permite además no importar las pertenencias. En ese caso, decide la asociación el correo público de origen frente a un correo confirmado de destino, no el correo principal como en la importación de archivo.
Para una agencia, estructure el destino antes de importar: un grupo de primer nivel por cliente, o un subgrupo por cliente bajo un grupo de agencia. Dé a cada cliente el rol mínimo solo en su grupo (Reporter o Developer en lugar de Owner), reserve el rol Owner al equipo interno, y más adelante podrá sacar a un cliente transfiriendo su grupo o exportando sus proyectos, sin tocar a los demás.
Variables CI/CD y registro de contenedores: reconstruir a mano
Las variables no viajan, porque GitLab las considera sensibles. Enumérelas en el origen con la API: curl --header "PRIVATE-TOKEN: <token>" "https://gitlab.com/api/v4/projects/<id>/variables". La lista da la clave, los atributos masked y protected y, normalmente, el valor; pero no todos los valores son necesariamente legibles, según la versión y cómo se creó la variable.
Luego recréelas en el destino con curl --request POST --header "PRIVATE-TOKEN: <token>" --form "key=NOMBRE" --form "value=valor" "https://git.su-dominio.com/api/v4/projects/<id>/variables". La clave admite 255 caracteres entre A-Z, a-z, 0-9 y _. Cuando falta el valor o sigue oculto, recree el secreto en su proveedor y guárdelo en la caja fuerte de la agencia.
Las variables de grupo se recrean desde los ajustes CI/CD del grupo. Los runners se registran de nuevo en la nueva instancia: sus tokens no acompañan.
Transferir las imágenes del registro a la nueva URL
Activar el registro en la instancia de destino
En
/etc/gitlab/gitlab.rb, definaregistry_external_urlen HTTPS, por ejemplohttps://registry.su-dominio.com, y ejecutesudo gitlab-ctl reconfigure. El registro exige un certificado TLS.Crear un token para cada lado
Un token con
read_registrybasta para descargar imágenes, y conwrite_registryademás para subirlas.Descargar cada imagen desde la URL antigua
Inicie sesión con
docker login registry.gitlab.comy despuésdocker pull registry.gitlab.com/grupo/proyecto/imagen:tag.Reetiquetar y subir al destino
Ejecute
docker tag registry.gitlab.com/grupo/proyecto/imagen:tag registry.su-dominio.com/grupo/proyecto/imagen:tag, luegodocker login registry.su-dominio.comydocker push registry.su-dominio.com/grupo/proyecto/imagen:tag. Las rutas de repositorio del registro se escriben en minúsculas.
Mantenga abierta la marcha atrás
No borre nada en el origen. Archive el proyecto antiguo o retire los permisos de escritura, déjelo legible y lance un pipeline y un git clone completo desde el destino. Mientras el cliente no haya firmado la validación, el cambio sigue siendo reversible: basta con reabrir el proyecto antiguo.
Solución de problemas: errores de autenticación y de importación
En docker login o docker push, el mensaje access forbidden significa, según la documentación, que la cabecera Authorization se eliminó antes de llegar a GitLab, a menudo por un proxy situado delante de la instancia. Revise la configuración del proxy inverso.
Un error UNAUTHORIZED (401) indica credenciales erróneas o caducadas, scopes ausentes o una contraseña usada con la doble autenticación activada: use entonces un token. Un DENIED (403) quiere decir que las credenciales son válidas pero sin derecho sobre el registro.
En una imagen grande, unauthorized: authentication required señala un token que caducó antes de terminar el push. Un administrador puede alargar su duración.
En la importación, un título de hito que ya existe recibe un sufijo único del tipo 18.0 (imported-…): renombre el hito antes de migrar para evitarlo.
Controles antes de cortar el acceso antiguo
- Repositorios idénticos — compare ramas y etiquetas, y haga un clon completo desde el destino.
- Pipeline completo en verde — un pipeline en la rama principal con las variables recreadas y los runners registrados de nuevo.
- Imágenes presentes — cada tag usado por un despliegue existe en el nuevo registro.
- Miembros y roles revisados — ningún autor ni asignado ha pasado a la cuenta que lanzó la importación.
- Webhooks y claves de despliegue recreados — incluidas las integraciones de chat, despliegue y supervisión.
- Validación escrita del cliente — el proyecto antiguo solo se cierra tras ese acuerdo.
La documentación oficial
Las reglas de esta guía proceden de la documentación de GitLab: exportación e importación de proyectos, migración de grupos por direct transfer, elementos migrados, API de variables de proyecto, autenticación en el registro y registro en una instancia autogestionada. Reléalas en la fecha de su migración: las listas de elementos migrados evolucionan.
Después: consolidar en torno a su instancia
Una vez validados los proyectos, la instancia pasa a ser el punto central de la cartera de la agencia. Para un registro más pesado, Harbor en un VPS puede tomar el relevo. Si su migración viene de otra herramienta de tickets, la guía de Jira a OpenProject o Plane sigue la misma lógica de inventario. Y si aún duda de la forja, el paso de GitLab a Gitea sigue siendo una opción más ligera.