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.

miércoles, 17 de diciembre de 2008

Esas pequeñas herramientas (I)

Hoy, UDP Cast.

UDP Cast es una herramienta que permite enviar un fichero a través de una red Ethernet a varios destinos a la vez. Para ello utiliza tramas Broadcast de Ethernet y direcciones multicast de IP.

Tiene dos usos principales, como programa instalado y como programa independiente. Como programa instalado, se puede utilizar en cualquier instalación de Unix (o de otros sistemas) para transmitir un fichero cualquiera. Así, el coste de distribuir un parche, por ejemplo, de un servidor a trescientos clientes es el mismo que el coste de distribuirlo a uno.

Como programa independiente, podemos arrancar varios ordenadores desde un disquete o un CD-ROM (o por PXE o por bootp o por...) y tras una configuración muy, muy sencilla, copiar discos completos o particiones entre sistemas, lo cual es enormemente útil para instalar aulas completas de ordenadores idénticos.

Por supuesto, en este caso hay que tener cuidado con las posibles diferencias en el hierro de los ordenadores, ya que discos o particiones de distinto tamaño o geometría, por ejemplo, pueden dar problemas.

En cualquier caso, siempre es bueno tener un par de discos de UDP Cast a mano.

martes, 2 de diciembre de 2008

Inestablemente estable


A veces, en Debian, uno tiene que instalar un paquete de una rama diferente a la que está utilizando. Por ejemplo, uno tiene un servidor instalado con la rama estable y tiene que instalar un determinado paquete de la rama de pruebas o de la inestable porque es la única manera de conseguir determinada característica.

Para entendernos, Debian tiene cuatro ramas: la estable (stable), la de pruebas (testing), la inestable (unstable) y la experimental (experimental). Normalmente el trabajo de desarrollo se hace en la inestable, y los programas que después de diez días en inestable no dan problemas se pasan a la rama de pruebas. Así, si se quiere estar siempre a la última hay que instalar el sistema con la rama inestable, pero es perfectamente posible que el sistema quede inutilizable. La rama de pruebas es la preferida por mucha gente que quiere estar a la última con sus escritorios pero sin arriesgarse a que todo quede parado, mientras que la rama estable es ideal para servidores o para administrar grandes conjuntos de máquinas iguales.

Por su parte, la rama experimental tiene versiones demasiado inestables incluso para la rama inestable. De hecho no es una rama completa, uno no puede instalar un sistema complete utilizando solamente paquetes de esta rama.

Pues bien, se me ha dado el caso de que en un ordenador con la rama de pruebas instalada necesité instalar ImageMagick, pero resulta que la versión de este programa que viene en esta rama (la 6.3.7.9) utiliza como compresor MPEG el programa mpeg_encode, que no existe en Debian. En cambio, la versión de la rama experimental es la 6.4.5.4 que utiliza ffmpeg, que sí está disponible.

La primera opción es bajarse el imagemagick de experimental e instalarlo a mano. Esto se empieza a complicar cuando uno descubre que necesita dos librerías más, también de experimental, y cambiar la versión de otro paquete que también tiene dependencias.

Y claro, uno se pregunta "¿Para qué tengo que hacer todo esto si es justo el tipo de cosas que le encanta a apt?"

La solución:

Lo primero, hay que dejarle bien claro a apt qué rama queremos utilizar normalmente:

#/etc/apt/apt.conf

APT::Default-Release "testing";


Lo segundo, hay que tener las fuentes de la rama que necesitamos, aparte de las fuentes de la rama que tenemos normalmente:

#/etc/apt/sources.list

# Fuentes remotas de paquetes
deb http://ftp.es.debian.org/debian/ stable main contrib non-free
deb http://ftp.es.debian.org/debian/ testing main contrib non-free
deb http://ftp.es.debian.org/debian/ unstable main contrib non-free
deb http://ftp.es.debian.org/debian/ experimental main contrib non-free

# Actualizaciones de seguridad
deb http://security.debian.org/ stable/updates main contrib non-free
deb http://security.debian.org/ testing/updates main contrib non-free


Y listo. Actualizamos las listas de paquetes con aptitude update o apt-get update (o dselect o Synaptic o lo que cada uno prefiera) y ya estamos preparados para indicarle al sistema lo que queremos:

# aptitude install imagemagick/experimental
Leyendo lista de paquetes... Hecho
Creando árbol de dependencias
Leyendo la información de estado... Hecho
Leyendo la información de estado extendido
Inicializando el estado de los paquetes... Hecho
Leyendo las descripciones de las tareas... Hecho
Los siguientes paquetes están ROTOS:
libmagickcore1
Se instalarán los siguiente paquetes NUEVOS:
ghostscript{a} gsfonts{a} imagemagick imagemagick-doc{a} libcupsimage2{a} libgd2-noxpm{a} libgomp1{a} libgraphviz4{a}
libgs8{a} libilmbase6{a} libjasper1{a} libltdl3{a} libmagickwand1{a} libopenexr6{a} libpaper-utils{a} libpaper1{a}
libwmf0.2-7{a} psfontmgr{a}
0 paquetes actualizados, 19 nuevos instalados, 0 para eliminar y 0 sin actualizar.
Necesito descargar 13,7MB de ficheros. Después de desempaquetar se usarán 48,4MB.
No se satisfacen las dependencias de los siguientes paquetes:
libmagickcore1: Depende: libdjvulibre21 (>= 3.5.21) pero no es instalable
Las acciones siguientes resolverán estas dependencias

Instalar los paquetes siguientes:
libdjvulibre-text [3.5.21-1 (unstable)]
libdjvulibre21 [3.5.21-1 (unstable)]

La puntuación es 12

¿Acepta esta solución? [Y/n/q/?]
Se instalarán los siguiente paquetes NUEVOS:
ghostscript{a} gsfonts{a} imagemagick imagemagick-doc{a} libcupsimage2{a} libdjvulibre-text{a} libdjvulibre21{a}
libgd2-noxpm{a} libgomp1{a} libgraphviz4{a} libgs8{a} libilmbase6{a} libjasper1{a} libltdl3{a} libmagickcore1{a}
libmagickwand1{a} libopenexr6{a} libpaper-utils{a} libpaper1{a} libwmf0.2-7{a} psfontmgr{a}
0 paquetes actualizados, 21 nuevos instalados, 0 para eliminar y 0 sin actualizar.
Necesito descargar 14,4MB de ficheros. Después de desempaquetar se usarán 50,5MB.
¿Quiere continuar? [Y/n/?]
Escribiendo información de estado extendido... Hecho
Des:1 http://ftp.fr.debian.org testing/main libcupsimage2 1.3.8-1lenny2 [98,5kB]
Des:2 http://ftp.fr.debian.org testing/main libpaper1 1.1.23+nmu1 [20,6kB]
Des:3 http://ftp.fr.debian.org testing/main libgs8 8.62.dfsg.1-3.1 [2219kB]
Des:4 http://ftp.fr.debian.org testing/main gsfonts 1:8.11+urwcyr1.0.7~pre44-3 [3373kB]
Des:5 http://ftp.fr.debian.org testing/main ghostscript 8.62.dfsg.1-3.1 [766kB]
Des:6 http://ftp.fr.debian.org testing/main libgomp1 4.3.2-1 [13,2kB]
Des:7 http://ftp.fr.debian.org unstable/main libdjvulibre-text 3.5.21-1 [74,4kB]
Des:8 http://ftp.fr.debian.org unstable/main libdjvulibre21 3.5.21-1 [682kB]
Des:9 http://ftp.fr.debian.org testing/main libgd2-noxpm 2.0.36~rc1~dfsg-3 [221kB]
Des:10 http://ftp.fr.debian.org testing/main libltdl3 1.5.26-4 [177kB]
Des:11 http://ftp.fr.debian.org testing/main libgraphviz4 2.20.2-3 [536kB]
Des:12 http://ftp.fr.debian.org testing/main libilmbase6 1.0.1-2+nmu2 [118kB]
Des:13 http://ftp.fr.debian.org testing/main libjasper1 1.900.1-5.1 [145kB]
Des:14 http://ftp.fr.debian.org experimental/main libmagickwand1 7:6.4.5.4.dfsg1-1 [332kB]
Des:15 http://ftp.fr.debian.org testing/main libopenexr6 1.6.1-3 [262kB]
Des:16 http://ftp.fr.debian.org testing/main libwmf0.2-7 0.2.8.4-6 [174kB]
Des:17 http://ftp.fr.debian.org experimental/main libmagickcore1 7:6.4.5.4.dfsg1-1 [1667kB]
Des:18 http://ftp.fr.debian.org experimental/main imagemagick 7:6.4.5.4.dfsg1-1 [86,1kB]
Des:19 http://ftp.fr.debian.org experimental/main imagemagick-doc 7:6.4.5.4.dfsg1-1 [3410kB]
Des:20 http://ftp.fr.debian.org testing/main libpaper-utils 1.1.23+nmu1 [17,6kB]
Des:21 http://ftp.fr.debian.org testing/main psfontmgr 0.11.10-0.2 [22,2kB]
Descargados 14,4MB en 3min47s (63,5kB/s).
Preconfigurando paquetes ...
[...]
Leyendo lista de paquetes... Hecho
Creando árbol de dependencias
Leyendo la información de estado... Hecho
Leyendo la información de estado extendido
Inicializando el estado de los paquetes... Hecho
Escribiendo información de estado extendido... Hecho
Leyendo las descripciones de las tareas... Hecho


Como se puede ver, la barra al final del nombre del paquete indica "quiero este paquete de esta rama", y el sistema ha bajado el paquete de experimental, y sus dependencias, mientras fue posible, de la rama actual, la de pruebas. Además, las actualizaciones del sistema no darán problemas diciendo siempre "hay nuevos paquetes disponibles" cuando esos paquetes no sean de la rama actual.