Configuración de Virtual Hosts en Apache: Guía Completa
Introducción
El alojamiento virtual es una potente característica de Apache que permite que un único servidor físico aloje múltiples sitios web, cada uno con su propio nombre de dominio, configuración y contenido. Esta capacidad ha revolucionado el alojamiento web, haciendo rentable ejecutar numerosos sitios web en un solo servidor mientras se mantiene un aislamiento completo entre sitios.
Apache admite dos tipos de alojamiento virtual: basado en nombres y basado en IP. El alojamiento virtual basado en nombres, el enfoque más común, utiliza la cabecera HTTP Host para determinar qué sitio web servir, permitiendo sitios web ilimitados en una sola dirección IP. El alojamiento virtual basado en IP asigna a cada sitio web una dirección IP única, lo cual es necesario para ciertas configuraciones SSL/TLS o cuando el alojamiento basado en nombres no es adecuado.
Esta guía completa cubre todo lo que necesitas saber sobre la configuración de virtual hosts en Apache. Aprenderás cómo configurar virtual hosts basados tanto en nombres como en IP, configurar certificados SSL/TLS, implementar las mejores prácticas de seguridad, solucionar problemas comunes y optimizar el rendimiento. Ya sea que estés alojando un pequeño blog o administrando un entorno complejo con múltiples sitios, dominar los virtual hosts es esencial para una administración efectiva de Apache.
Requisitos Previos
Antes de configurar virtual hosts, asegúrate de tener:
- Apache instalado y ejecutándose en Ubuntu/Debian o CentOS/Rocky Linux
- Acceso root o sudo a tu servidor
- Comprensión básica de la configuración de Apache
- Nombres de dominio configurados con DNS apuntando a la IP de tu servidor
- Familiaridad con los permisos de archivos y la estructura de directorios de Linux
- Conocimiento de editores de texto (nano, vim u otros)
- Comprensión de conceptos básicos de redes
- Certificados SSL/TLS (si configuras virtual hosts HTTPS)
Comprendiendo los Virtual Hosts
Virtual Hosts Basados en Nombres
El alojamiento virtual basado en nombres permite múltiples dominios en una dirección IP:
Flujo de Solicitud del Cliente:
1. El cliente solicita http://example.com/page.html
2. El navegador envía una solicitud HTTP con cabecera "Host: example.com"
3. Apache recibe la solicitud en la dirección IP 192.168.1.100:80
4. Apache verifica la cabecera Host contra los virtual hosts configurados
5. Apache sirve contenido del virtual host coincidente
6. Si no encuentra coincidencia, sirve del virtual host predeterminado
Ejemplo de configuración:
# Todos los virtual hosts comparten la misma IP
<VirtualHost 192.168.1.100:80>
ServerName example.com
DocumentRoot /var/www/example.com
</VirtualHost>
<VirtualHost 192.168.1.100:80>
ServerName another.com
DocumentRoot /var/www/another.com
</VirtualHost>
Virtual Hosts Basados en IP
El alojamiento virtual basado en IP asigna a cada sitio una IP única:
# Cada virtual host tiene una IP diferente
<VirtualHost 192.168.1.100:80>
ServerName example.com
DocumentRoot /var/www/example.com
</VirtualHost>
<VirtualHost 192.168.1.101:80>
ServerName another.com
DocumentRoot /var/www/another.com
</VirtualHost>
Casos de uso:
- SSL/TLS con Server Name Indication (SNI) no disponible
- Clientes que no envían cabeceras Host
- Requisito de direcciones IP separadas por sitio
Estructura de Directorios de Virtual Hosts
Ubuntu y Debian
Apache en Ubuntu/Debian usa una estructura sites-available/sites-enabled:
/etc/apache2/
├── sites-available/ # Todas las configuraciones de virtual hosts
│ ├── 000-default.conf # Virtual host HTTP predeterminado
│ ├── default-ssl.conf # Virtual host HTTPS predeterminado
│ ├── example.com.conf # Virtual host personalizado
│ └── another.com.conf # Otro virtual host
└── sites-enabled/ # Virtual hosts habilitados (enlaces simbólicos)
├── 000-default.conf -> ../sites-available/000-default.conf
└── example.com.conf -> ../sites-available/example.com.conf
Flujo de trabajo:
- Crear configuración en
sites-available/ - Habilitar con el comando
a2ensite(crea enlace simbólico) - Recargar Apache para aplicar cambios
CentOS, Rocky Linux y AlmaLinux
Los sistemas basados en Red Hat usan un enfoque más simple:
/etc/httpd/
└── conf.d/ # Todos los archivos *.conf se cargan
├── example.com.conf
├── another.com.conf
└── ssl.conf
Flujo de trabajo:
- Crear archivo .conf en
conf.d/ - Recargar Apache para aplicar cambios
Creando tu Primer Virtual Host
Paso 1: Crear el Directorio Raíz de Documentos
Crea la estructura de directorios para tu sitio web:
# Ubuntu/Debian
sudo mkdir -p /var/www/example.com/public_html
sudo mkdir -p /var/www/example.com/logs
# CentOS/Rocky/AlmaLinux
sudo mkdir -p /var/www/example.com/public_html
sudo mkdir -p /var/www/example.com/logs
Paso 2: Establecer Permisos Apropiados
Configurar propiedad y permisos:
# Ubuntu/Debian
sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com
# CentOS/Rocky/AlmaLinux
sudo chown -R apache:apache /var/www/example.com
sudo chmod -R 755 /var/www/example.com
En sistemas con SELinux habilitado (CentOS/Rocky/AlmaLinux):
# Establecer contexto SELinux correcto
sudo chcon -R -t httpd_sys_content_t /var/www/example.com/public_html
sudo chcon -R -t httpd_log_t /var/www/example.com/logs
# Hacerlo permanente
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example.com/public_html(/.*)?"
sudo semanage fcontext -a -t httpd_log_t "/var/www/example.com/logs(/.*)?"
sudo restorecon -Rv /var/www/example.com
Paso 3: Crear Contenido de Prueba
Crear un archivo index.html simple:
sudo nano /var/www/example.com/public_html/index.html
Agregar el siguiente contenido:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bienvenido a Example.com</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background: white;
padding: 40px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #d14836;
border-bottom: 3px solid #d14836;
padding-bottom: 10px;
}
.info {
background: #e8f4f8;
padding: 15px;
border-left: 4px solid #0088cc;
margin: 20px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>Bienvenido a Example.com</h1>
<p>¡Tu virtual host de Apache está configurado correctamente!</p>
<div class="info">
<strong>Información del Servidor:</strong><br>
Virtual Host: example.com<br>
Raíz de Documentos: /var/www/example.com/public_html<br>
Estado: Activo y Ejecutándose
</div>
<p>Ahora puedes subir el contenido de tu sitio web a este directorio.</p>
</div>
</body>
</html>
Paso 4: Crear la Configuración del Virtual Host
Configuración en Ubuntu/Debian
Crear el archivo de configuración del virtual host:
sudo nano /etc/apache2/sites-available/example.com.conf
Agregar la configuración básica:
<VirtualHost *:80>
# Configuración básica
ServerName example.com
ServerAlias www.example.com
ServerAdmin [email protected]
# Raíz de documentos
DocumentRoot /var/www/example.com/public_html
# Permisos de directorio
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Registro de logs
ErrorLog /var/www/example.com/logs/error.log
CustomLog /var/www/example.com/logs/access.log combined
# Opcional: Establecer variable de entorno
SetEnv ENVIRONMENT production
</VirtualHost>
Habilitar el virtual host:
# Habilitar el sitio
sudo a2ensite example.com.conf
# Probar la configuración
sudo apache2ctl configtest
# Recargar Apache
sudo systemctl reload apache2
Configuración en CentOS/Rocky/AlmaLinux
Crear el archivo de configuración:
sudo nano /etc/httpd/conf.d/example.com.conf
Agregar la configuración:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAdmin [email protected]
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/www/example.com/logs/error.log
CustomLog /var/www/example.com/logs/access.log combined
</VirtualHost>
Probar y recargar:
# Probar la configuración
sudo httpd -t
# Recargar Apache
sudo systemctl reload httpd
Configuración Avanzada de Virtual Hosts
Múltiples Nombres de Dominio (ServerAlias)
Alojar múltiples dominios apuntando al mismo contenido:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com example.net www.example.net example.org
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example-error.log
CustomLog ${APACHE_LOG_DIR}/example-access.log combined
</VirtualHost>
ServerAlias con Comodines
Coincidir con todos los subdominios:
<VirtualHost *:80>
ServerName example.com
ServerAlias *.example.com
DocumentRoot /var/www/example.com/public_html
# Registrar el subdominio en los logs de acceso
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_combined
CustomLog ${APACHE_LOG_DIR}/example-access.log vhost_combined
</VirtualHost>
Virtual Hosts de Subdominios
Crear virtual hosts separados para subdominios:
# Dominio principal
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
</VirtualHost>
# Subdominio de blog
<VirtualHost *:80>
ServerName blog.example.com
DocumentRoot /var/www/example.com/blog
<Directory /var/www/example.com/blog>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/blog.example-error.log
CustomLog ${APACHE_LOG_DIR}/blog.example-access.log combined
</VirtualHost>
# Subdominio de API
<VirtualHost *:80>
ServerName api.example.com
DocumentRoot /var/www/example.com/api
<Directory /var/www/example.com/api>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# Formato de registro específico para API
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" api_log
CustomLog ${APACHE_LOG_DIR}/api.example-access.log api_log
</VirtualHost>
Opciones Específicas de Directorio
Configurar diferentes opciones para diferentes directorios:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# Directorio principal del sitio web
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Directorio de descargas - habilitar listado de directorios
<Directory /var/www/example.com/public_html/downloads>
Options +Indexes +FollowSymLinks
AllowOverride None
Require all granted
IndexOptions FancyIndexing NameWidth=* DescriptionWidth=*
</Directory>
# Área de administración - restringir acceso
<Directory /var/www/example.com/public_html/admin>
Options -Indexes +FollowSymLinks
AllowOverride None
Require ip 192.168.1.0/24
Require ip 10.0.0.100
# Autenticación adicional
AuthType Basic
AuthName "Área de Administración"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
# Recursos estáticos - tiempos largos de caché
<Directory /var/www/example.com/public_html/assets>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
</Directory>
</VirtualHost>
Redirección de URL
Redirigir www a no-www (o viceversa):
# Redirigir www a no-www
<VirtualHost *:80>
ServerName www.example.com
Redirect permanent / http://example.com/
</VirtualHost>
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# ... resto de la configuración
</VirtualHost>
# Alternativa usando mod_rewrite
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1$1 [R=301,L]
</IfModule>
</VirtualHost>
Páginas de Error Personalizadas
Configurar páginas de error personalizadas por virtual host:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# Documentos de error personalizados
ErrorDocument 400 /errors/400.html
ErrorDocument 401 /errors/401.html
ErrorDocument 403 /errors/403.html
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html
ErrorDocument 502 /errors/502.html
ErrorDocument 503 /errors/503.html
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Crear páginas de error personalizadas:
sudo mkdir -p /var/www/example.com/public_html/errors
sudo nano /var/www/example.com/public_html/errors/404.html
Ejemplo de página 404:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - Página No Encontrada</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 50px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
h1 { font-size: 72px; margin: 0; }
p { font-size: 24px; }
a { color: #ffd700; text-decoration: none; }
</style>
</head>
<body>
<h1>404</h1>
<p>¡Ups! La página que buscas no existe.</p>
<p><a href="/">Volver a la página de inicio</a></p>
</body>
</html>
Virtual Hosts SSL/TLS
Configurar virtual hosts HTTPS:
Habilitar Módulo SSL
# Ubuntu/Debian
sudo a2enmod ssl
sudo systemctl restart apache2
# CentOS/Rocky/AlmaLinux
sudo yum install mod_ssl -y # o dnf
sudo systemctl restart httpd
Virtual Host HTTPS Básico
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
# Motor SSL
SSLEngine on
# Certificados SSL
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/chain.crt
# Protocolos y Cifrados SSL
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
SSLHonorCipherOrder on
# Cabecera HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example-ssl-error.log
CustomLog ${APACHE_LOG_DIR}/example-ssl-access.log combined
</VirtualHost>
# Redirección HTTP a HTTPS
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
Configuración de Let's Encrypt
Después de obtener certificados Let's Encrypt con Certbot:
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# Configuración SSL fuerte
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
# OCSP Stapling
SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Optimización de Rendimiento
Habilitar Compresión
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# Habilitar compresión
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE application/xml application/rss+xml
AddOutputFilterByType DEFLATE image/svg+xml
# No comprimir imágenes
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary
# Manejar peculiaridades del navegador
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# Agregar cabecera Vary
Header append Vary User-Agent env=!dont-vary
</IfModule>
</VirtualHost>
Caché del Navegador
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# Habilitar módulo de expiración
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
# HTML
ExpiresByType text/html "access plus 1 hour"
# Imágenes
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
# CSS y JavaScript
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# Fuentes
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
</IfModule>
# Cabeceras Cache-Control
<IfModule mod_headers.c>
<FilesMatch "\.(jpg|jpeg|png|gif|ico|svg)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
<FilesMatch "\.(css|js)$">
Header set Cache-Control "public, max-age=2592000"
</FilesMatch>
</IfModule>
</VirtualHost>
Integración con PHP-FPM
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# PHP-FPM vía proxy
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost"
</FilesMatch>
# O vía mod_fastcgi
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks +ExecCGI
AllowOverride All
Require all granted
</Directory>
# Configuración de timeout del proxy
ProxyTimeout 300
</VirtualHost>
Configuración de Seguridad
Control de Acceso Basado en IP
<VirtualHost *:80>
ServerName admin.example.com
DocumentRoot /var/www/example.com/admin
<Directory /var/www/example.com/admin>
Options -Indexes +FollowSymLinks
AllowOverride None
# Permitir solo IPs específicas
Require ip 192.168.1.0/24
Require ip 10.0.0.100
Require ip 203.0.113.50
# O denegar IPs específicas
<RequireAll>
Require all granted
Require not ip 192.0.2.100
</RequireAll>
</Directory>
</VirtualHost>
Autenticación Básica
<VirtualHost *:80>
ServerName secure.example.com
DocumentRoot /var/www/example.com/secure
<Directory /var/www/example.com/secure>
AuthType Basic
AuthName "Área Restringida"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
Options -Indexes +FollowSymLinks
AllowOverride None
</Directory>
</VirtualHost>
Crear archivo de contraseñas:
# Ubuntu/Debian
sudo htpasswd -c /etc/apache2/.htpasswd usuario
# CentOS/Rocky/AlmaLinux
sudo htpasswd -c /etc/httpd/.htpasswd usuario
Cabeceras de Seguridad
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# Cabeceras de seguridad
<IfModule mod_headers.c>
# Prevenir clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# Prevenir MIME sniffing
Header always set X-Content-Type-Options "nosniff"
# Protección XSS
Header always set X-XSS-Protection "1; mode=block"
# Política de Referrer
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Política de Seguridad de Contenido
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"
# Eliminar información del servidor
Header always unset X-Powered-By
Header always unset Server
</IfModule>
</VirtualHost>
Configuración de Registro de Logs
Formatos de Log Personalizados
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# Definir formato de log personalizado
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %b %D" performance
# Usar formatos personalizados
CustomLog ${APACHE_LOG_DIR}/example-access.log vhost_combined
CustomLog ${APACHE_LOG_DIR}/example-performance.log performance
ErrorLog ${APACHE_LOG_DIR}/example-error.log
# Establecer nivel de log de errores
LogLevel warn
</VirtualHost>
Logs Separados por Subdominio
<VirtualHost *:80>
ServerName blog.example.com
DocumentRoot /var/www/example.com/blog
ErrorLog /var/log/apache2/blog.example-error.log
CustomLog /var/log/apache2/blog.example-access.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName api.example.com
DocumentRoot /var/www/example.com/api
ErrorLog /var/log/apache2/api.example-error.log
CustomLog /var/log/apache2/api.example-access.log combined
</VirtualHost>
Registro Condicional
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
# No registrar archivos estáticos
SetEnvIf Request_URI "\.(gif|jpg|jpeg|png|css|js|ico)$" dontlog
# No registrar verificaciones de salud
SetEnvIf Request_URI "^/health$" dontlog
CustomLog ${APACHE_LOG_DIR}/example-access.log combined env=!dontlog
</VirtualHost>
Solución de Problemas
Probar la Configuración
Siempre probar la configuración antes de recargar:
# Ubuntu/Debian
sudo apache2ctl configtest
# CentOS/Rocky/AlmaLinux
sudo httpd -t
Verificar la Configuración del Virtual Host
# Ubuntu/Debian
sudo apache2ctl -S
# CentOS/Rocky/AlmaLinux
sudo httpd -S
La salida muestra:
- Todos los virtual hosts configurados
- Asignaciones de puertos
- Valores de ServerName y ServerAlias
- Virtual host predeterminado
Problemas Comunes
Problema: "Name or service not known"
# Asegurarse de que ServerName sea resoluble
# Agregar a /etc/hosts para pruebas:
sudo nano /etc/hosts
# Agregar: 127.0.0.1 example.com www.example.com
Problema: Se sirve el virtual host incorrecto
# Verificar el orden de virtual hosts
sudo apache2ctl -S
# Asegurarse de que ServerName coincida exactamente
# Verificar si hay un virtual host catch-all predeterminado
Problema: Errores de permiso denegado
# Verificar permisos de archivos
ls -la /var/www/example.com/
# Corregir permisos
sudo chown -R www-data:www-data /var/www/example.com # Ubuntu/Debian
sudo chown -R apache:apache /var/www/example.com # CentOS/Rocky
# Verificar SELinux (CentOS/Rocky/AlmaLinux)
sudo getenforce
sudo chcon -R -t httpd_sys_content_t /var/www/example.com/public_html
Mejores Prácticas
Configuración Organizada
Mantener los archivos de virtual hosts organizados:
# Convención de nombres en Ubuntu/Debian
/etc/apache2/sites-available/
├── 000-default.conf # Predeterminado/catch-all
├── example.com.conf # Dominio principal
├── blog.example.com.conf # Subdominio
└── api.example.com.conf # Subdominio de API
Documentación
Documentar cada virtual host:
#
# Configuración de Virtual Host: example.com
# Creado: 2024-01-15
# Modificado: 2024-01-20
# Propósito: Sitio web principal de la empresa
# Contactos: [email protected]
#
<VirtualHost *:80>
ServerName example.com
# ...
</VirtualHost>
Copias de Seguridad Regulares
Hacer copias de seguridad de las configuraciones de virtual hosts:
# Ubuntu/Debian
sudo tar -czf apache-vhosts-backup-$(date +%F).tar.gz /etc/apache2/sites-available/
# CentOS/Rocky/AlmaLinux
sudo tar -czf httpd-vhosts-backup-$(date +%F).tar.gz /etc/httpd/conf.d/
Monitoreo
Monitorear accesos y errores de virtual hosts:
# Log de acceso en tiempo real
sudo tail -f /var/log/apache2/example-access.log
# Log de errores en tiempo real
sudo tail -f /var/log/apache2/example-error.log
# Contar solicitudes por virtual host
sudo awk '{print $1}' /var/log/apache2/*-access.log | sort | uniq -c | sort -nr
Conclusión
Los virtual hosts son una característica fundamental de Apache que permite el alojamiento eficiente de múltiples sitios web en un solo servidor. Esta guía ha cubierto todo, desde virtual hosts básicos basados en nombres hasta configuraciones avanzadas de SSL/TLS, endurecimiento de seguridad y optimización de rendimiento.
Puntos clave:
- El alojamiento virtual basado en nombres permite sitios web ilimitados en una dirección IP
- La estructura de directorios y los permisos adecuados son esenciales para la seguridad
- Los virtual hosts SSL/TLS requieren configuración adicional pero son críticos para la web moderna
- La optimización de rendimiento mediante caché y compresión mejora la experiencia del usuario
- Las cabeceras de seguridad y los controles de acceso protegen tus sitios web
- Las pruebas y el monitoreo regulares aseguran una operación confiable
Domina la configuración de virtual hosts para administrar eficientemente múltiples sitios web, reducir costos de alojamiento y mantener entornos web seguros y de alto rendimiento. Continúa explorando temas avanzados como virtual hosts dinámicos con mod_vhost_alias, integración con herramientas de gestión de configuración y gestión automatizada de certificados SSL con Let's Encrypt.


