Servidor GitLab de acceso privado

Buenas a todos!! Últimamente he estado liado a programar y me ha surgido la idea de montar un servicio privado en el cual me sea fácil mantener mis proyectos personales de forma privada pero accesible.

La idea será tener en nuestra infraestructura de servidores virtuales (VPS) una máquina dedicada, que tendrá poca exigencia de recursos y por tanto podremos configurar con el mínimo necesario de recursos. Realmente podríamos realizar algo más manual y manejar una configuración de servidor Git con bare repositories (podéis ver un buen tutorial aquí), pero una interfaz web de gestión como la que nos proporciona GitLab facilita mucho el trabajo.

Además, si en el futuro queremos abrir al exterior el servicio, podemos hacerlo fácilmente y realizar de una forma mucho más sencilla la gestión de usuarios. Otro escenario en el que podríamos querer tener una instancia privada de GitLab podría ser un ámbito empresarial en el que quieras tener un acceso y control total de todo lo que pasa en tu control de versiones.

Vamos entonces a ello. Lo primero será elegir nuestro proveedor para el VPS. A mí me gusta DigitalOcean, pero podéis elegir AWS, Azure, Google Cloud, OVH… lo que queráis. Por seguir un ejemplo concreto, vamos a hacerlo en DigitalOcean, que tiene una interfaz muy sencilla. Además, te regalan 100$ de crédito para gastar en 2 meses si vienes referido por un usuario actual, y al usuario que te invite le dan 25$ cuando tú pagues otros 25$. Post no patrocinado por DigitalOcean, pero oye, que está interesante (gracias a un compi por el chivatazo).

En caso de que utilices otro proveedor, puedes saltarte esta sección.

Creación del Droplet en DigitalOcean

Crearemos lo primero un Droplet (así se llaman en DigitalOcean las plantillas para las máquinas) yendo al botón superior Create y seleccionando Droplets. Elegiremos un sistema operativo Debian para este ejemplo, pero de nuevo esto va a gusto de cada uno. También al gusto, o más bien al presupuesto, irá el plan de configuración que elijamos. Para este caso nos bastará con el más básico, con 1CPU y 1GB de RAM.

Seleccionaremos (aunque es opcional) el servicio de Backups, que por 1$/mes nos realizará un backup semanal y podremos remontarnos a los 4 backups anteriores. Nunca viene mal ir sobre seguro.

Podemos añadir un bloque de almacenamiento si vemos que se nos queadn cortos los 25GB que trae el plan básico, pero para este ejemplo no lo haremos. Elegid el centro de datos de la región que más os apetezca, teniendo en cuenta siempre que cuanto más cercano menos latencia (aunque suele haber poca diferencia).

No seleccionaremos otra opción adicional de las que se nos ofrecen en Select additional options, pero podría ser interesante crear la interfaz de red privada.

Añadiremos una clave SSH pública para poder realizar autenticación en la máquina con este método, de forma que nos ahorramos algún que otro sustillo. Nos podría servir también una clave precompartida muy muy larga, pero es más seguro usar la clave privada que esté además cifrada. Tenéis aquí como crear el par de claves en Windows con PuttyGen y aquí cómo hacerlo en Linux con OpenSSL.

Una vez creada podemos pulsar en New SSH Key y pegar en el campo que aparece el contenido de la clave pública.

Una vez agregada aparecerá en el formulario como seleccionable. Evidentemente, la seleccionamos.

Por último elegimos el hostname de la máquina, que en este caso será PruebasGitLab, y haremos click en Create para que comience el despliegue. En un par de minutos como mucho tendremos la máquina lista para usarse.

En el Dashboard de DigitalOcean o el equivalente del proveedor que sea podremos ver ya nuestra máquina creada y su dirección IP para conectarnos. Nos conectaremos por tanto a ella mediante SSH utilizando la clave privada.

ssh -i <clave_privada> <ip_maquina>

Se nos pedirá la clave de cifrado de la clave privada para poder utilizarla y ya podremos estar dentro, una vez aceptada la clave pública de la máquina virtual como confiable, lo habitual.

Agregar memoria SWAP a la máquina

De forma predeterminada, DigitalOcean y otros, para ahorrar espacio en disco, no crean una partición SWAP en las máquinas, lo cual nos limita a la hora de hacer reservar uso de memoria para los programas. GitLab, por ejemplo, necesita algo más que 1GB de RAM, haciendo necesario el uso de SWAP.

No os preocupéis, la solución es sencilla. Crearemos un fichero SWAP, que tendrá la misma función que una partición de dicho tipo, y haremos que se monte automáticamente en el arranque de la máquina.

Para la creación del fichero SWAP de 1GB (como administrador):

fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon --show

Podemos con ese último comando verificar que la SWAP está montada y en uso. Podemos también revisar la salida del comando free.

Agregarmos por último las siguientes líneas al fichero /etc/fstab de manera que el fichero SWAP se monte con el inicio del sistema:

/swapfile swap swap defaults 0 0

Instalación de GitLab

Una vez ya con acceso dentro de la máquina, tal vez queramos ejecutar algunos pasos de securización, como un poco de tuneo del servicio SSH (no permitir el acceso directo con root, permitir el acceso con la clave de acceso al usuario debian u otro, cambiar el puerto predeterminado…), la configuración de un Firewall (ya sea UFW, FirewallD o directamente IPTables) y el uso del servicio fail2ban para prevenir la fuerza bruta y otros floodings. Pero esto da para otra entrada 🙂 Vamos a centrarnos en lo que nos ocupa.

El paso siguiente es actualizar la máquina. Tranquilos, no se rompe, no es Kali Linux. Para hacerlo de forma rápida y desatendida:

apt update && sudo apt dist-upgrade -y

Hecho esto, instalaremos algunas dependencias de GitLab:

apt install ca-certificates curl openssh-server postfix

En la instalación de Postfix le diremos qsue queremos configurarlo como Internet Site. Dejaremos de momento el mail name predeterminado, el nombre de la máquina que tomará Postfix, dado que no tenemos un dominio asignado a la máquina.

Lo siguiente será descargar un script, ofrecido por el mismo GitLab, que agrega los repositorios necesarios a nuestra máquina para instalar y mantener actualizado el servicio. Una vez descargado, lo ejecutaremos.

curl -LO https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh
bash script.deb.sh

Por último, instalaremos en sí el paquete correspondiente a GitLab:

Hecho esto, se nos mostrará un mensaje de éxito muy majo en el que además se nos indica que procedamos a la configuración.

Editaremos ahora el fichero /etc/gitlab/gitlab.rb y en la línea external_url indicaremos la dirección localhost como enlace HTTP, dado que como vamos a ver a continuación tendremos el servicio solamente de puertas para adentro. Además, descomentaremos (o copiaremos debajo descomentada) la línea nginx[‘listening_addresses’] y le daremos un valor [‘localhost’].

Acto seguido ejecutaremos el siguiente comando para que GitLab cargue los ficheros de configuración y con ellos se autoconfigure:

gitlab-ctl reconfigure

Tras unos largos minutos, tendremos el servicio ya corriendo correctamente, cosa que podemos comprobar con un pequeño netstat:

netstat -tupln

Vemos ya un buen número de servicios, relacionados con GitLab, destacando la base de datos PostgreSQL y el servidor web Nginx corriendo en localhost.

Acceso a GitLab

Pero, ¿cómo accedemos al servicio? ¡Solo tenemos la consola y esto va por una web solo accesible desde localhost! Y para más inri, si lo hemos securizado, hay también Firewall de por medio.

Esto lo hemos hecho aposta. Esta máquina va a tener una superficie de exposición lo más reducida posible. Para ello, accederemos al servicio web de forma segura mediante un túnel SSH desde nuestra máquina local hasta el VPS.

El comando para hacerlo es muy sencillo:

ssh -i <clave_privada> -fN -L 8080:localhost:80 <usuario>@<ip_maquina>

Una breve explicación de los parámetros:

  • -f indica que la sesión SSH se ejecutará en background.
  • -N indica que no se entregará una línea de comandos a la sesión.
  • 8080:localhost:80 indica que nuestro puerto 8080 local dirigirá a localhost:80 de la máquina objetivo, es decir, el servicio ofrecido a la dirección localhost de la máquina.
  • Por último indicamos el usuario y dirección IP pública de la máquina.

El resultado como podremos comprobar es que hay un proceso SSH corriendo en segundo plano y que abriendo la dirección localhost:8080 en un explorador web local podremos ver ya la página inicial de establecimiento de contraseña de GitLab.

El proceso a partir de aquí es muy sencillo. Rellenamos la nueva contraseña y nos podremos loguear en la página siguiente con el usuario predeterminado root y la contraseña que hayamos elegido. Fijaos además de que existe un formulario de registro de usuarios, dado que la plataforma de forma predeterminada ya es totalmente funcional y admite nuevos usuarios.

Y ya tendremos nuestra instancia de GitLab preparada para utilizarse 🙂 Como prueba de que todo va bien, vamos a crear un nuevo proyecto llamado PruebaProyecto y subir una simple página Readme.md de prueba haciendo uso de Git.

Vemos la opción de incluir ya un Readme, pero ¿qué gracia tendría? Si vamos a subirlo nosotros!! Por lo demás, los campos son bastante autoexplicativos. La URL del proyecto será http://localhost:8080/root/pruebaproyecto, concatenando la dirección que ha detectado en el explorador, nuestro nombre de usuario al ser el dueño del repositorio, y el campo Project Slug, que es simplemente el identificador que queremos darlo en la URL.

Esto está muy bien y podemos desde una sesión desde la misma máquina clonar el proyecto, obviando el puerto 8080, que desde la propia máquina será el 80.

Asimismo podemos hacer lo mismo desde nuestra máquina local mientras esté habilitado el túnel SSH hasta la máquina a nuestro puerto 8080. Esto compensa el hecho de que estamos realizando, al menos en esta prueba, el protocolo HTTP para realizar las subidas y bajadas del repositorio, dado que el túnel SSH ya proporciona una comunicación cifrada.

Interacción vía SSH

El problema es que no suele ser conveniente o cómodo tener que levantar un túnel en cada sitio que estemos desarrollando. Vamos a configurar entonces una clave SSH en GitLab de forma que podamos realizar el control de versiones mediante este protocolo. Lo primero será crear una nueva clave dentro de la máquina, para no utilizar la misma que la de acceso a la máquina en sí:

ssh-keygen -o t rsa -b 4096 -C "git@localhost"

Una vez creado el par de claves, copiaremos el contenido de la clave pública en GitLab. Para ello nos dirigimos a la configuración (haciendo click en nuestro avatar de usuario arriba a la derecha y clicando Settings) abriremos la configuración SSH Keys a la izquierda. Debemos simplemente pegar aquí el contenido de la clave pública y darle un título o alias.

Hacemos click en Add key y ya tenemos la clave agregada. Nos la bajamos a la máquina local utilizando SCP:

Podemos ahora descargar el repositorio de la siguiente forma:

GIT_SSH_COMMAND="ssh -i <clave_privada_git>" git clone git@<ip_maquina>:root/pruebaproyecto.git

Con esto estamos estableciendo una variable global que se utilizará únicamente al invocar el comando git actual y que le indica que debe utilizar una clave privada y dónde encontrarla. Indicamos simplemente el usuario git y el repositorio de forma muy parecida a la sintaxis de SCP, y si todo ha ido correctamente ya tendremos nuestro repositorio en local.

Nos introducimos en el proyecto descargado, aún vacío (en realidad hay un directorio .git oculto), e introduciremos un par de líneas en un nuevo fichero Readme.md. Tras ello, agregamos los nuevos ficheros al control de versiones con git add -A y comprobamos que se ha agregado correctamente con git status.

Para realizar un commit tendremos que ejecutar los comandos git config user.email «<email>» y git config user.name «<user>» para establecer a nivel de repositorio con qué usuario realizamos el commit. Si queremos dejarlo establecido a nivel global (no lo recomiendo) agregamos la opción –global. Ahora ya podemos realizar un commit con git commit -m «<mensaje_commit>».

Por último ejecutamos git push con la misma variable modificadora que utilizábamos a la hora de hacer el clonado. Tendremos que utilizarla siempre que interactuemos con el repositorio remoto para decirle a git dónde encontrar la clave privada, como decíamos.

Si planeamos lanzar muchos comandos siempre podemos dejar la variable definida de forma global en la sesión invocando simplemente en bash:

GIT_SSH_COMMAND="ssh -i <clave_privada_git>"

Si nos dirigimos ahora al proyecto en la página de GitLab podemos ver ya actualizado el proyecto con el nuevo Readme.md:

Ya tenemos todo listo y configurado para poder empezar a realizar el control de versiones de nuestro proyectos de forma aislada, privada y totalmente bajo nuestro control 🙂

Espero como siempre que os haya gustado la entrada y os sirva para aprender. Cualquier cosa ya sabéis dónde encontrarme. Un saludo!!