miércoles, 31 de diciembre de 2008

Servidor Subversion

Hace poco he instalado un servidor SVN para que distintas personas puedan alojar sus proyectos. Vamos a ver cómo lo he hecho.

El primer paso ha sido, evidentemente, instalar Subversion:

aptitude install subversion


Claro que, para que todos los colaboradores puedan contribuir, tienen que poder acceder a los repositorios. Para ello hay dos métodos, un servidor especializado (svnserve) y el bueno de nuestro querido Apache con web-DAV.

Dados los problemas que puede presentar el servidor especializado con respecto a cortafuegos, proxys y similares, y dado que de todos modos vamos a usar Apache, que además nos permitirá navegar por la versión más reciente de cada repositorio, o incluso descargarlo con herramientas del tipo de wget, hacemos:

aptitude install apache2


Y claro, necesitamos que Apache y Subversion se entiendan:

aptitude install libapache2-svn


El primer paso de decisión es colocar los repositorios. La elección obvia sería /var/svn pero también se pueden considerar otras opciones como /srv/svn o /usr/lib/svn o incluso /usr/local/lib/svn.

Así, dentro de /var/svn tendremos un subdirectorio para cada repositorio completo. Ahora hay que convencer a Apache de que nos los muestre. Para ello, en el mismo directorio creamos un fichero como éste:

#Fichero /var/svn/repositorio_dav_svn.apache2.conf

<Location /svn/>
# Repositorio Subversion vía WebDAV
DAV svn

# Cualquier petición "/svn/algo" corresponderá al repositorio /var/svn/algo
SVNParentPath /var/svn

# Permitimos el listado de repositorios
SVNListParentPath on
</Location>


Con esta configuración ya podemos crear repositorios con
svnadmin create
y directamente los podremos utilizar desde otros ordenadores con órdenes del estilo de
svn co http://host/svn/repositorio
tanto para hacer checkout como commit.

¿O no?

Pues no. Hay dos detalles que se nos han quedado pendientes. El primero es que Apache no se entera de la existencia de ese fichero por arte de magia. Hay que decirle que hay un nuevo sitio disponible y que lo use:

ln -s /var/svn/repositorio_dav_svn.apache2.conf /etc/apache2/sites-available/repositorio_dav_svn
a2ensite repositorio_dav_svn
apache2ctl graceful


Sí, ya sé que sites-available está para configuraciones de tipo VirtualHost, pero es que prefiero dejar las cosas limpitas.

El segundo detalle es que al crear un repositorio con
svnadmin create repositorio
no podremos realizar commit en él, ya que Apache no puede escribir en el directorio. Por ello, ejecutamos

chgrp -R www-data repositorio
chmod -R g+w repositorio


Claro que puede que a los colaboradores no les maraville que todas las versiones de todos los proyectos estén disponibles a todo el mundo, y menos aún con acceso de escritura. Así que hay que hacer algo con los permisos, pero ya no puede ser sobre los repositorios, porque quien accede a ellos es Apache. Así que lo que hacemos es decirle a él que se encargue de la autentificación de usuarios y de su autorización.

Para ello, cogemos el fichero /var/svn/repositorio_dav_svn.apache2.conf de antes y lo modificamos un poco:

#Fichero /var/svn/repositorio_dav_svn.apache2.conf

# Esto es para evitar la incompatibilidad entre SVNListParentPath y AuthzSVNAccessFile
RedirectMatch ^(/svn)$ $1/

<Location /svn/>
# Repositorio Subversion vía WebDAV
DAV svn

# Cualquier petición "/svn/algo" corresponderá al repositorio /var/svn/algo
SVNParentPath /var/svn

# Permitimos el listado de repositorios
SVNListParentPath on

# Fichero de control de acceso por repositorios y ramas
AuthzSVNAccessFile /var/svn/authz

# Orden de prueba de usuarios
Satisfy Any
Require valid-user

# Método de autenticación y fichero de contraseñas
AuthType Digest
AuthDigestDomain http://miservidor/svn/
AuthName "Repositorio Subversion de miservidor"
AuthUserFile /var/svn/passwd-digest
</Location>


Hemos añadido cuatro piezas nuevas. La primera es para evitar un problema con las autentificaciones que puede surgir si se trata de ver el listado de repositorios, y las otras tres, ya dentro de la Location, configuran la autentificación y la autorización.

Ojo, que ese RedirectMatch está para algo, y es que AuthzSVNAccessFile da problemas si la barra final no está, así que es muy importante que la Location diga algo como <Location /svn/> y no <Location /svn> sin la barra final, aunque eso sea lo que viene en la documentación.

La autentificación es el último bloque. En él decimos que queremos que las contraseñas viajen cifradas (AuthType Digest), qué Reino de Autentificación (conjunto de dominios y subdirectorios en ellos) está en juego (es una manera de separar los accesos para distintos sitios con el mismo nombre de usuario, y también de agruparlos), que el cliente utiliza para no requerirnos cada vez el nombre de usuario y la contraseña (AuthDigestDomain http://miservidor/svn/), el nombre del Reino de Autentificación (para que el usuario sepa a qué corresponden el nombre de usuario y contraseña que debe introducir) que el cliente normalmente nos mostrará en el formulario (AuthName "Repositorio Subversion de miservidor") y, finalmente, en qué fichero almacenamos las parejas nombre de usuario-contraseña (AuthUserFile /var/svn/passwd-digest).

Este fichero hay que crearlo con la orden htdigest. Y ojo, que como vamos a utilizar autentificación por digest tenemos que activar el módulo correspondiente de Apache:

a2enmod auth_digest


Los otros dos bloques son el control de acceso. La parte

# Orden de prueba de usuarios
Satisfy Any
Require valid-user

hace que el acceso sin identificarse sea posible allí donde esté permitido. Si no lo ponemos, será imposible incluso acceder a la lista de repositorios sin identificarse. La otra parte simplemente indica qué fichero tiene la lista de control de acceso, es decir, qué nombres de usuario tienen permitido el acceso de lectura o de escritura a cada repositorio y a cada directorio de cada repositorio (AuthzSVNAccessFile /var/svn/authz). Este fichero tiene aproximadamente este aspecto:

# Fichero /var/svn/authz

# Acceso de lectura libre a todos sitios
# (es decir, al listado de repositorios) para todos
# y acceso de escritura al administrador del sitio
[/]
administrador = rw
* = r

# Permisos particulares para el repositorio repo1
# Añadimos permiso de escritura para algunos usuarios
# y quitamos el permiso de lectura para el usuario sin identificar
[repo1:/]
repo1admin = rw
repo1colaborador = rw
* =

# Quitamos el permiso de lectura al colaborador en determinado directorio
[repo1:/privado]
repo1colaborador =


Por supuesto, esta estructura puede complicarse bastante, y además los usuarios se pueden organizar en grupos. Hay más información en http://svnbook.red-bean.com/nightly/en/svn.serverconfig.pathbasedauthz.html.

Y adelante, ya tenemos un servidor Subversion preparado para aguantar lo que le echen.

No hay comentarios: