Redirigir peticiones http de una maquina a otra sin perder hostname con mod_proxy

Hace unos dias me encontré con el siguiente problema, tengo que migrar el site foo.com del servidor A al servidor B, no podemos tener el site caido mucho tiempo mas allá de unos pocos minutos (lo que tardamos en hacer un dump de los datos y una copia de ficheros), tampoco queremos cambiar el dominio del site  (por ejemplo usando una redirección del estilo.foo.com a new.foo.com).

Resumiendo: queremos que todas las peticiones que entren al servidor A para el virtual host foo.com le lleguen al servidor B que tiene tambien configurado ese mismo dominio en sus virtual hosts.

Afortunadamente Apache 2 es el servidor web del dominio foo.com.

¿Como lo hacemos?

Voy a proponer una solución al problema utilizando mod_proxy:

Añadimos estas 3 lineas a la configuración del servidor A.

ProxyPass / http://192.240.2.93/

ProxyPassReverse / http://192.240.2.93/

ProxyPreserveHost On

Explicamos para que sirven los parametros:

  • ProxyPass redirige la petición del servidor A a la ip del servidor B.
  • ProxyPassReverse cambia la URL en las cabeceras Location, Content-Location y URI de las respuestas HTTP redirect. Se utiliza para que la respuesta de la petición vaya al cliente a traves del host A, lo cual es muy util cuando redirigimos peticiones a hosts en una red privada que no tienen acceso a internet. En nuestro caso esta directiva es opcional y podemos decidir que sea el host B el que responda al cliente directamente.
  • ProxyPreserveHost mantiene la cabecera Host de la petición en la redirección al servidor B, esta pensado especificamente para poder hacer redirecciones a servidores que utilicen virtual hosts basados en nombres de dominio.

En el host B tenemos que tener una configuración similar a esta para que acepte las peticiones que le entran desde el servidor A:

<virtualhost *:80>
ServerName foo.com
DocumentRoot /var/www/foo

<directory “/var/www/foo”>
Order allow,deny
Allow from all
</directory>

ErrorLog /var/log/apache2/foo.err
CustomLog /var/log/apache2/foo.log combined
</virtualhost>