Archivo de Etiquetas de 'debian'

Subversion desde Apache usando virtual hosts y locations

Aunque hay bastantes guías que cubren cómo configurar un WebDAV para acceder a un repositorio Subversion mediante HTTP usando el servidor Apache, aquí os presento la mía, en la que configuro el acceso a un conjunto de repositorios usando un virtual host y distintas locations (es decir, es una guía más con la configuración que a mi más me gusta :D ).

Lo primero que debemos hacer es asegurarnos de que tenemos el módulo adecuado. En Debian, por ejemplo, podemos buscarlo e instalarlo si es necesario usando los siguientes mandatos:

$ aptitude search apache subversion | grep svn
# aptitude install libapache2-svn

Además, deberemos asegurarnos de que Apache habilita el módulo, lo cual, nuevamente en Debian, es trivial gracias a la buena organización que tiene de la configuración de Apache:

$ a2enmod dav_svn
# /etc/init.d/apache2 restart

El siguiente paso es crear un repositorio Subversion. Lo habitual es crear uno por proyecto, aunque en mi caso no lo hago así exactamente. Por ejemplo, tengo un repositorio al que llamo personal en el que tengo mi CV, algunas prácticas y cosas pequeñas en las que es más que improbable que participe nadie más que yo. Depende del criterio de cada uno (por ejemplo, a mi siempre me resulta tentador tener un único respositorio para todo, y a la hora de hacer el checkout, hacerlo con ruta relativa al proyecto que necesito), pero recordad que los usuarios, contraseñas y permisos serán los mismos para todo un repositorio. La creación del repositorio la hacemos con los mandatos:

$ mkdir -p /opt/svn/nombre_del_repositorio/
$ svnadmin create /opt/svn/nombre_del_repositorio/repo

Podemos verificar que funciona intentando hacer un checkout:

$ svn co file:////opt/svn/nombre_del_repositorio/repo /tmp/

Por último, creamos los usuarios y passwords del repositorio:

$ mkdir -p /opt/svn/nombre_del_repositorio/passwords/
$ htpasswd -c /opt/svn/nombre_del_repositorio/passwords/.htpasswd usuario

Y procedemos a crear el fichero de configuración del virtual host de Apache. En el ejemplo, lo voy a hacer para dos repositorios, uno llamado personal y otro llamado público, suponiendo que quiera acceder a ambos a través del mismo dominio (svn.deigote.com) pero con distintas localizaciones (/personal y /publico):

<VirtualHost *:80>
   ServerName svn.deigote.com
   DocumentRoot /opt/websites/svn.deigote.com

Como véis, definimos un virtual host para el dominio elegido, y le asignamos un docroot, en el que podríamos poner una página de inicio o incluso vacía (para que si alguien entra directamente en el dominio, no vea el clásico It works! situado en /var/www :D )(1).

A partir de aquí, para cada localización (personal y publico) establecemos que es un WebDAV de tipo Subversion, e indicamos la ruta del repositorio y del fichero de passwords, tanto para el repositorio personal:

   <Location "/personal" >
     DAV svn
     SVNPath /opt/svn/personal/repo

     AuthType Basic
     AuthName "SVN Deigote - Personal"
     AuthUserFile /opt/svn/personal/passwords/.htpasswd
     Require valid-user

     Order deny,allow
     Deny from all
     Allow from unaipdeconfianza.com
   </Location>

como para el repositorio público:


   <Location "/publico" >
     DAV svn
     SVNPath /opt/svn/publico/repo

     AuthType Basic
     AuthName "SVN Deigote - Publico"
     AuthUserFile /opt/svn/publico/passwords/.htpasswd
     <LimitExcept GET PROPFIND OPTIONS REPORT>
       Require valid-user
     </LimitExcept>
   </Location>

Podemos ver un par de diferencias. Mientras que el repositorio personal pide un usuario válido para todos los casos (es decir, un usuario definido en el fichero de passwords), el repositorio público especifica que necesita un usuario válido excepto para algunas acciones. Básicamente, son el conjunto de acciones que permiten lectura y navegación por el repositorio. De esta manera, todo el mundo podrá ver (acciones checkout, update, etcétera) pero sólo los usuarios válidos podrán escribir (acción commit, add, etcétera) (2)

La otra diferencia es que el repositorio personal tiene una sección que especifica que el acceso es denegado para todos, y admitido para una ip o nombre de dominio. Esto te garantiza que la persona que accede a tu repositorio lo está haciendo desde una IP de tu confianza, aumentando ligeramente la paranoia seguridad.

