Hosts Virtuales Nginx: Alojando Múltiples Sitios Web en un Solo Servidor
Aprovecha el poder de los hosts virtuales (bloques de servidor) de Nginx para alojar eficientemente múltiples sitios web o subdominios en un solo servidor. Esta guía proporciona un tutorial completo paso a paso, que cubre la configuración de directorios, la creación de archivos de configuración, la habilitación de bloques de servidor y las pruebas de Nginx. Aprende las mejores prácticas para subdominios, bloques de servidor predeterminados, integración HTTPS y registro dedicado. Ejemplos prácticos y consejos esenciales para la resolución de problemas te ayudarán a dominar el alojamiento multi-sitio con Nginx, optimizando el uso de recursos y simplificando la gestión del servidor web.
Hosts Virtuales Nginx: Alojando Múltiples Sitios Web en un Solo Servidor
Ejecutar varios sitios pequeños desde un solo servidor es un trabajo normal de Nginx. Puede que tengas un sitio de empresa, un sitio de documentación, una aplicación de staging y un portal de clientes, todos en la misma máquina. Nginx los separa con bloques server. La gente de Apache a menudo llama a la misma idea hosts virtuales, por lo que verás ambos términos utilizados en tutoriales y paneles de alojamiento.
La parte importante es simple: Nginx mira el puerto, la dirección IP y el encabezado Host, luego elige el bloque server que coincide. Si se carga el sitio equivocado, el problema generalmente no es misterioso. A menudo es un registro DNS faltante, un error tipográfico en server_name, un servidor predeterminado capturando la solicitud, o dos archivos reclamando el mismo nombre.
Entendiendo los Bloques de Servidor de Nginx (Hosts Virtuales)
En esencia, un bloque de servidor de Nginx es una directiva de configuración definida dentro del archivo de configuración de Nginx (nginx.conf o archivos incluidos). Cada bloque server define la configuración para un host virtual específico, dictando cómo Nginx debe responder a las solicitudes para un dominio particular o conjunto de dominios. Nginx usa la directiva listen para especificar la dirección IP y el puerto en los que debe escuchar, y la directiva server_name para identificar qué nombres de dominio o nombres de host debe responder este bloque de servidor.
Cuando llega una solicitud, Nginx examina el encabezado Host de la solicitud HTTP y lo compara con las directivas server_name de sus bloques de servidor configurados. Luego sirve el contenido definido en el bloque de servidor coincidente. Si ningún server_name coincide, Nginx normalmente recurre al bloque de servidor predeterminado (el primer bloque server o uno marcado explícitamente como default_server).
Prerrequisitos
Antes de comenzar, asegúrate de tener lo siguiente:
- Nginx Instalado: Nginx debe estar instalado y ejecutándose en tu servidor. Si no es así, normalmente puedes instalarlo a través del gestor de paquetes de tu sistema (por ejemplo,
sudo apt update && sudo apt install nginxen Ubuntu/Debian,sudo yum install nginxen CentOS/RHEL). - Nombres de Dominio: Necesitas al menos dos nombres de dominio (por ejemplo,
ejemplo1.comyejemplo2.com) o subdominios (por ejemplo,blog.ejemplo.comyapp.ejemplo.com) que quieras alojar. Los registros DNS A/AAAA de estos dominios deben apuntar a la dirección IP pública de tu servidor. - Estructura de Directorios Básica: Un plan de dónde residirán los archivos de tu sitio web. Una práctica común es
/var/www/tudominio.com/html. - Privilegios Sudo: Necesitarás acceso
sudopara modificar los archivos de configuración de Nginx.
Guía de Configuración Paso a Paso
Configuramos dos hosts virtuales: ejemplo1.com y ejemplo2.com.
Paso 1: Crear la Estructura de Directorios para los Sitios Web
Primero, crea directorios raíz para cada uno de tus sitios web. Aquí es donde se almacenarán sus archivos HTML, CSS, JavaScript y otros archivos estáticos. Una ubicación común es /var/www/.
sudo mkdir -p /var/www/ejemplo1.com/html
sudo mkdir -p /var/www/ejemplo2.com/html
# Establece la propiedad a tu usuario (reemplaza $USER con tu nombre de usuario) para permitir la edición
sudo chown -R $USER:$USER /var/www/ejemplo1.com/html
sudo chown -R $USER:$USER /var/www/ejemplo2.com/html
# Establece permisos de lectura para el servidor web
sudo chmod -R 755 /var/www
A continuación, crea un archivo index.html simple en cada directorio para probar la configuración:
Para /var/www/ejemplo1.com/html/index.html:
<!-- /var/www/ejemplo1.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>¡Bienvenido a Ejemplo1.com!</title>
</head>
<body>
<h1>¡Éxito! Este es Ejemplo1.com.</h1>
<p>Este host virtual está funcionando correctamente.</p>
</body>
</html>
Para /var/www/ejemplo2.com/html/index.html:
<!-- /var/www/ejemplo2.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>¡Bienvenido a Ejemplo2.com!</title>
</head>
<body>
<h1>¡Éxito! Este es Ejemplo2.com.</h1>
<p>¡Este host virtual también está funcionando!</p>
</body>
</html>
Paso 2: Crear Archivos de Configuración de Bloques de Servidor de Nginx
Nginx normalmente carga las configuraciones de los bloques de servidor desde archivos en el directorio /etc/nginx/sites-enabled/. Estos archivos suelen ser enlaces simbólicos a configuraciones almacenadas en /etc/nginx/sites-available/. Esta separación te permite almacenar configuraciones que aún no están activas o habilitar/deshabilitar sitios fácilmente.
Crea un nuevo archivo de configuración para ejemplo1.com:
sudo nano /etc/nginx/sites-available/ejemplo1.com.conf
Agrega el siguiente contenido:
# /etc/nginx/sites-available/ejemplo1.com.conf
server {
listen 80;
listen [::]:80;
root /var/www/ejemplo1.com/html;
index index.html index.htm index.nginx-debian.html;
server_name ejemplo1.com www.ejemplo1.com;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/ejemplo1.com_access.log;
error_log /var/log/nginx/ejemplo1.com_error.log;
}
Explicación de las Directivas:
listen 80;: Nginx escucha en el puerto 80 (HTTP estándar).listen [::]:80;es para IPv6.root /var/www/ejemplo1.com/html;: Especifica la raíz del documento para este bloque de servidor. Nginx buscará archivos dentro de este directorio.index index.html ...;: Define el archivo predeterminado que Nginx debe servir cuando se solicita un directorio (por ejemplo, cuando alguien visitaejemplo1.com/).server_name ejemplo1.com www.ejemplo1.com;: Esto es crucial. Le dice a Nginx que responda a las solicitudes deejemplo1.comowww.ejemplo1.comusando la configuración de este bloque de servidor.location / { ... }: Un bloque que define cómo manejar las solicitudes para URI específicas.try_filesintenta servir un archivo directamente ($uri), luego un directorio ($uri/), y finalmente devuelve un error404 Not Found.access_logyerror_log: Especifica archivos de registro separados para este sitio específico, lo cual es una buena práctica para una depuración y análisis más fáciles.
Ahora, crea un archivo de configuración similar para ejemplo2.com:
sudo nano /etc/nginx/sites-available/ejemplo2.com.conf
Agrega el siguiente contenido:
# /etc/nginx/sites-available/ejemplo2.com.conf
server {
listen 80;
listen [::]:80;
root /var/www/ejemplo2.com/html;
index index.html index.htm index.nginx-debian.html;
server_name ejemplo2.com www.ejemplo2.com;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/ejemplo2.com_access.log;
error_log /var/log/nginx/ejemplo2.com_error.log;
}
Paso 3: Habilitar Bloques de Servidor
Para habilitar estas configuraciones, crea enlaces simbólicos desde el directorio sites-available al directorio sites-enabled. Esto le dice a Nginx que incluya estos archivos cuando se inicie.
sudo ln -s /etc/nginx/sites-available/ejemplo1.com.conf /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/ejemplo2.com.conf /etc/nginx/sites-enabled/
Paso 4: Probar la Configuración de Nginx
Es crucial probar tu configuración de Nginx en busca de errores de sintaxis antes de recargar. Esto evita que Nginx no se reinicie debido a un error tipográfico.
sudo nginx -t
Deberías ver una salida similar a esta, indicando éxito:
nginx: la sintaxis del archivo de configuración /etc/nginx/nginx.conf es correcta
nginx: la prueba del archivo de configuración /etc/nginx/nginx.conf fue exitosa
Si ves algún error, corrígelo en los respectivos archivos de configuración y vuelve a ejecutar sudo nginx -t hasta que pase.
Paso 5: Reiniciar Nginx
Aplica la nueva configuración reiniciando o recargando Nginx. reload generalmente es preferido ya que permite a Nginx cargar nuevas configuraciones sin interrumpir las conexiones activas.
sudo systemctl reload nginx
# O, si recargar no funciona o para instalaciones nuevas:
sudo systemctl restart nginx
Paso 6: Actualizar Registros DNS
Asegúrate de que los registros DNS A para ejemplo1.com, www.ejemplo1.com, ejemplo2.com y www.ejemplo2.com apunten todos a la dirección IP de tu servidor Nginx. Sin entradas DNS correctas, tu navegador no sabrá dónde encontrar tus sitios web.
Una vez que la propagación de DNS se complete (lo que puede tomar desde unos minutos hasta varias horas), deberías poder visitar http://ejemplo1.com y http://ejemplo2.com en tu navegador web y ver las respectivas páginas index.html.
Escenarios Avanzados y Mejores Prácticas
Alojamiento de Subdominios
Alojar subdominios (por ejemplo, blog.ejemplo.com, tienda.ejemplo.com) funciona exactamente igual que alojar dominios separados. Solo defines un nuevo bloque de servidor con el subdominio como server_name.
Ejemplo para blog.ejemplo.com:
# /etc/nginx/sites-available/blog.ejemplo.com.conf
server {
listen 80;
listen [::]:80;
root /var/www/blog.ejemplo.com/html;
index index.html;
server_name blog.ejemplo.com;
location / {
try_files $uri $uri/ =404;
}
}
Recuerda crear el directorio (/var/www/blog.ejemplo.com/html), crear un index.html, crear el enlace simbólico y recargar Nginx.
El Bloque de Servidor Predeterminado
Es una buena práctica tener un bloque de servidor predeterminado que capture las solicitudes de nombres de dominio que no coinciden con ninguna otra directiva server_name en tu servidor. Esto evita que solicitudes desconocidas sean servidas por el primer host virtual que Nginx encuentre, o te permite servir una página genérica de "sitio no encontrado".
Normalmente, el primer bloque server en tu nginx.conf o sites-enabled es implícitamente el predeterminado. Puedes establecer uno explícitamente usando default_server:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# El guion bajo `_` es un nombre de dominio inexistente que nunca coincidirá con una solicitud real.
# También puedes usar localhost.
root /var/www/default_site/html;
index index.html;
location / {
return 444; # Devuelve un error 444 específico de Nginx (sin respuesta) para hosts desconocidos
# O, sirve una página de aterrizaje genérica:
# try_files $uri $uri/ =404;
}
}
Advertencia: Si defines un bloque default_server, asegúrate de que solo un bloque server en un puerto listen dado tenga la bandera default_server, de lo contrario Nginx registrará una advertencia.
Asegurando Hosts Virtuales con HTTPS (SSL/TLS)
Para sitios web en producción, habilitar HTTPS es esencial. Esto implica obtener un certificado SSL/TLS (por ejemplo, a través de Let's Encrypt usando Certbot) y configurar Nginx para escuchar en el puerto 443 con el certificado.
Un bloque de servidor HTTPS típico se ve así (después de obtener los certificados):
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ejemplo1.com www.ejemplo1.com;
root /var/www/ejemplo1.com/html;
index index.html;
ssl_certificate /etc/letsencrypt/live/ejemplo1.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ejemplo1.com/privkey.pem;
# Incluye otras configuraciones SSL (cifrados, protocolos, etc.)
include /etc/nginx/snippets/ssl-params.conf;
location / {
try_files $uri $uri/ =404;
}
}
# Opcional: Redirección de HTTP a HTTPS para este dominio
server {
listen 80;
listen [::]:80;
server_name ejemplo1.com www.ejemplo1.com;
return 301 https://$host$request_uri;
}
Es común tener un bloque de servidor HTTP separado cuyo único propósito es redirigir todo el tráfico a su contraparte HTTPS.
Si usas Certbot, puede crear o editar estos bloques por ti. Eso es conveniente, pero aún debes leer el archivo resultante. Las herramientas de certificados automatizadas a veces agregan lógica de redirección en un lugar que no habrías elegido tú mismo, y las redirecciones duplicadas pueden dificultar la resolución de problemas.
Registro para Cada Sitio
Como se muestra en los ejemplos, dedicar archivos access_log y error_log separados para cada host virtual es una buena práctica. Esto facilita significativamente la depuración de problemas y el análisis del tráfico de sitios web individuales sin tener que revisar registros combinados.
Estructura de Archivos de Configuración
Para implementaciones más grandes, considera organizar tus archivos de configuración de Nginx de esta manera:
nginx.conf: Configuración principal, incluyeconf.d/*.confysites-enabled/*.conf.d/: Configuraciones generales de todo el servidor (por ejemplo, Gzip, almacenamiento en caché).snippets/: Fragmentos de configuración de Nginx reutilizables (por ejemplo, parámetros SSL, bloqueslocationcomunes).sites-available/: Bloquesserverindividuales para cada sitio web.sites-enabled/: Enlaces simbólicos a configuraciones activas ensites-available/.
Solución de Problemas Comunes
- Error 403 Prohibido: Esto generalmente significa que Nginx no tiene acceso de lectura a los archivos o directorios de tu sitio web. Vuelve a verificar los permisos de archivos y directorios (por ejemplo,
sudo chmod -R 755 /var/www/tudominio.com/htmly asegúrate de que el usuario de Nginx, típicamentewww-dataonginx, pueda leerlos). - Error 404 No Encontrado: Verifica que la directiva
rooten tu bloque de servidor apunte al directorio correcto y que tu archivoindex.htmlexista en esa ubicación. Además, asegúrate de quetry_filesesté configurado correctamente. - Se Carga el Sitio Equivocado: Esto a menudo indica un problema con la directiva
server_name. Asegúrate de queserver_namecoincida exactamente con el nombre de dominio al que intentas acceder (incluyendowww.o subdominios). También, verifica tus registros DNS. - Nginx No Se Inicia/Recarga: Siempre usa
sudo nginx -tpara probar tu configuración antes de intentar recargar o reiniciar Nginx. Los mensajes de error señalarán la línea y el archivo donde ocurrió el error de sintaxis. - Problemas de DNS: Si puedes acceder a tu sitio por dirección IP pero no por nombre de dominio, es casi con certeza un problema de DNS. Usa
digonslookuppara verificar que los registros A de tu dominio apunten a la IP correcta del servidor.
Pruebas Antes de que el DNS Esté Listo
No tienes que esperar al DNS público para probar el lado de Nginx. Puedes enviar una solicitud con un encabezado Host personalizado:
curl -H "Host: ejemplo1.com" http://203.0.113.10/
curl -H "Host: ejemplo2.com" http://203.0.113.10/
Reemplaza 203.0.113.10 con la IP de tu servidor. Si cada comando devuelve la página de prueba correcta, la coincidencia del bloque de servidor está funcionando. Si ambos comandos devuelven la misma página, verifica si ambos archivos están habilitados, si server_name es correcto y si un bloque predeterminado está capturando la solicitud.
Para HTTPS, la prueba es un poco diferente porque TLS usa SNI antes de que se procese el encabezado HTTP Host:
curl --resolve ejemplo1.com:443:203.0.113.10 https://ejemplo1.com/
Ese comando le dice a curl que se conecte a la IP de tu servidor mientras sigue usando ejemplo1.com para TLS y HTTP. Es una de las formas más rápidas de probar un nuevo host virtual HTTPS antes de cambiar el DNS.
Un Patrón de Múltiples Sitios Mantenible
Para un puñado de sitios estáticos, los ejemplos anteriores son suficientes. Una vez que alojas varias aplicaciones, repite menos y centraliza solo las partes que son genuinamente compartidas. Por ejemplo, coloca encabezados de seguridad comunes, compresión y parámetros SSL en fragmentos, pero mantén root, server_name, upstream y registros de cada sitio visibles en su propio archivo.
Evita copiar un bloque de producción grande de un dominio a otro sin leer cada línea. Así es como se cuelan errores de server_name, rutas de certificados incorrectas y archivos de registro compartidos. Una lista de verificación práctica de revisión es corta:
- ¿
server_nameincluye cada nombre de host que los usuarios escribirán? - ¿
rootoproxy_passapunta a este sitio, no al anterior? - ¿Los registros de acceso y error están lo suficientemente separados para depurar este sitio solo?
- ¿
nginx -tpasa antes de recargar? - ¿
curl -H "Host: ..."ocurl --resolvedevuelve el sitio esperado?
Notas Finales
Los hosts virtuales de Nginx son confiables cuando cada sitio tiene un bloque de servidor claro, un server_name correcto y un respaldo predeterminado predecible. Mantén los archivos aburridos. Prueba cada cambio antes de recargar. Usa registros dedicados cuando los sitios importen. La mayoría de los problemas de múltiples sitios en Nginx se vuelven fáciles de resolver una vez que puedes probar si DNS, TLS/SNI o la coincidencia del bloque de servidor es la parte que falló.