Llevo unos cuantos días navegando en un estado mental que hacía tiempo que no sufría. De hecho, hay en el Fallout 3 un perk (una mejora, vamos), cuyo nombre me vendría como anillo al dedo, para el caso: Nerd Rage!.
Y antes de que sigan leyendo, advertencia: la historia es lo más técnico que he escrito en mucho tiempo. De hecho, es lo más técnico que habré escrito en la corta historia de este blog (en el viejo ya hice de las mías). La historia va, en resumen, de cómo montar un servidor Mercurial de versiones en tu servidor sin volverte majareta (y mira que me ha costado).
Y ahora que he espantado a todos mis lectores, dejaré estas palabras como referencia para los que lleguen vía Google buscando cómo montar un puto servidor de Mercurial. Imaginen que es de noche, hay mucha niebla y estamos en Whitechapel. Por partes, pues.
¿Por qué Mercurial?
Tengo unos cuantos proyectos de documentación y desarrollo en mente, pero antes de acometerlos, quería montar en mi servidor casero un sistema de control de versiones. Si eres desarrollador, es posible que estés familiarizado con el CVS o con el Subversion. En mi empresa usamos Subversion de forma rutinaria para mantener las distintas versiones de cada pieza de código fuente, por ejemplo.
Sin embargo, ustedes me conocen, y saben que si hay una forma sencilla de hacer las cosas, será justamente la que no elija xD Hace tiempo leí un artículo de Joel Spolsky acerca de sistemas distribuidos de control de versiones o DVCS (Distributed Version Control System).
El artículo de Spolsky me convenció para intentar usar un DVCS. En realidad no era estrictamente necesario. Teniendo en cuenta que no tengo ningún proyecto con nadie, tampoco es que necesitara gran cosa, pero como les dije al principio, ya me conocen 😛
La cuestión era, ¿qué sistema usar? Yo solo conozco dos: Mercurial (el que menciona Spolsky en su artículo) y Git, usado, por ejemplo, para mantener el código del núcleo de Linux.
Me decidí por Mercurial porque Spolsky publicó una guía cojonuda para entender los conceptos de Mercurial si vienes del mundo de Subversion. Dicha guía se llama Hg Init, y es recomendable leerla de cabo a rabo para entender de qué va esto.
Dicho lo cual, pongámonos manos a la obra.
El escenario
Me he pegado varios días para montar el servidor, en parte porque tiempo no es que tenga mucho, y en parte porque nadie, repito, NADIE contaba en sus artículos un pequeño detalle vital para entender cómo funciona el servidor de Mercurial. Pero todo a su tiempo.
En esta guía trabajaremos con varias máquinas, a saber:
- Un servidor con Linux (Ubuntu, concretamente), que será en el que instalemos el servidor de Mercurial.
- Un cliente cuyo sistema operativo es Mac OS X Lion.
- Un cliente cuyo sistema operativo es Windows 7.
- Un cliente cuyo sistema operativo es Windows XP.
- Un cliente cuyo sistema operativo es Linux Mint.
Les comentaré qué hay que hacer en cada una de estas máquinas para tener el sistema funcionando.
Una peculiaridad del servidor de Mercurial es que no es realmente un servidor. En realidad consiste en unos cuantos binarios que ponen una capa sobre SSH para que puedas manejar ficheros en un repositorio de tu elección. Lo digo para que nadie espere ver un proceso mercurial-server
en segundo plano o algo así, porque no lo hay.
También debo mencionar un requisito indispensable: todas las máquinas tienen que tener OpenSSH o equivalente instalado. No voy a explicar en este artículo cómo hacerlo (excepto una breve mención en el caso de Windows, que como siempre, es el más raro).
La idea es que cuando vayamos a leer o escribir un fichero en el repositorio de código fuente de nuestro servidor, toda la comunicación se haga mediante el uso de claves públicas y privadas a través de SSH. Este artículo sobre SSH les dará bastante pistas al respecto.
Instalando Mercurial en el servidor
Aunque no se lo crean esta es la parte fácil. Vamos a suponer que mi servidor se llama Orthanc y mi usuario se llama adastra. Lo primero que tenemos que hacer es instalar los paquetes de mercurial
y mercurial-server
. Primero hay que poner en la lista de fuentes del sistema aquella de la que nos podemos bajar los paquetes de Mercurial. Para ello hay que modificar el fichero /etc/apt/sources.list e introducir esta línea (cambia lucid
por lo que corresponda a tu distribución de Linux):
deb http://mirrors.kernel.org/ubuntu lucid main universe
Luego solo hay que instalar los paquetes correspondientes:
$ sudo apt-get update
$ sudo apt-get install mercurial mercurial-server
Con esto ya tenemos instalado el servidor. Pero, por descontado, todavía no funciona ni de coña. A todo esto, hay dos sitios importantes que tienes que tener en cuenta:
- La carpeta de configuración del servidor está en /etc/mercurial-server. Ahí tendremos que trastear en breve.
- La carpeta con el repositorio central de Mercurial está en /var/lib/mercurial-server/repos. Esto es algo QUE NADIE MENCIONABA. Me volví loco pensando que la carpeta estaba en otro lado (ya les contaré).
Ahora hay otro pequeño detalle que casi todo dios pasaba por alto, y es la configuración del demonio de SSH para que admita conexiones con el usuario hg
, que es el usuario por defecto que tiene Mercurial para trastear con el repositorio que les he puesto ahí arriba.
Para arreglar esto, tenemos que modificar el archivo /etc/ssh/sshd_config, asegurándonos de tener, entre otras, estas líneas de configuración:
Port {El puerto que quieras usar, pero que no sea el 22}
Protocol 2
PermitRootLogin no
AllowUsers hg adastra {El resto de usuarios que quieras permitir}
RSAAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
PermitEmptyPasswords no
Una vez hecho esto, solo tenemos que reiniciar el servidor de SSH:
$ sudo service ssh restart
Claves públicas y privadas
Para que todo este tinglado funcione, tienen que cumplirse dos condiciones:
- Tienes que tener una clave pública en el servidor al que quieres conectarte.
- Tienes que tener una copia de tu clave privada en cada uno de los clientes desde los cuales quieres conectarte al servidor.
Si no te queda claro todo este rollo, puedes consultar la página de la Wikipedia sobre criptografía de clave pública.
Sin salir de nuestro servidor, vamos a generar un par de claves compuesto por una clave pública (la que se queda en el servidor) y una clave privada (la que va a los clientes). Ten en cuenta que tu clave pública es, eso, pública, así que la puedes poner a disposición de los demás sin problemas. Pero como tu clave privada quede comprometida, te verás con el culo al aire y cualquiera podrá entrar en tu servidor para hacer cosas malas. Avisado quedas.
Para generar las claves hacemos lo siguiente:
$ ssh-keygen -C adastra@Orthanc
Por supuesto, cambia el comentario de la orden a tu conveniencia. Después de ejecutarse la orden, se habrán generado dos ficheros en la ruta /home/{usuario}/.ssh, uno de los cuales será tu clave pública (id_rsa.pub) y el otro tu clave privada (id_rsa). Deja la clave pública ahí y copia la clave privada a un sitio seguro (como una IronKey o así).
Para acabar con el servidor, tenemos que decirle al servidor de Mercurial cuál es la clave pública a través de la cual un usuario podrá conectarse por SSH. Para ello, copiamos la clave pública (recordemos que está en /home/{usuario}/.ssh/id_rsa.pub) a la ruta /etc/mercurial-server/keys/root/{usuario}/id_rsa.pub. Ten en cuenta que bajo la ruta /etc/mercurial-server/keys/root/ no hay nada al principio, así que tendrás que crear a mano el directorio donde poner la clave pública.
Ya hemos terminado con el servidor, así que ahora vamos con los clientes.
Cliente Mac OS X
Lo primero es instalar los paquetes de Mercurial en nuestro Mac OS X, si no lo hemos hecho ya. Para comprobar que estén instalados solo hay que lanzar la terminal y averiguar el número de versión:
$ hg version
Lo siguiente es usar nuestra clave privada para conectarnos por SSH al servidor. Y para ello tenemos que conocer a nuestro amigo ssh-agent, otro del que nadie habla ¬¬
Verán, volviendo al tema de criptografía de clave pública, cuando te vas a conectar por SSH a un servidor empleando tu clave privada, tienes que cargar en la memoria del sistema dicha clave privada. Para ello se emplea normalmente un programa llamado ssh-agent, pero este programa tiene una peculiaridad: normalmente no arranca con el sistema.
Así pues, tenemos dos opciones: o lo ejecutamos cada vez que queramos conectarnos por SSH o lo cargamos desde el inicio con algún truco. Yo encontré la forma de cargar ssh-agent al inicio de sesión en Mac OS X.
Ahora ponemos cargar nuestra clave privada en memoria. Si ponemos la clave privada en /Users/{usuario}/.ssh/id_rsa, bastará con que hagamos:
$ ssh-add
En caso contrario, tendremos que especificar la ruta completa de la clave privada en la orden. Lo que prefieran. Si quieren comprobar que la clave ha quedado cargada pueden hacer:
$ ssh-add -l
¡Ya casi estamos! Para comprobar que realmente podemos conectarnos a nuestro servidor de Mercurial, vamos a traernos el repositorio de administración que éste tiene por defecto. Para ello ejecutamos lo siguiente:
$ hg clone ssh://hg@Orthanc:888/hgadmin
Ojo aquí. Lo que estamos haciendo es clonar (hg clone
) el repositorio llamado hgadmin
en el servidor Orthanc, que usa el puerto 888 (o el que sea) para conexiones SSH, usando el usuario hg.
Si todo ha ido bien, tendrás que ver una carpeta llamada hgadmin donde quiera que hayas ejecutado la orden.
Si quieres hacerlo a la inversa, poniendo un repositorio en el servidor, puedes hacer esta prueba:
$ mkdir Prueba
$ cd Prueba
$ hg init
$ touch foo.txt
$ hg add
$ hg commit -m "Prueba"
$ hg clone . ssh://hg@Orthanc:888/Prueba
Si todo ha salido bien, ahora habrá un repositorio en el servidor llamado Prueba (recuerda que estará en /var/lib/mercurial-server/repos/Prueba).
Cliente Windows XP
Tanto en Windows XP como en Windows 7 (o Windows Vista, si es que usas ese horror), tenemos la peculiaridad de que todo lo que tenga que ver con SSH es un poco atravesado.
Para resumir, que ya llevo escritas 1653 palabras, improperio arriba, improperio abajo, les recomiendo que se bajen TortoiseHg, un programa que trae todo lo que necesitarán para conectarse al servidor de Mercurial, incluyendo el propio cliente de Mercurial.
Recuerden que tenemos que traernos nuestra clave privada al cliente. Si quieren ponerla en el lugar canónico, pueden hacerlo en C:Documents and Settings{usuario}.sshid_rsa.
Lo siguiente que tenemos que hacer es decirle dos cosas al cliente de Mercurial:
- Cómo se va a llamar el usuario con el que operaremos.
- Cómo debe encontrar el cliente de SSH la clave privada.
Peeeeeeeeero, resulta que no nos vale la clave privada que generamos en primera instancia. Primero tendremos que convertirla a un formato que entienda TortoiseHg, y para ello usaremos el programa puttygen. Una vez descargado e instalado, convertimos la clave privada siguiendo este tutorial, y la guardamos en C:Documents and Settings{usuario}.sshid_rsa.ppk.
A continuación creamos un fichero de configuración que irá en la ruta C:Documents and Settings{usuario}mercurial.ini, que contendrá:
[ui]
user=adastra
ssh="C:Program FilesTortoiseHgTortoisePlink.exe" -ssh -2 -i "C:Documents and Settings{usuario}.sshid_rsa.ppk"
Vamos a probar que todo haya funcionado, como sigue, en una consola DOS:
C:> hg clone ssh://hg@Orthang:888/hgadmin
Si todo va bien, se habrá creado una carpeta C:hgadmin que nos habremos traído desde el servidor. Mira la sección sobre Mac OS X para que te hagas una idea de cómo subir tú mismo un proyecto al servidor.
Cliente Windows Vista/7
Bajo Windows Vista/7 hay que seguir los mismos pasos que bajo Windows XP, cambiando únicamente las rutas donde están las cosas importantes:
- La clave privada estará en C:Users{usuario}.sshid_rsa.
- La clave privada convertida al formato que TortoiseHg puede enteder estará en C:Users{usuario}.sshid_rsa.ppk.
- El fichero de configuración de Mercurial estará en C:Users{usuario}mercurial.ini.
Los contenidos del fichero de configuración son levemente diferentes:
[ui]
user=adastra
ssh="C:Program FilesTortoiseHgTortoisePlink.exe" -ssh -2 -i "C:Users{usuario}.sshid_rsa.ppk"
Para probar que todo funciona, haz exactamente lo mismo que en Windows XP.
Cliente Linux
Para finalizar, vayamos con el cliente Linux. Lo primero es asegurarnos de que tenemos instalado el paquete de Mercurial. Para ello seguiremos las mismas instrucciones que veíamos en el servidor, pero instalando solo el cliente:
$ sudo apt-get update
$ sudo apt-get install mercurial
Comprobamos que todo haya funcionado en una terminal:
$ hg version
Aquí volvemos a tener presente a nuestro amigo ssh-agent, y como en Mac OS X, tenemos que asegurarnos de que se cargue al inicio de la sesión. Para ello vamos a utilizar una herramienta llamada keychain, que instalaremos así:
$ sudo apt-get update
$ sudo apt-get install keychain
Acto seguido debemos modificar el fichero /home/{usuario}/.bash_profile, introduciendo lo siguiente:
/usr/bin/keychain $HOME/.ssh/id_rsa
source $HOME/.keychain/$HOSTNAME-sh
Si ponemos nuestra clave privada en /home/{usuario}/.ssh/id_rsa, este programa la cargará cada vez que la necesitemos. Por ejemplo, al intentar descargar el repositorio de administración de nuestro servidor:
$ hg clone ssh://hg@Orthanc:888/hgadmin
Conclusión
Si has llegado hasta aquí sin saltarte nada (excepto, quizás, las partes de los clientes que no te interesan), enhorabuena. Tienes resistencia mental como para enfrentarte a Nyarlathotep y darle una patada en los huevos sin tener que hacer una tirada por cordura.
Información sobre el servidor de Mercurial hay mucha. Toneladas de bytes. Pero ninguna cuenta de forma completa cómo funciona el asunto. No es que yo me haya extendido mucho (y no, no es un chiste; en realidad he pasado muy por encima de ciertos temas), pero por lo menos he intentado poner todo lo que he tenido que usar y configurar para que esto funcione.
Lo primero que me dio por saco fueron las claves públicas y privadas. No tenía claro dónde ponerlas ni cómo funcionaba el tema de ssh-agent (o pageant, si tienen curiosidad por instalar algo parecido en Windows).
Luego estaba el tema de dónde coño iba el repositorio del usuario hg. Lo vine a descubrir de pura chiripa porque a alguien le dio por preguntar por qué no podía bajarse el repositorio de administración y le contestaron diciéndole exactamente dónde están los repositorios y cuál era el fallo. Yo me mataba creando repositorios que luego no sabía dónde estaban.
A lo mejor alguien cae por aquí preguntando por estos temas. Si es así y tiene alguna duda, intentaré responder en los comentarios como buenamente pueda. Por lo menos respiro tranquilo con la satisfacción del deber cumplido.
Ahora, manos a la obra con mis proyectos ^^