Añadir que el directorio raiz (/) es un location válido, por lo que podemos configurar un único repositorio para el dominio, aunque sería equivalente a poner dicha configuración directamente en el contexto del virtual host en vez de en el del location.

Añadiendo la información de logs y demás, el fichero de virtual host de ejemplo (/etc/apache2/sites-available/svn.deigote.com) queda como se ve a continuación:

<VirtualHost *:80>
   ServerName svn.deigote.com
   DocumentRoot /opt/websites/svn.deigote.com
   <Location "/personal" >
     DAV svn
     SVNPath /opt/svn/personal/repo

     AuthType Basic
     AuthName "SVN Deigote - Personal"
     AuthUserFile /opt/svn/personal/passwords/.htpasswd
     Require valid-user

     Order deny,allow
     Deny from all
     Allow from unaipdeconfianza.com
   </Location>

   <Location "/publico" >
     DAV svn
     SVNPath /opt/svn/publico/repo

     AuthType Basic
     AuthName "SVN Deigote - Publico"
     AuthUserFile /opt/svn/publico/passwords/.htpasswd
     <LimitExcept GET PROPFIND OPTIONS REPORT>
       Require valid-user
     </LimitExcept>
   </Location>

   ErrorLog /var/log/apache2/error_svn.deigote.com.log
   LogLevel warn
   CustomLog /var/log/apache2/access_svn.deigote.com.log combined
</VirtualHost>

Lo añadimos a la lista de sites y reiniciamos Apache, y ya estamos listos para jugar:

$ a2ensite svn.deigote.com
$ /etc/init.d/apache restart
$ svn co http://svn.deigote.com/personal
$ svn co http://svn.deigote.com/publico

Como nota final, ojo con los passwords. Tened en cuenta que estamos configurando un acceso a través de HTTP, por lo que la información no va encriptada. Para que sí lo fuera tendríamos que configurar el virtual host para ir a través de HTTPS, pero eso lo dejamos para un próximo capítulo (más que nada porque todavía no he aprendido a hacerlo :) ).

(1) Tened cuidado de no crear directorios en el document root con el mismo nombre que los location. Os encontraréis con un error de este estilo al hacer el checkout:

$ ls /opt/websites/svn.deigote.com # Docroot
personal
$ svn co http://svn.deigote.com/personal/ /tmp/personal
Authentication realm: SVN Deigote - Personal
Password for 'deigote':
svn: PROPFIND request failed on '/personal'
svn: PROPFIND of '/personal': 301 Moved Permanently (http://svn.deigote.com)
$ rmdir /opt/websites/svn.deigote.com/personal
$ svn co http://svn.deigote.com/personal/ /tmp/personal
...
Checked out revision 1

(2) Se puede afinar más usando mod_authz_svn, que permite establecer qué usuarios pueden escribir y cuáles pueden leer sin complicarse mucho, pero yo de momento no lo he necesitado, así que queda para el siguiente capítulo :-)

Ruby On Rails + Passenger + Apache + MySQL + SQLite en Debian 5

Por motivos que ya saldrán a la luz :D he actualizado mi fantabulosa aplicación en Ruby On Rails MyBestLap para que funcione en Ruby On Rails 2.3.2 usando Passenger con Apache 2 en una Debian 5 versión servidora.

Como me ha resultado un pelín farragoso, he decidido publicar los pasos por si alguien se ve en una situación parecida.

  1. Instalando Ruby
  2. Instalando Rubygems
  3. Instalando Rails
  4. Instalando SQLite y MySQL
  5. Instalando Passenger

Instalando ruby

Personalmente, cuando trabajo con Rails (en realidad, con Ruby en general), prefiero tener una instalación basada en Rubygems en lugar de usar el sistema de paquetes de la distribución. Aunque a priori puede parecer peor, a la larga resulta más cómodo (puedes escoger la versión que necesitas y no dependes de que la gema esté disponible como paquete para tu distro, además de que te permite escoger la versión de Ruby, mientras que las gemas precompiladas sólo suelen estar para la versión estable) y más coherente (ya que, como no todas las gemas están disponibles como paquetes, acabas instalando algunas mediante gem y otras mediante el gestor de paquetes, en mi caso aptitude, siendo más complicado identificar qué tienes instalado.).

Por lo tanto, de momento sólo instalaremos el intérprete de ruby y los paquetes de documentación y la shell interactiva, es decir:

sudo aptitude install ruby ri1.8 rdoc1.8 irb1.8

Que en Debian 5 por defecto se traduce en la instalación de la versión 1.8 del intérprete (aunque la 1.9 también está disponible). Los siguientes enlaces simbólicos nos serán útiles si el paquete no los ha creado (para verlo, dpkg -L nombre_del_paquete):

