<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nordri&#039;s Blog &#187; Apache</title>
	<atom:link href="http://www.muspells.net/blog/category/apache/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.muspells.net/blog</link>
	<description>Estamos trabajando en ello...</description>
	<lastBuildDate>Wed, 04 Jan 2012 16:01:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Crear un Demonio en Linux</title>
		<link>http://www.muspells.net/blog/2011/09/crear-un-demonio-en-linux/</link>
		<comments>http://www.muspells.net/blog/2011/09/crear-un-demonio-en-linux/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 17:33:11 +0000</pubDate>
		<dc:creator>Fede Diaz</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[daemon]]></category>
		<category><![CDATA[monitorizacion]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=1056</guid>
		<description><![CDATA[En esta entrada vamos a explicar cómo proceder para escribir un demonio bajo GNU/Linux. Lo primero es definir que se entiende por un demonio, y citamos a la wikipedia: Un demonio, daemon o dæmon (de sus siglas en inglés Disk And Execution MONitor), es un tipo especial de proceso informático no interactivo, es decir, que [...]]]></description>
			<content:encoded><![CDATA[<p>En esta entrada vamos a explicar cómo proceder para escribir un demonio bajo GNU/Linux. Lo primero es definir que se entiende por un demonio, y citamos a la wikipedia:</p>
<blockquote><p>
Un demonio, daemon o dæmon (de sus siglas en inglés Disk And Execution MONitor), es un tipo especial de proceso informático no interactivo, es decir, que se ejecuta en segundo plano en vez de ser controlado directamente por el usuario. Este tipo de programas se ejecutan de forma continua (infinita), vale decir, que aunque se intente cerrar o matar el proceso, este continuará en ejecución o se reiniciará automáticamente. Todo esto sin intervención de terceros y sin dependencia de consola alguna.</p></blockquote>
<p>Un ejemplo de demonio es Apache, permanece en ejecución en segundo plano esperando peticiones de páginas web para ser servidas. O cron que es un demonio temporal, es decir, realiza acciones basadas en el tiempo.</p>
<p>El primer paso que debemos tener en cuenta es qué va a realizar el demonio, Linux basa su programación en que cada programa resuelve un único problema pero lo hace bien. Para ilustrar esta entrada construiremos un demonio que supervise si el demonio Apache está funcionando.</p>
<h4>Requisitos</h4>
<p>Necesitamos un compilador de C, normalmente GCC, y las cabezeras de C para linux, esto en Debian se consigue con:</p>
<pre># apt-get install build-essential</pre>
<p>Necesitaremos también un editor para escribir el código.</p>
<h4>Estructura básica de un demonio</h4>
<p>Durante la ejecución del demonio debemos realizar algunas tareas básicas que se resumen en:</p>
<ul>
<li>Hacer fork del proceso padre.</li>
<li>Cambiar la máscara de fichero.</li>
<li>Abrir los archivos de registros necesarios.</li>
<li>Crear un identificador de sesión único.</li>
<li>Cambiar el directorio de trabajo hacia un sitio más seguro.</li>
<li>Cerrar los descriptores de ficheros estandard.</li>
<li>Escribir el código del demonio propiamente.</li>
</ul>
<h4>El código</h4>
<p>He comentado el código con lo más importante y está bastante autoexplicativo:</p>
<pre>

#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;
#include &lt;unistd.h&gt;
#include &lt;syslog.h&gt;
#include &lt;string.h&gt;

int main(void) {

  pid_t pid, sid;
  int apachePIDfile, apachePIDread, apachePID, daemonLogFileDesc;
  char buf[5], filename[255];        

  /* Forkeamos el proceso padre */
  pid = fork();
  if (pid < 0) {
    exit(EXIT_FAILURE);
  }
  /* Cuando tenemos un PID correcto podemos cerrar
   * el proceso padre.
   * Atención al control de errores, es una buena
   * técnica de programación comprobar todas las
   * situaciones donde se pueden dar errores. */
  if (pid > 0) {
    exit(EXIT_SUCCESS);
  }

  /* Cambiamos el modo de la mascara de ficheros */
  /* Hacemos esto para que los fichero generados por el
   * demonio sean accesibles por todo el mundo */
  umask(0);

  /* Abrimos los ficheros de logs del demonio */
  /* Esto es opcional pero como vamos a cerrar los descriptores
   * hacemos esto para que exista algo de comunicación con el demonio */
  daemonLogFileDesc = open ("log", O_WRONLY | O_CREAT, 0600);
  if (daemonLogFileDesc == -1) {
    perror ("Error en la apertura del log");
    exit (EXIT_FAILURE);
  }

  /* Creamos un nuevo SID */
  /* Esto se hace porque al haber matado al padre el hijo puede quedarse
   * en el sistema como un proceso zombie, generando un nuevo SID hacemos
   * que el sistema se haga cargo del proceso huérfano otorgándole un nuevo SID */
  sid = setsid();
  if (sid < 0) {
    perror("new SID failed");
    exit(EXIT_FAILURE);
  }

  /* Por seguridad, cambiamos el directorio de trabajo */
  if ((chdir("/")) < 0) {
    perror("Change the current work directory failed");
    exit(EXIT_FAILURE);
  }

  /* Cerramos los descriptores standard */
  /* El demonio no puede usar la terminal, por lo que estos
   * descriptores son inútiles y un posible riesgo de seguridad.*/
  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  close(STDERR_FILENO);

  /* El código del demonio */
  /* Obtenemos el PID con el que está corriendo el proceso apache */
  apachePIDfile = open("/var/run/apache2.pid", O_RDONLY, 0600);
  if (apachePIDfile == -1) {
    perror("Error en la apertura del fichero");
    exit(EXIT_FAILURE);
  }
  apachePIDread = read (apachePIDfile, buf, sizeof(buf));

  /* El gran bucle! */
  /* El demonio ejecutara este bucle toda su vida,
   * abrirá un archivo del pseudo sistema de ficheros /proc
   * y comprobará que existe, si existe Apache está corriendo y lo escribe
   * en el log, en caso contrario sale. */
  while (1) {
    apachePID = atoi (buf);
    snprintf(filename, sizeof(filename), "/proc/%d/cmdline", apachePID);

    if ((open (filename, O_RDONLY, 0600)) == -1) {
      perror ("No puedo abrir el fichero en proc");
      exit(EXIT_FAILURE);
    } else {
      write (daemonLogFileDesc, "Apache running\n", 15);
      sleep(30); /* espera 30 segundos */
    }
  }
  exit(EXIT_SUCCESS);
}
</pre>
<h4>Compilamos</h4>
<p>Para compilar hacemos lo siguiente:</p>
<pre># cc daemon1.c -o daemon1</pre>
<p>A falta de un nombre más original, he llamado al demonio <strong>daemon1</strong>.</p>
<h4>Ejecución</h4>
<p>Para ejecutarlo hacemos:</p>
<pre># ./daemon1</pre>
<p>Podemos ver que está corriendo tanto en el lista de procesos con <em>ps</em> como mirando el fichero <em>log</em> que hemos creado.</p>
<pre>tailf log
...
Apache running
Apache running
Apache running
...
</pre>
<h4>Referencias</h4>
<p>Es una traducción/adaptación de la guía <a href="http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html" target="_blank">Linux Daemon Writing HOWTO</a>, que es más teórica y aquí he querido dar una aplicación práctica, aunque es obvio que existe demonios de monitorización más avanzado quería marcar bien los conceptos de la construcción de un demonio aplicados a un caso particular.</p>
<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.muspells.net%2Fblog%2F2011%2F09%2Fcrear-un-demonio-en-linux%2F&amp;layout=button_count&amp;show_faces=false&amp;width=100&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Crear un Demonio en Linux. via @nordri" data-url="http://www.muspells.net/blog/2011/09/crear-un-demonio-en-linux/" 
						data-via=""  ></a> 
				</div></div>
		<div style="clear:both;"></div>]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2011/09/crear-un-demonio-en-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Montar un Servidor Web</title>
		<link>http://www.muspells.net/blog/2011/06/montar-un-servidor-web/</link>
		<comments>http://www.muspells.net/blog/2011/06/montar-un-servidor-web/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 16:29:31 +0000</pubDate>
		<dc:creator>Fede Diaz</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[debian squeeze]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[virtualhost]]></category>
		<category><![CDATA[webserver]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=994</guid>
		<description><![CDATA[Hay muchas formas de llevar a cabo la tarea de desplegar un servidor Web, incluso se puede optar por algún servicio que nos ofrezca un panel de control para administrar el contenido perdidiendo la capacidad de administrar físicamente los servicios. Como digo, existen muchas maneras de hacer esto, esta es una de ellas. Introducción No [...]]]></description>
			<content:encoded><![CDATA[<p>Hay muchas formas de llevar a cabo la tarea de desplegar un servidor Web, incluso se puede optar por algún servicio que nos ofrezca un panel de control para administrar el contenido perdidiendo la capacidad de administrar físicamente los servicios. Como digo, existen muchas maneras de hacer esto, esta es una de ellas.</p>
<h4>Introducción</h4>
<p>No entramos en detalles sobre el hardware de la máquina, ya está instalado un sistema GNU/Linux Debian Squezee. Hemos contratado un servidor que incluye nombre DNS para nuestro dominio <em>midominio.com</em>.</p>
<h4>El usuario</h4>
<p>La ejecución del servidor debe ser bajo un usuario no privilegiado y sin shell válida en el sistema. En Debian, tras instalar Apache, se crea un usuario <em>www-data</em> para esta tarea, pero lo vamos a cambiar por otro por no mantener, en la medida de lo posible, los valores por defecto. Nuestro usuario será <em>webuser</em> que es bastante descriptivo de la labor que tendrá.</p>
<p>Creamos el grupo y el usuario y le asignamos contraseña:</p>
<pre>
# groupadd webuser
# useradd -d /home/webuser -s /bin/false -g webuser -m webuser
# passwd webuser
Introduzca la nueva contraseña de UNIX:
Vuelva a escribir la nueva contraseña de UNIX:
passwd: contraseña actualizada correctamente
</pre>
<p>Con esto contamos con el usuario, vamos a instalar Apache.</p>
<h4>Instalando Apache</h4>
<p>Vamos a instalarlo mediante la utilidad <em>tasksel</em> que es gráfica de consola y nos ahorra escribir.</p>
<pre>
# tasksel
</pre>
<p>De las opciones disponibles, elegimos la de Servidor Web, como vemos en la imagen, luego le damos a aceptar.</p>
<div id="attachment_997" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.muspells.net/blog/wp-content/uploads/2011/06/01Tasksel1.png"><img src="http://www.muspells.net/blog/wp-content/uploads/2011/06/01Tasksel1-300x187.png" alt="Tasksel" title="Tasksel" width="300" height="187" class="size-medium wp-image-997" /></a><p class="wp-caption-text">Tasksel</p></div>
<p>Instalará Apache y todas las dependencias.</p>
<div id="attachment_998" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.muspells.net/blog/wp-content/uploads/2011/06/02Instalando.png"><img src="http://www.muspells.net/blog/wp-content/uploads/2011/06/02Instalando-300x187.png" alt="Instalando" title="Instalando" width="300" height="187" class="size-medium wp-image-998" /></a><p class="wp-caption-text">Instalando</p></div>
<p>Ya podemos pasar a configurar el servidor.</p>
<h4>Configurando Apache</h4>
<p>La configuración que trae Debian para Apache es la que me hace elegir esta distribución frente a otras como CentOS que también es conocida por estar presente en muchos servidores web de internet. El primer fichero que vamos a configurar es <em>/etc/apache2/envvars</em> y añadimos el usuario y grupo que hemos creado.</p>
<pre># vim /etc/apache2/envvars</pre>
<pre>
[...]
export APACHE_RUN_USER=webuser
export APACHE_RUN_GROUP=webuser
[...]
</pre>
<p>A continuación deshabilitamos los <strong>VirtualHosts</strong> que vienen por defecto para crear el nuestro, podemos crear tantos como sean necesarios.</p>
<pre>
# a2dissite 000-default
Site default disabled.
Run '/etc/init.d/apache2 reload' to activate new configuration!
</pre>
<p>Ahora creamos nuestro sitio empezando por crear la estructura de directorios. Para ello vamos a crear siguiendo la filosofía que vi en SuSE y me gustó.</p>
<pre># mkdir -p /server/midominio.com </pre>
<p>De esta forma, contamos con el directorio <em>/server</em> y de él colgaran todos los servidores virtuales.</p>
<p>Ajustamos los permisos del directorio:</p>
<pre># chown -R webuser.webuser /server</pre>
<p>Configuramos ahora las <em>stanzas</em> para nuestro servidor, para ello creamos un nuevo fichero <em>/etc/apache2/sites-available/misitio</em>.</p>
<pre># vim /etc/apache2/sites-available/midominio.com</pre>
<pre>
NameVirtualHost *:80
&lt;VirtualHost *:80&gt;
        ServerName midominio.com
        ServerAlias www.midominio.com
        ServerAdmin <span class="mh-email"><a href='http://www.google.com/recaptcha/mailhide/d?k=01YKdTHthsc-GjIi7grn-9Jw==&amp;c=mfYAf3BfzwcluoxtKVUc1UArcejzuP11Q_Pcyb5sR74=' onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k=01YKdTHthsc-GjIi7grn-9Jw==&amp;c=mfYAf3BfzwcluoxtKVUc1UArcejzuP11Q_Pcyb5sR74=', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;" title="Click para desvelar.">Email protegido.</a></span>

        DocumentRoot /server/midominio.com/
        &lt;Directory /&gt;
                Options FollowSymLinks
                AllowOverride all
        &lt;/Directory&gt;
        &lt;Directory /server/midominio.com/&gt;
                Options FollowSymLinks Multiviews Indexes
                AllowOverride all
                Order allow,deny
                allow from all
        &lt;/Directory&gt;

        ErrorLog /var/log/apache2/error.midominio.com.log
        LogLevel warn
        CustomLog /var/log/apache2/error.midominio.com.log combined
        ServerSignature Off
&lt;/VirtualHost&gt;
</pre>
<p>Comentamos que permitimos <em>AllowOverride</em> a <em>all</em> para que podamos customizar el sitio a través de <em>.htaccess</em> y no tener que tocar mucho la configuración del servidor. También personalizamos los archivos de logs por si añadimos más servidores distinguir entre ellos.</p>
<p>Habilitamos el sitio.</p>
<pre># a2ensite misitio</pre>
<p>Ya podemos arrancar el servidor.</p>
<pre># apache2ctl graceful</pre>
<p>Ahora ya podemos abrir un navegador web y entrar en el sitio, aunque no tiene contenido, cosa que resolveremos ahora.</p>
<p>En nuestro panel de control habilitamos que tanto <em>midominio.com</em> como <em>www.midominio.com</em> resuelvan a nuestra web, luego podemos usar un truco como <a href="http://www.aquihaydominios.com/blog/forzar-www-usando-htaccess/">este</a> para que por defecto se utilice las uves dobles que es mejor desde el punto de vista SEO.</p>
<h4>Añadir contenido, el servidor FTP</h4>
<p>El usuario no tiene shell, luego no podemos iniciar una sesión en el servidor para crear los archivos html que queramos servir ni copiarlos por ssh, así que desplegamos un servidor FTP, por razones más históricas que otra cosa, uso Proftpd que tiene una configuración modular similar a la de Apache. Tiene soporte de <em>VirtualHost</em> pero la limitación del protocolo hace que no se pueda usar el mismo puerto en todos los servidores, esto es, cada <em>VirtualHost</em> que configures estará asociado a un puerto.</p>
<p>Pasamos a instalarlo.</p>
<pre># apt-get install proftpd</pre>
<p>Lo instalamos como servidor independiente.</p>
<p>La configuración es esta:</p>
<pre>
# /etc/proftpd/proftpd.conf -- This is a basic ProFTPD configuration file.
# To really apply changes reload proftpd after modifications.

# Includes DSO modules
Include /etc/proftpd/modules.conf

# Set off to disable IPv6 support which is annoying on IPv4 only boxes.
UseIPv6				off
# If set on you can experience a longer connection delay in many cases.
IdentLookups			off

ServerName			"Mi servidor FTP"
ServerType			standalone
DeferWelcome			off

MultilineRFC2228		on
DefaultServer			on
ShowSymlinks			on

TimeoutNoTransfer		600
TimeoutStalled			600
TimeoutIdle			1200

DisplayLogin                    welcome.msg
DisplayChdir               	.message true
ListOptions                	"-l"

DenyFilter			\*.*/

# Use this to jail all users in their homes
# DefaultRoot			~

# Users require a valid shell listed in /etc/shells to login.
# Use this directive to release that constrain.
# RequireValidShell		off

# Port 21 is the standard FTP port.
Port				0

# In some cases you have to specify passive ports range to by-pass
# firewall limitations. Ephemeral ports can be used for that, but
# feel free to use a more narrow range.
PassivePorts                  49152 65534

# If your host was NATted, this option is useful in order to
# allow passive tranfers to work. You have to use your public
# address and opening the passive ports used on your firewall as well.
# MasqueradeAddress		1.2.3.4

# This is useful for masquerading address with dynamic IPs:
# refresh any configured MasqueradeAddress directives every 8 hours
&lt;IfModule mod_dynmasq.c&gt;
# DynMasqRefresh 28800
&lt;/IfModule&gt;

# To prevent DoS attacks, set the maximum number of child processes
# to 30.  If you need to allow more than 30 concurrent connections
# at once, simply increase this value.  Note that this ONLY works
# in standalone mode, in inetd mode you should use an inetd server
# that allows you to limit maximum number of processes per service
# (such as xinetd)
MaxInstances			30

# Set the user and group that the server normally runs at.
User				webuser
Group				webuser

# Umask 022 is a good standard umask to prevent new files and dirs
# (second parm) from being group and world writable.
Umask				022  022
# Normally, we want files to be overwriteable.
AllowOverwrite			on

# Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords:
# PersistentPasswd		off

# This is required to use both PAM-based authentication and local passwords
# AuthOrder			mod_auth_pam.c* mod_auth_unix.c

# Be warned: use of this directive impacts CPU average load!
# Uncomment this if you like to see progress and transfer rate with ftpwho
# in downloads. That is not needed for uploads rates.
#
# UseSendFile			off

TransferLog /var/log/proftpd/xferlog
SystemLog   /var/log/proftpd/proftpd.log

&lt;IfModule mod_quotatab.c&gt;
QuotaEngine off
&lt;/IfModule&gt;

&lt;IfModule mod_ratio.c&gt;
Ratios off
&lt;/IfModule&gt;

# Delay engine reduces impact of the so-called Timing Attack described in
# http://security.lss.hr/index.php?page=details&#038;ID=LSS-2004-10-02
# It is on by default.
&lt;IfModule mod_delay.c&gt;
DelayEngine on
&lt;/IfModule&gt;

&lt;IfModule mod_ctrls.c&gt;
ControlsEngine        off
ControlsMaxClients    2
ControlsLog           /var/log/proftpd/controls.log
ControlsInterval      5
ControlsSocket        /var/run/proftpd/proftpd.sock
&lt;/IfModule&gt;

&lt;IfModule mod_ctrls_admin.c&gt;
AdminControlsEngine off
&lt;/IfModule&gt;

&lt;VirtualHost midominio.com&gt;
        ServerName "midominio.com"
        Port 21
        DefaultRoot /server/midominio
        &lt;Limit LOGIN&gt;
                AllowUser webuser
                AllowGroup webuser
                DenyAll
        &lt;/Limit&gt;
        RequireValidShell off
        AllowOverwrite on
&lt;/VirtualHost&gt;
</pre>
<p>Hemos cambiado el puerto FTP por el 0 para usar el 21 para el <em>VirtualHost</em> e indicamos que el usuario (webuser) no requiere de una shell valida.</p>
<p>Ahora podemos usar un cliente FTP, por ejemplo <a href="http://filezilla-project.org/">Filezilla</a> para subir ficheros al servidor.</p>
<p>Y ya hemos terminado, hemos creado un servidor web desde cero, aun quedan cosas por hacer pero lo básico está cubierto, os invito a seguir navegando por el blog y veáis como configurar <strong>mod_deflate</strong> para servir <a href="http://www.muspells.net/blog/2011/03/optimizando-el-rendimiento-de-apache-con-mod_expires-y-mod_deflate/">contenido comprimido</a>, <strong>mod_evasive</strong> para evitar <a href="http://www.muspells.net/blog/2010/10/evitar-ataques-dos-con-mod_evasive-e-iptables/">ataques DDOS</a>, o <strong>mod_expires</strong> para almacenar contenido estático en la caché del usuario.</p>
<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.muspells.net%2Fblog%2F2011%2F06%2Fmontar-un-servidor-web%2F&amp;layout=button_count&amp;show_faces=false&amp;width=100&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Montar un Servidor Web. via @nordri" data-url="http://www.muspells.net/blog/2011/06/montar-un-servidor-web/" 
						data-via=""  ></a> 
				</div></div>
		<div style="clear:both;"></div>]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2011/06/montar-un-servidor-web/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Alta Disponibilidad con Apache2 y Heartbeat en Debian Squeeze</title>
		<link>http://www.muspells.net/blog/2011/04/alta-disponibilidad-con-apache2-y-heartbeat-en-debian-squeeze/</link>
		<comments>http://www.muspells.net/blog/2011/04/alta-disponibilidad-con-apache2-y-heartbeat-en-debian-squeeze/#comments</comments>
		<pubDate>Tue, 19 Apr 2011 19:44:19 +0000</pubDate>
		<dc:creator>Fede Diaz</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[alta disponibilidad]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[debian squeeze]]></category>
		<category><![CDATA[heartbeat]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=920</guid>
		<description><![CDATA[A raíz de las últimas entradas en rm-rf.es y systemadmin.es quería probar el demonio de alta disponibilidad (heartbeat) sobre Debian, la entrada sobre Apache que publicó el primero me inspiró a hacer lo que contaba sobre la &#8220;distro&#8221; de la espiral. Partimos de la misma configuración, tenemos dos servidores, cluster01 y cluster02 con las IPs [...]]]></description>
			<content:encoded><![CDATA[<p>A raíz de las últimas entradas en <a href="http://rm-rf.es">rm-rf.es</a> y <a href="http://systemadmin.es">systemadmin.es</a> quería probar el demonio de alta disponibilidad (heartbeat) sobre Debian, la entrada sobre Apache que publicó el primero me inspiró a hacer lo que contaba sobre la &#8220;distro&#8221; de la espiral.</p>
<p>Partimos de la misma configuración, tenemos dos servidores, <strong>cluster01</strong> y <strong>cluster02</strong> con las IPs 192.168.2.98 y 192.168.2.99 y una IP flotante 192.168.2.100</p>
<p>Configuradas ambas máquinas, instalamos los paquetes necesarios:</p>
<pre># apt-get install apache2</pre>
<p>En nuestro caso, para la configuración de Apache editamos <em>/etc/apache2/ports.conf</em> y añadimos la IP flotante a la línea de </strong>NameVirtualHost</strong> así:</p>
<pre>NameVirtualHost 192.168.2.100:80</pre>
<p>Para que Apache no se levante al inicio ya que queremos que el que se encargue de esto es Heartbeat escribimos:</p>
<pre># update-rc.d apache2 remove</pre>
<p>Y detenemos el servicio:</p>
<pre># /etc/init.d/apache2 stop</pre>
<p>A continuación instalamos Heartbeat.</p>
<pre># apt-get install heartbeat</pre>
<p>Y configuramos, estos ficheros de configuración se encuentran todos en <em>/etc/ha.d/</em> y disponemos de plantillas para configurarlos en <em>/usr/share/doc/heartbeat/</em>. Podemos tomar ejemplo para configuraciones más específica.</p>
<p>Para el archivo <strong>ha.cf</strong> usamos la misma:</p>
<pre>logfile /var/log/cluster.log
logfacility local0
warntime 5
deadtime 30
initdead 120
keepalive 2
bcast eth0
udpport 694
auto_failback on
node cluster01
node cluster02
</pre>
<p>La explicación</p>
<ul>
<li><strong>logfile</strong> y <strong>logfacility</strong>: Fichero de log y nivel.</li>
<li><strong>warntime</strong>: Heartbeat avisará cuando un nodo falle tras 5 segundos.</li>
<li><strong>deadtime</strong>: Hearbeat confirmará que un nodo ha caído, 30 segundos.</li>
<li><strong>initdead</strong>: Tiempo máximo que Heartbeat esperará a que un nodo arranque, 60 segundos.</li>
<li><strong>keepalive</strong>: Especifica cada cuanto tiempo Heartbeat enviará paquetes para comprobar la disponibilidad de los nodos, 2 segundos.</li>
<li>Las dos últimas líneas son las listas de nodos que conforman el cluster.</li>
</ul>
<p>Para el fichero <strong>authkeys</strong> que es donde configuramos la comunicación entre los nodos del clúster, también para Debian podemos usar la original:</p>
<pre>
auth 2
2 sha1 clu$ter-4uth
</pre>
<p>Le asignamos los permisos para que sólo root tenga acceso.</p>
<pre># chmod 600 /etc/ha.d/authkeys</pre>
<p>El último fichero cambia en Debian y es el <strong>haresources</strong> que queda con este aspecto:</p>
<pre>cluster01 IPaddr2::192.168.2.100/24/eth0 apache2</pre>
<p>Cambia la forma de escribir la IP flotante que está de una forma más completa y el script de inicio de Apache que en Debian es apache2.</p>
<p>Seguimos la entrada y la propagación se hace ejecutando el siguiente comando:</p>
<pre># /usr/share/heartbeat/ha_propagate</pre>
<p>Levantamos el servicio.</p>
<pre>/etc/init.d/heartbeat start</pre>
<p>Ya está todo configurado, podemos probar a desactivar la interface de cluster01 y ver como al poco tiempo (el que hemos configurado) se levanta cluster02 para seguir sirviendo páginas.</p>
<p>La configuración entre CentOS y Debian es prácticamente la misma, pero tiene los suficientes detalles como para que los escriba aquí para no olvidar como se hace.</p>
<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.muspells.net%2Fblog%2F2011%2F04%2Falta-disponibilidad-con-apache2-y-heartbeat-en-debian-squeeze%2F&amp;layout=button_count&amp;show_faces=false&amp;width=100&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Alta Disponibilidad con Apache2 y Heartbeat en Debian Squeeze. via @nordri" data-url="http://www.muspells.net/blog/2011/04/alta-disponibilidad-con-apache2-y-heartbeat-en-debian-squeeze/" 
						data-via=""  ></a> 
				</div></div>
		<div style="clear:both;"></div>]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2011/04/alta-disponibilidad-con-apache2-y-heartbeat-en-debian-squeeze/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Optimizando el Rendimiento de Apache con mod_expires y mod_deflate</title>
		<link>http://www.muspells.net/blog/2011/03/optimizando-el-rendimiento-de-apache-con-mod_expires-y-mod_deflate/</link>
		<comments>http://www.muspells.net/blog/2011/03/optimizando-el-rendimiento-de-apache-con-mod_expires-y-mod_deflate/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 20:44:03 +0000</pubDate>
		<dc:creator>Fede Diaz</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[apache2]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[lenny]]></category>
		<category><![CDATA[mod_deflate]]></category>
		<category><![CDATA[mod_expires]]></category>
		<category><![CDATA[squezee]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=796</guid>
		<description><![CDATA[Llevo unas horas jugando con el plugin PageSpeed de Google que te da una serie de consejos y buenas prácticas a la hora de publicar en Internet. Dos de esos consejos son los de comprimir los archivos que sirves desde el servidor y jugar con la caché del navegador del usuario para que los archivos [...]]]></description>
			<content:encoded><![CDATA[<p>Llevo unas horas jugando con el plugin <a href="http://code.google.com/speed/page-speed/">PageSpeed</a> de <a href="http://www.google.es/">Google</a> que te da una serie de consejos y buenas prácticas a la hora de publicar en Internet. Dos de esos consejos son los de comprimir los archivos que sirves desde el servidor y jugar con la caché del navegador del usuario para que los archivos más estáticos no sean descargados cada vez que entran en el sitio. Veamos como configurar nuestro servidor Apache para mejorar la experiencia de nuestros usuarios.</p>
<p>Lo he probado en Debian tanto Lenny con Apache/2.2.9 como Squezee con Apache/2.2.16.</p>
<h2>mod_expires</h2>
<p>El módulo viene de serie en ambas instalaciones y para activarlo simplemente hacemos:</p>
<pre># a2enmod expires</pre>
<p>Y nos cargará el módulo. Pasamos a configurarlo, tenemos varias opciones que nos lo cuenta la entrada en la documentación de Apache:</p>
<blockquote><p>Context:	server config, virtual host, directory, .htaccess</p></blockquote>
<p>Lo he probado en <em>server config</em>, <em>virtual host</em> y <em>.htaccess</em> tan sólo cambia donde vamos a escribir las reglas de vida de los tipos de archivo. En <em>server config</em> lo escribiriamos en un archivo:</p>
<pre># vim /etc/apache2/mods-available/expires.conf</pre>
<p>y añadiríamos el siguiente contenido:</p>
<pre>
&lt;IfModule mod_expires.c&gt;
          ExpiresActive on
          ExpiresByType image/jpg "access plus 60 days"
          ExpiresByType image/png "access plus 60 days"
          ExpiresByType image/gif "access plus 60 days"
          ExpiresByType image/jpeg "access plus 60 days"
          ExpiresByType text/css "access plus 1 days"
          ExpiresByType image/x-icon "access plus 1 month"
          ExpiresByType application/pdf "access plus 1 month"
          ExpiresByType audio/x-wav "access plus 1 month"
          ExpiresByType audio/mpeg "access plus 1 month"
          ExpiresByType video/mpeg "access plus 1 month"
          ExpiresByType video/mp4 "access plus 1 month"
          ExpiresByType video/quicktime "access plus 1 month"
          ExpiresByType video/x-ms-wmv "access plus 1 month"
          ExpiresByType application/x-shockwave-flash "access 1 month"
          ExpiresByType text/javascript "access plus 1 week"
          ExpiresByType application/x-javascript "access plus 1 week"
          ExpiresByType application/javascript "access plus 1 week"
&lt;/IfModule&gt;
</pre>
<p>La sintaxis es sencilla, sigue la siguiente regla:</p>
<pre>ExpiresByType mime.type "&lt;base&gt; [plus] {&lt;num&gt; &lt;type&gt;}*"</pre>
<p>donde</p>
<ul>
<li>base: Puede ser <em>access</em>, <em>now</em> o <em>modification</em>. <em>now</em> es igual a <em>access</em>.</li>
<li>La clave <em>plus</em> es opcional. <em>num</em> debe ser un entero y <em>type</em> es uno de los siguiente:</li>
</ul>
<ul>
<li>years</li>
<li>months</li>
<li>weeks</li>
<li>days</li>
<li>hours</li>
<li>minutes</li>
<li>seconds</li>
</ul>
<p>Así, por ejemplo, le estamos diciendo al navegador del usuario que almacene los archivos de imágenes durante 60 días desde el primer acceso, los archivos multimedia durante un mes y así.</p>
<p>Una vez ajustados estos tiempos conforme a nuestras necesidades hacemos un enlace del archivo de configuración dentro de <em>mods-enabled</em></p>
<pre>
# ln -s /etc/apache2/mods-available/expires.conf /etc/apache2/mods-enabled/
</pre>
<p>y reiniciamos el servidor.</p>
<pre># /etc/init.d/apache2 restart</pre>
<p>Un error que me dio en este punto fue que no encontraba el archivo de mime types en la raiz del servidor, por si os encontrais este problema, el archivo está en la documentación de Apache del servidor y lo obtenemos así:</p>
<pre>
# zcat /usr/share/doc/apache2.2-common/examples/apache2/mime.types.gz > /etc/apache2/mime.types
</pre>
<p>Si nos decidimos a configurarlo a nivel de <em>Virtual Host</em> tenemos que añadir la configuración dentro de las directiva <em>Directory</em></p>
<p>Y si preferimos que nuestros propios usuarios del servidor definan la esperanza de vida en sus <em>.htaccess</em> tenemos que permitir el <em>Allow Override</em> a <em>Indexes</em> para que la configuración del servidor pueda ser sobrescrita con las directivas incluidas en este archivo.</p>
<h2>mod_deflate</h2>
<p>Enviar todo lo que podamos de forma comprimida nos hará ahorrar ancho de banda y nuestro usuarios con conexiones lentas nos lo agradecerán, por eso vamos a habilitar el módulo encargado de hacer esto.</p>
<pre> # a2enmod deflate </pre>
<p>Este módulo ya viene con un fichero de configuración que se enlaza en <em>mods-enabled</em> por lo que sólo tenemos que añadir:</p>
<pre># vim /etc/apache2/mods-available/deflate.conf</pre>
<pre>
  SetOutputFilter DEFLATE
  SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
  SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
  SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
</pre>
<p>En esta configuración le decimos que comprima todo excepto imágenes, archivos ya comprimidos y pdf&#8217;s, podemos hacer que lo comprima todo pero para estos archivos específicos no nos merece la pena y sería un gasto de computación innecesario.</p>
<h2>Resultados</h2>
<p>Para comprobar los resultado podemos usar el mismo plugin de PageSpeed o instalarnos el plugin para <a href="http://www.mozilla.com/en-US/firefox/">Firefox</a> <a href="https://addons.mozilla.org/en-US/firefox/addon/live-http-headers/">LiveHeader</a> y ver si nos dice la fecha en la que expira el contenido y si la codificación del contenido es <em>gzip</em>, como podemos ver en la siguiente imagen:</p>
<div id="attachment_800" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.muspells.net/blog/wp-content/uploads/2011/03/LiveHeaderMark.png"><img src="http://www.muspells.net/blog/wp-content/uploads/2011/03/LiveHeaderMark-300x202.png" alt="LiveHeaderMark" title="LiveHeaderMark" width="300" height="202" class="size-medium wp-image-800" /></a><p class="wp-caption-text">Live Header</p></div>
<p>También lo podemos comprobar por línea de comando así:</p>
<pre>
$ curl -I http://www.muspells.net/images/logo.png
HTTP/1.1 200 OK
Date: Mon, 01 Aug 2011 11:15:39 GMT
Server: Apache
Last-Modified: Wed, 09 Mar 2011 18:36:27 GMT
ETag: "1b1e197-1b3e-49e1101b340c0"
Accept-Ranges: bytes
Content-Length: 6974
Cache-Control: max-age=5184000
Expires: Fri, 30 Sep 2011 11:15:39 GMT
Content-Type: image/png
</pre>
<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.muspells.net%2Fblog%2F2011%2F03%2Foptimizando-el-rendimiento-de-apache-con-mod_expires-y-mod_deflate%2F&amp;layout=button_count&amp;show_faces=false&amp;width=100&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Optimizando el Rendimiento de Apache con mod_expires y mod_deflate. via @nordri" data-url="http://www.muspells.net/blog/2011/03/optimizando-el-rendimiento-de-apache-con-mod_expires-y-mod_deflate/" 
						data-via=""  ></a> 
				</div></div>
		<div style="clear:both;"></div>]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2011/03/optimizando-el-rendimiento-de-apache-con-mod_expires-y-mod_deflate/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Añadiendo marcas de agua al vuelo para evitar hotlinking</title>
		<link>http://www.muspells.net/blog/2011/02/anadiendo-marcas-de-agua-al-vuelo-para-evitar-hotlinking/</link>
		<comments>http://www.muspells.net/blog/2011/02/anadiendo-marcas-de-agua-al-vuelo-para-evitar-hotlinking/#comments</comments>
		<pubDate>Sat, 05 Feb 2011 19:37:57 +0000</pubDate>
		<dc:creator>Fede Diaz</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[hotlinking]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod rewrite]]></category>

		<guid isPermaLink="false">http://www.muspells.net/blog/?p=665</guid>
		<description><![CDATA[A partir de una entrada que aparecía esta mañana en Tu Receta, he pasado el día intentando mejorar el sistema. Ellos proponen que cuando alguien enlace directamente a una foto de tu sitio, cambiar la url mediante mod_rewrite hacía otra imagen para que en el sitio sólo pueda mostrar una imagen con algún mensaje o [...]]]></description>
			<content:encoded><![CDATA[<p>A partir de una entrada que aparecía esta mañana en <a href="http://tureceta.es">Tu Receta</a>, he pasado el día intentando mejorar el sistema. Ellos proponen que cuando alguien enlace directamente a una foto de tu sitio, cambiar la url mediante <em>mod_rewrite</em> hacía otra imagen para que en el sitio sólo pueda mostrar una imagen con algún mensaje o similar, pero no las imágenes originales. Recordé que mi amigo Migue había pasado por eso y lo resolvió, así que empece a investigar para ver cómo podría solucionarlo.</p>
<p><strong>Requerimientos:</strong></p>
<ol>
<li>Tener activado mod_rewrite en nuestro servidor</li>
<li>PHP5-GD para trabajar con imágenes</li>
<li>Una imagen que será la marca de agua</li>
</ol>
<p>Lo primero que hacemos es añadir a nuestro <em>.htaccess</em> las nuevas reglas para <em>mod_rewrite</em> que son las básicamente las mismas que en Tu Receta pero cambiamos la <em>RewriteRule</em> así:</p>
<pre>
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.muspells.net/.*$      [NC]
RewriteCond %{HTTP_REFERER} !^http://www.muspells.net$      [NC]
RewriteRule ^(.*)\.(gif|jpg|png)$ image_script.php?image=$1\.$2   [R]
</pre>
<p>Cambiamos la regla de reescritura para que apunte a un script de PHP donde editaremos al vuelo la imagen para devolverla al REFERER con una marca de agua.</p>
<p>Hemos llamado al script <em>image_script</em> y lo hemos colocado en la raíz de documentos,</p>
<pre>
&lt;?php

// En WordPress por ejemplo las imagenes se guardan en directorios,
// necesitamos el PATH completo a la imagen.
$URI = $_GET['image'];
$URI_PARSER = explode ('/', $URI);
$image = "/path/to/DocumentRoot/".$URI_PARSER[count($URI_PARSER) - 1];

switch (TRUE) {
   case stristr($image,'jpg'):
      $photoImage = ImageCreateFromJpeg("$image");
      break;
   case stristr($image,'gif'):
      $photoImage = ImageCreateFromGIF("$image");
      break;
   case stristr($image,'png'):
      $photoImage = ImageCreateFromPNG("$image");
      break;
}

ImageAlphaBlending($photoImage, true); 

// Añadimos aquí el fichero de marca de agua.
$logoImage = ImageCreateFromPNG("watermark.png");
$logoW = ImageSX($logoImage);
$logoH = ImageSY($logoImage); 

// Los 1's representan el margen con el margen superior izquierdo
ImageCopy($photoImage, $logoImage, 1, 1, 0, 0, $logoW, $logoH); 

ImagePNG($photoImage); // output to browser 

ImageDestroy($photoImage);
ImageDestroy($logoImage);
?&gt;
</pre>
<p>El script colocará la imagen <strong>watermark.png</strong> en la esquina superior izquierda.</p>
<p>Cuando accedemos a alguna imagen de nuestro sitio de forma legítima la veremos así:</p>
<div id="attachment_668" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.muspells.net/blog/wp-content/uploads/2011/02/gnu.png"><img src="http://www.muspells.net/blog/wp-content/uploads/2011/02/gnu-300x293.png" alt="gnu" title="gnu" width="300" height="293" class="size-medium wp-image-668" /></a><p class="wp-caption-text">GNU</p></div>
<p>Mientras que si accedemos enlazando directamente la veremos así:
<p>
<a href="http://www.muspells.net/blog/wp-content/uploads/2011/02/gnu.wm_.png"><img src="http://www.muspells.net/blog/wp-content/uploads/2011/02/gnu.wm_-300x293.png" alt="gnu" title="gnu.wm" width="300" height="293" class="aligncenter size-medium wp-image-669" /></a></p>
<p><strong>Fuentes:</strong></p>
<ol>
<li><a href="http://tureceta.es/evitar-hot-linking-con-htaccess/">Tu Receta: Evitar Hot-linking con .htaccess</a></li>
<li><a href="http://www.simplemachines.org/community/index.php?topic=2441.0">El script</a></li>
<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.muspells.net%2Fblog%2F2011%2F02%2Fanadiendo-marcas-de-agua-al-vuelo-para-evitar-hotlinking%2F&amp;layout=button_count&amp;show_faces=false&amp;width=100&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Añadiendo marcas de agua al vuelo para evitar hotlinking. via @nordri" data-url="http://www.muspells.net/blog/2011/02/anadiendo-marcas-de-agua-al-vuelo-para-evitar-hotlinking/" 
						data-via=""  ></a> 
				</div></div>
		<div style="clear:both;"></div>]]></content:encoded>
			<wfw:commentRss>http://www.muspells.net/blog/2011/02/anadiendo-marcas-de-agua-al-vuelo-para-evitar-hotlinking/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

