Apache Virtual Host – Cómo configurar servidores virtuales en Apache 2.4

Apache Virtual Host – Cómo configurar servidores virtuales en Apache 2.4

En esta entrada vamos a ver cómo configurar servidores virtuales en Apache 2.4, la forma de utilizar un mismo servidor Apache para que aloje servicios web que respondan a distintos dominios.

Aunque los ejemplos de este tutorial se realizan sobre Debian GNU/Linux 9, las configuraciones son aplicables a cualquier otro sistema que esté corriendo un servidor Apache 2.4.

Distintos dominios para una misma máquina

En el ejemplo usaremos un servidor que responde en la dirección IPv4 192.168.119.135 y dos dominios locales, vhost1.local y vhost2.local, que apuntan a esa misma dirección IP.

ping servidor web
Distintos dominios apuntando a la misma dirección IP

 

Además, existirá también un subdominio www para vhost1.local, es decir, podremos utilizar la dirección www.vhost1.local apuntada a la misma dirección IP.

Si quieres experimentar en tu máquina local o red interna y no sabes cómo hacerlo, tengo una entrada en la que explico cómo simular dominios locales.

En cualquier caso, toda esta guía es aplicable también a dominios reales. Si quieres configurar servidores virtuales de Apache con dominios que aún no has registrado, te recomiendo Namecheap, el lugar donde registro y mantengo los dominios de mis sitios web, como este mismo.

Configuración por defecto

Una instalación limpia de Apache 2.4 deja el servidor web funcionando y sirviendo la página web por defecto a cualquier petición que reciba.

pagina por defecto apache
Apache sirviendo la misma página por defecto a cualquier petición

 

El hecho de que se muestre esta página se debe a que Apache trae una configuración por defecto que, en realidad, es un servidor virtual configurado para NO responder a un dominio concreto. Esto es lo mismo que decir que la configuración por defecto responde a cualquier dominio que no tenga su propia configuración aparte. Se puede comprobar fácilmente escribiendo en la barra de direcciones del navegador cualquier dominio que apunte al servidor: siempre recibiremos la misma página web por defecto.

Directorios de configuración de los servidores virtuales de Apache

Las configuraciones de los distintos servidores virtuales se almacenan en una carpeta, normalmente un archivo por servidor virtual configurado. Se podrían tener varios servidores virtuales configurados a través del mismo archivo de configuración, pero el mantenimiento sería mucho más engorroso.

En Debian GNU/Linux, la configuración de Apache 2.4 se guarda en la carpeta /etc/apache2/. Dentro de esta encontramos las carpetas sites-available/ y sites-enabled/.

/etc/apache2/sites-available/: Servidores virtuales configurados

En esta carpeta se guardan los archivos de configuración de cada servidor virtual que se tenga configurado. En una instalación nueva ya hay un archivo, 000-default.conf, que guarda la configuración por defecto del servidor. A partir de la versión 2.4 de Apache, estos archivos de configuración tienen la extensión .conf.

Es en esta carpeta donde crearemos los nuevos archivos de configuración de los nuevos servidores virtuales.

El hecho de que existan los archivos de configuración en esta carpeta no significa que Apache los cargue en su configuración al arrancar. Ahora veremos cómo se hace esto.

/etc/apache2/sites-enabled/: Servidores virtuales activos

En esta carpeta aparecen enlaces simbólicos a los archivos de configuración de sites-available/ que sí se activan al arrancar o recargar la configuración de Apache. Por lo tanto, una vez configurado, para activar un servidor virtual hay que crear un enlace simbólico desde sites-enabled/ hasta el archivo de configuración situado en sites-available/.

En una instalación inicial de Apache 2.4 existirá el enlace simbólico sites-enabled/000-default.conf a sites-available/000-default.conf.

Servidor virtual por defecto de Apache

Hemos visto que una instalación limpia de Apache dirige cualquier petición a un dominio no configurado al servidor por defecto. Y que este servidor se configura a través del siguiente archivo, 000-default.conf:

<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

La mayor parte del contenido del archivo son comentarios. Si los quitamos queda más legible:

<VirtualHost *:80>
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

En esta versión, las líneas que empiezan por # no son comentarios, sino directivas desactivadas. En la práctica el resultado es el mismo: Apache no toma en consideración estas líneas.

Analizando este esqueleto de configuración de servidor virtual, su comportamiento especial (responder a todos los dominios que apunten al servidor y que no tengan configuración propia) se debe a la primera directiva desactivada, la directiva ServerName. Esta es la directiva que establece a qué dominio pertenece esta configuración.

Teniendo en cuenta esto, ya podemos empezar a crear las configuraciones para nuestros propios servidores virtuales.

Configurando el servidor virtual desde cero