cd /usr/local/bin
sudo ln -s /usr/bin/irb1.8 irb
sudo ln -s /usr/bin/rdoc1.8 rdoc
sudo ln -s /usr/bin/ri1.8 ri

Instalando rubygems

Debido a que el paquete rubygems tiene algunas restricciones en Debian que no te permiten usar todas las opciones, y la versión no es la más moderna, optaremos por una instalación a la vieja usanza :) . Aunque asuste, los pasos son realmente sencillos:

mkdir tmp
cd tmp
wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz
tar zxvf rubygems-1.2.0.tgz
cd rubygems-1.2.0
sudo ruby setup.rb
sudo ln -s /usr/bin/gem1.8 /usr/local/bin/gem
gem --version

A continuación, nos aseguramos de que tenemos la última versión de rubygems (1), instalando la gema rubygems-update, que sirve para actualizar rubygems (mola :D ):

gem list -r | grep update
sudo gem install rubygems-update
sudo update-rubygems
gem --version

Como habréis observado, no me he preocupado del path a la hora de lanzar el mandato update-rubygems. Rubygems hace una cosa que bajo mi punto de vista es un gran error, pero que facilita el mantenimiento del path: copia los binarios de cada gema en /usr/bin (primer error, copiarlo a /usr/bin en vez de /usr/local/bin, ya que es una instalación local, segundo error, ¿¿porqué copiar en vez de enlazar simbólicamente??, supongo que la respuesta es que Ruby es multiplataforma y por defecto no permite enlaces simbólicos, como le pasa a Java, aunque quizá sea otra cosa).

A partir de aquí, al instalar algunas gemas (en el ejemplo, sqlite3-ruby), obtendremos un error del tipo

Building native extensions. This could take a while...
ERROR: Error installing sqlite3-ruby:
ERROR: Failed to build gem native extension.
/usr/bin/ruby1.8 extconf.rb
extconf.rb:1:in `require': no such file to load -- mkmf (LoadError)
from extconf.rb:1
Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4 for inspection.
Results logged to /usr/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4/ext/sqlite3_api/gem_make.out

Esto es debido a que necesitamos las librerías de desarrollo de Ruby, ya que vamos a compilar cada gema. Por tanto, las instalamos como paquete, ya que el interprete también lo hemos instalado de esa manera:

sudo aptitude install ruby-dev

Instalando Rails

El siguiente paso es instalar Rails, con un sencillo gesto de dedos :) :

sudo gem install rails

Podéis especificar la versión que necesitáis, pero en mi caso he decido ir a por la que se instala por defecto, una moderna Rails 2.3.2.

Instalando MySQL y SQLite

Aunque existen otras posiblidades, MySQL y SQL suelen ser los gestores de base de datos usados para la persistencia en una aplicación Rails. Normalmente, SQLite se usa en el entorno de desarrollo y MySQL en el de producción, aunque estoy convencido de que la mayoría de aplicaciones (incluyendo la mía :D ) se apañarían con SQLite (que no pase hambre).

La instalación de ambas gemas es sencilla, aunque requieren instalar algunos paquetes adicionales. Aquí, lo más habitual es instalar todo lo que huela al paquete a instalar (empezaremos por SQLite), pero realmente no es necesario, y yo prefiero instalar lo mínimo necesario, sobretodo en un servidor de producción. El truco, valido también para cuando estamos compilando una aplicación Linux (con el clásico configure + make + make install), es instalar los paquetes del tipo libcosadelaquedependes y libcosadelaquedependes-dev, que contienen las librerías necesarias para la ejecución y compilación de otros programas o librerías que dependan de cosadelaquedependes.

Así, para SQLite, buscamos la gema que queremos instalar:

gem list -r | grep sqlite

y nos quedamos con la que tiene el nombre más prometedor, sqlite3-ruby :) . Si la intentamos instalar, posiblemente obtengamos un mensaje similar a:

gem install sqlite3-ruby
Building native extensions. This could take a while...
ERROR: Error installing sqlite3-ruby:
ERROR: Failed to build gem native extension.
/usr/bin/ruby1.8 extconf.rb
checking for fdatasync() in -lrt... yes
checking for sqlite3.h... no
make
make: *** No hay ninguna regla para construir el objetivo `ruby.h', necesario para `sqlite3_api_wrap.o'. Alto.
Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4 for inspection.
Results logged to /usr/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4/ext/sqlite3_api/gem_make.out