Creamos el archivo /etc/apache2/sites-available/vhost1.local.conf con nuestro editor de texto favorito y privilegios de root:

~$ sudo nano /etc/apache2/sites-available/vhost1.local.conf

Hemos visto en el archivo del servidor por defecto que toda la configuración está encerrada en una directiva VirtualHost, así que será lo primero que incluyamos:

<VirtualHost *:80>
</VirtualHost>

En la directiva VirtualHost indicamos desde qué dirección escuchará el servidor (IP propia), y tras los dos puntos (:) indicamos el puerto en el que Apache esperará las conexiones. El asterisco o wildcard (*) indica que Apache atenderá peticiones desde todos los adaptadores de red que tenga configurados. Por ejemplo, si especificáramos 127.0.0.1 el servidor sólo sería accesible localmente. En cuanto al puerto, 80 es el puerto HTTP estándar.

Ahora vamos a especificar el dominio al que responderá esta configuración, mediante ServerName:

<VirtualHost *:80>
        ServerName vhost1.local
</VirtualHost>

ServerName tiene un cometido muy simple, especificar qué dominio queremos atender. Solamente eso. En cada servidor virtual tendremos que especificar un dominio distinto. Ahora el servidor dejará de ofrecer la página principal por defecto, mostrando en su lugar la que más adelante vamos a especificar.

En uno de los dominios de ejemplo tenemos configurado un subdominio www. En muchos sitios web se sirve la misma página tanto si especificamos el dominio solamente o el subdominio www. Esto no sucede de forma automática. Si ambos nombres apuntan a la misma dirección, tenemos que configurar el servidor para que atienda ambos nombres. Aquí entra en funcionamiento la directiva ServerAlias:

<VirtualHost *:80>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
</VirtualHost>

Especificando el otro dominio o subdominio como alias, Apache ofrece la misma página para ambas peticiones. Podemos configurar tantos alias como queramos, bien añadiéndolos separados por espacios en blanco en la misma línea, bien añadiendo distintas directivas ServerAlias.

Es hora de especificar el directorio donde van a residir los archivos del sitio web, esto se hace mediante la directiva DocumentRoot:

<VirtualHost *:80>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chacho/public_html/vhost1
</VirtualHost>

De forma sencilla especificamos la carpeta de archivos del servidor virtual, basta con especificar la ruta completa. En el ejemplo, sitúo esta carpeta dentro del directorio public_html/ de mi usuario. Lógicamente cada uno puede situar la carpeta en el lugar del sistema de archivos que más le interese.

Ya casi estamos, falta especificar los accesos y permisos al directorio web. Lo haremos a través de un bloque Directory:

<VirtualHost *:80>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chacho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Require all granted
        </Directory>
</VirtualHost>

Dentro de la directiva Directory establecemos ciertos accesos. Todo lo que no especifiquemos quedará con los valores por defecto de la configuración por defecto de Apache. En versiones 2.2 y anteriores no era necesario, pero a partir de Apache 2.4 hay que permitir explícitamente el acceso a cualquier directorio web que no esté bajo la ruta /var/www/ a través de la cláusula Require all granted.

Con esta configuración mínima, y haciendo que Apache reinicie o recargue su configuración YA funciona el nuevo servidor virtual.

Afinando la configuración del servidor virtual

Sería conveniente especificar un par de detalles más en la configuración de acceso al directorio web añadiendo un par de cláusulas más en el bloque Directory:

<VirtualHost *:80>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chacho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
</VirtualHost>

Añadimos una cláusula AllowOverride all para poder alterar el funcionamiento del servidor a través de los archivos .htaccess en el directorio web. Incluyo esta configuración porque ya no recuerdo cuál fue la última web en que trabajé que no necesitara un archivo .htaccess para realizar redirecciones, reescrituras de URLs, etc.

Otra cláusula que añado es Options -Indexes, con la que se prohíbe el acceso a carpetas y subcarpetas del sitio web que no contengan un archivo index (index.php, index.html, etc.) ya que si estuviese activada la opción Indexes se mostraría el contenido de la carpeta y se podría acceder a archivos cuya existencia el visitante normalmente no debería conocer. El comportamiento por defecto suele ser desactivar Indexes, pero lo especifico por seguridad. Quien quiera desactivar la prohibición de acceso debería especificar la cláusula como Options Indexes.

Activación de logs propios para el servidor virtual

Con esta configuración, los registros de acceso al servidor virtual se almacenan en el archivo /var/log/apache2/other_vhosts_access.log, mientras que los registros de error se añadirían al archivo /var/log/apache2/error.log.

Lo interesante es que cada servidor virtual tenga sus propios archivos de registro, tanto de acceso como de errores, así que añadiríamos algunas directivas más:

<VirtualHost *:80>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chacho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/vhost1.local-error.log
        CustomLog ${APACHE_LOG_DIR}/vhost1.local-access.log combined
        LogLevel info
</VirtualHost>

Es muy importante configurar de forma óptima los archivos de registro de cada servidor virtual, ya que ofrecen valiosísima información sobre accesos y errores.

Y con esta configuración tenemos ya muy perfilado el funcionamiento del servidor virtual. Para el servidor virtual del dominio vhost2.local el archivo sería muy parecido:

<VirtualHost *:80>
        ServerName vhost2.local
        DocumentRoot /home/chacho/public_html/vhost2
        <Directory /home/chacho/public_html/vhost2>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/vhost2.local-error.log
        CustomLog ${APACHE_LOG_DIR}/vhost2.local-access.log combined
        LogLevel info
</VirtualHost>

La diferencia es que para este dominio no se ha configurado ningún alias (no se podría acceder como www.vhost2.local) y se especifica su propio directorio de archivos web y archivos de registro personalizados.

Activación y desactivación de los servidores virtuales

Las configuraciones que acabamos de realizar se guardarían en sendos archivos de configuración, por ejemplo /etc/apache2/sites-available/vhost1.local.conf y /etc/apache2/sites-available/vhost2.local.conf.

Para que Apache cargue estas configuraciones es necesario crear los enlaces simbólicos correspondientes desde /etc/apache2/sites-enabled/. Esto se podría hacer a mano, pero normalmente Apache incluye utilidades para activar y desactivar los servidores virtuales.

En Debian con Apache 2.4 activamos un servidor virtual con el comando a2ensite:

~$ sudo a2ensite vhost1.local.conf vhost2.local.conf
Enabling site vhost1.local.
Enabling site vhost2.local.
To activate the new configuration, you need to run:
  systemctl reload apache2

Podemos indicar varios servidores virtuales en el mismo comando.

Para desactivar servidores virtuales tenemos el comando a2dissite:

~$ sudo a2dissite vhost1.local
Site vhost1.local disabled.
To activate the new configuration, you need to run:
  systemctl reload apache2

Ya sea activación o desactivación, cualquier cambio en la configuración de los servidores virtuales entrará en funcionamiento tras hacer que Apache recargue su configuración, o tras el siguiente reinicio de Apache.

Recargaremos la configuración de Apache con systemctl:

~$ sudo systemctl reload apache2

Antes de acceder a los servidores virtuales habrá que crear los directorios donde se alojará el contenido, referenciados en los archivos de configuración:

~$ mkdir -p public_html/vhost1 public_html/vhost2

Para no obtener errores de acceso, podemos añadir al menos un archivo index.html con cualquier contenido en cada directorio web de cada servidor virtual y ya estaremos listos para acceder desde el navegador a las direcciones http://vhost1.local, http://www.vhost1.local y http://vhost2.local.

como configurar virtual hosts en apache
Servidores virtuales en funcionamiento

 

Añadiendo configuración SSL a los servidores virtuales

Hasta aquí hemos configurado servidores virtuales que pueden ser accedidos mediante protocolo HTTP no seguro. Pero hoy día es raro no configurar un servidor web para que atienda peticiones bajo HTTP seguro o HTTPS.

Siguiendo con el ejemplo de esta guía configuraremos, por ejemplo, el servidor virtual del dominio vhost1.local para que funcione bajo HTTPS usando certificados SSL.

Para hacer esto usaremos el mismo archivo .conf del servidor virtual que estamos configurando, añadiendo al final del mismo un bloque VirtualHost pero trabajando en el puerto 443:

<VirtualHost *:443>
</VirtualHost>

Como primer paso, podemos copiar todo el contenido del bloque para el puerto HTTP (puerto 80), ya que la mayor parte de la configuración es idéntica:

<VirtualHost *:443>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chacho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/vhost1.local-error.log
        CustomLog ${APACHE_LOG_DIR}/vhost1.local-access.log combined
        LogLevel info
</VirtualHost>

Ahora hay que añadir la configuración específica para el uso de certificados SSL. En este ejemplo estamos configurando un dominio local, no accesible desde Internet, por lo que podemos usar certificados autofirmados.

En Debian durante la instalación del paquete ssl-cert se genera automáticamente un certificado autofirmado, que es el que utilizaré en este ejemplo. Si has generado otro distinto, especifica las rutas convenientemente.

Debemos añadir las siguientes directivas:

SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

Otro cambio que conviene hacer es modificar la directiva LogLevel, a la que se le he añade el parámetro ssl para establecer el nivel de registro, por ejemplo a partir de alertas.

LogLevel info ssl:warn

El bloque de configuración SSL para HTTPS quedaría así:

<VirtualHost *:443>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chaho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
        SSLEngine on
        SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
        SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
        ErrorLog ${APACHE_LOG_DIR}/vhost1.local-error.log
        CustomLog ${APACHE_LOG_DIR}/vhost1.local-access.log combined
        LogLevel info ssl:warn
</VirtualHost>

Configurando Apache para usar SSL (HTTPS)

No basta con crear configuraciones SSL para el servidor virtual. Apache debe cargar el módulo SSL, lo que podemos hacer con el comando a2enmod:

~$ sudo a2enmod ssl
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
systemctl restart apache2

Y como nos indica el propio comando, debemos reiniciar Apache:

~$ sudo systemctl reload apache2

Ya podemos acceder a la página web de nuestro servidor virtual tanto a través de HTTP, en la dirección http://vhost1.local, como a través de HTTPS, en la dirección https://vhost1.local.

Seguramente el navegador presentará una alerta por comprobar que el certificado no está firmado por autoridades certificadoras, pero aceptando (donde proceda, según el navegador), se presentará la página cifrada sin más problemas.

Configurando SSL para un dominio real

En el ejemplo de este tutorial estamos usando un dominio local para el servidor virtual, pero si te interesa un dominio de Internet entonces querrás usar un certificado firmado por alguna autoridad certificadora.

Suponiendo que ya tienes todo configurado y los certificados instalados en tu sistema, las directivas SSL del archivo de configuración serían algo así:

SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/tudominio.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/tudominio.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/tudominio.com/chain.pem

En este ejemplo tenemos instalados los certificados generados por la autoridad certificadora Let’s Encrypt para el dominio tudominio.com.

La configuración es muy similar, únicamente hay que añadir una directiva SSLCertificateChainFile para indicar el arhivo chain que verifica que el certificado está firmado por la autoridad certificadora (Let’s Encrypt en este caso).

Simplificando el archivo de configuración para el servidor virtual

Hasta ahora hemos configurado el servidor virtual vhost1.local con configuraciones idénticas para HTTP y HTTPS. Podríamos ofrecer páginas distintas si se accede mediante uno u otro protocolo, bastaría con especificar en la configuración distintas carpetas de documentos web. Pero lo habitual hoy día es no sólo ofrecer el mismo contenido, sino ofrecerlo únicamente vía HTTPS.

El archivo de configuración completo ha quedado así:

<VirtualHost *:80>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chacho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/vhost1.local-error.log
        CustomLog ${APACHE_LOG_DIR}/vhost1.local-access.log combined
        LogLevel info
</VirtualHost>

<VirtualHost *:443>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chaho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
        SSLEngine on
        SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
        SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        LogLevel info ssl:warn
</VirtualHost>

Para ofrecer todo el contenido cifrado modificaremos el archivo para dejarlo así:

<VirtualHost *:80>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        Redirect permanent / https://vhost1.local/
        ErrorLog ${APACHE_LOG_DIR}/vhost1.local-error.log
        CustomLog ${APACHE_LOG_DIR}/vhost1.local-access.log combined
        LogLevel info
</VirtualHost>

<VirtualHost *:443>
        ServerName vhost1.local
        ServerAlias www.vhost1.local
        DocumentRoot /home/chaho/public_html/vhost1
        <Directory /home/chacho/public_html/vhost1>
                Options -Indexes
                AllowOverride all
                Require all granted
        </Directory>
        SSLEngine on
        SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
        SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        LogLevel info ssl:warn
</VirtualHost>

Hay que mantener las directivas para los nombres de dominio y la configuración de archivos de registro, pero eliminamos la directiva DocumentRoot y el bloque Directory, sustituyéndolos por esta directiva Redirect:

Redirect permanent / https://vhost1.local

De esta forma, todas las peticiones HTTP se redirigirán a sus versiones HTTPS.

Conclusión

Hemos visto cómo configurar un servidor virtual Apache a través de archivos de configuración independientes para cada servidor, sacándole el máximo rendimiento a Apache. Mientras tengamos disco duro para los archivos web y memoria para atender procesos, podemos alojar tantos dominios como los recursos de la máquina sean capaces de servir simultáneamente.

Cualquier duda, sugerencia, corrección, mejora o proposición de nuevos artículos me la podéis hacer a través de los comentarios.

¡Apoya este sitio!

¡Ah!, y si te sido útil este artículo, siempre puedes invitarme a un café

1 estrella2 estrellas3 estrellas4 estrellas5 estrellas (4 votos, promedio: 5,00 de 5)
Cargando…

Esta entrada tiene un comentario

  1. Buenos días, qué pasa si quiero tener un subdominio dinámico? Intento usar
    ServerAlias *.midominio.com
    pero no funciona, estoy usando Ubuntu 16.04 y Apache 2.4.

Deja un comentario

Cerrar menú

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información

ACEPTAR
Aviso de cookies