Si os fijáis, le falta el fichero sqlite3.h, es decir, un fichero de cabeceras del lenguaje C. Por lo que procedemos a realizar el truco antes mencionado, comprobando antes y después si tenemos o no el fichero sqlite3.h:

dpkg -S sqlite3.h
sudo aptitude install libsqlite3-dev
dpkg -S sqlite3.h
gem install sqlite3-ruby

Tras esto, la gema SQLite debería instalarse sin problemas. Para MySQL, la instalación es análoga:

gem list -r | grep mysql
gem install mysql
Building native extensions. This could take a while...
ERROR: Error installing mysql:
ERROR: Failed to build gem native extension.
/usr/bin/ruby1.8 extconf.rb
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... yes
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details.
Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/mysql-2.7 for inspection.
Results logged to /usr/lib/ruby/gems/1.8/gems/mysql-2.7/gem_make.out

Buscando e instalando la librería adecuada, no deberíamos tener ningún problema:

aptitude search mysql | grep lib | grep dev
aptitude install libmysql++-dev
gem install mysql

Instalando y configurando Passenger

La instalación de Passenger es trivial, aunque por defecto no se explica cómo configurarlo a la Debian, si no que se sólo se habla de Apache en general (lógico por otra parte). Necesitáis los siguientes mandatos:

sudo gem install passenger
sudo passenger-install-apache2-module

El primero de ellos instala la gema, mientras que el segundo compila el módulo para Apache. Es probable que no funcione a la primera y os pida que instaléis una serie de paquetes de Apache (algunas librerías de desarrollo y similar), pero con seguir las instrucciones no debería dar mayor problema. En mi caso fueron los siguientes paquetes:

aptitude install build-essential libopenssl-ruby apache2-prefork-dev libapr1-dev libaprutil1-dev

Una vez instalado, Passenger nos indicará cómo configurar una aplicación en un virtualhost, así como las líneas a añadir a la configuración de Apache. Sin embargo, ya que estamos, en Debian, lo mejor es hacerlo a la Debian y crearnos el fichero /etc/apache2/mods-available/passenger.load con la ruta al módulo de Apache que Passenger nos facilita al final de la instalación:

LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.4/ext/apache2/mod_passenger.so

y su correspondiente /etc/apache2/mods-available/passenger.conf con la configuración del módulo:

PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.4
PassengerRuby /usr/bin/ruby1.8

El virtual host no tiene ningún misterio, en mi caso por ejemplo edito el fichero /etc/apache2/sites-available/mybestlap.com con el siguiente contenido:

ServerName mybestlap.com
DocumentRoot /opt/websites/mybestlap/public
ErrorLog /var/log/apache2/error_mybestlapcom.log
LogLevel warn
CustomLog /var/log/apache2/access_mybestlap.com.log combined

Depués sólo queda habilitar el módulo y el site, y reiniciar Apache

sudo a2enmod passenger
sudo a2ensite mybestlap.com
sudo /etc/init.d/apache2 restart

Y ya tenemos nuestra aplicación lista para salir a producción. Ahora queda lo más diver, implementarla :D. Happy coding!

(1) También se puede instalar directamente una versión más moderna de Rubygems, pero prefería cubrir el caso descrito, que es el que yo hice y que tenía algo más de miga.

Webcam Quickcam Messenger en Ubuntu Linux

Pues sí, como he comentado en el post anterior, uno de los reyes (no recuerdo si Melchor o Baltasar… Gaspar no, que ese me ha traido la minimoto) me ha traido una webcam, que he hecho funcionar bajo Linux (concretamente, yo uso Ubuntu). La cuestión es que oficialmente la cámara no está soportada. Sin embargo encontré un driver, enlazado ya en Del.ici.us, que es el siguiente:
Quickcam Messenger Driver
Tras compilarlo y tal, la cosa funcionó, ya he hecho mis primeros videochateos con el Amsn (¡como mola! :D). El único problema que tengo es que la resolución es pobre (lei por ahí que de momento no soporta los 640×480 de la cámara) y que cada vez que reconecto la cámara, tengo que borrar y cargar los drivers de nuevo (puede ser problema de que antes instalé otros drivers y que estén todos, los de Ubuntu incluidos, pegándose por la cámara :P), pero bueno, al final se resume en:
# sudo rmmod quickcam ; sudo rmmod videodev ; sudo modprobe quickcam ; sudo modprobe videodev
cada vez que conecto la cámara. El micro parece que es detectado por la Ubuntu (de hecho, me monta la cámara como una tarjeta de sonido extra), pero todavía no he conseguido grabar nada con él (tampoco he dedicado mucho tiempo).

Technorati Tags: