Apache VirtualHost Generator

Configura VirtualHosts con SSL, redirects 80→443 y logs personalizados.

toolboox.app/herramientas/apache-vhost-generator

Herramienta

apache.conf

Qué problema resuelve

Los VirtualHosts de Apache requieren varias directivas coherentes entre puertos 80 y 443.

Un VirtualHost es la unidad con la que Apache decide qué sitio sirve para cada petición: combina la dirección y puerto de escucha, el `ServerName`, la raíz de documentos y las políticas de acceso, logs y TLS. Configurarlo bien evita los dos errores clásicos del hosting: que un dominio nuevo muestre el contenido de otro y que el redirect a HTTPS entre en bucle. Este generador produce los dos bloques habituales (80 y 443) coherentes entre sí y listos para `a2ensite`.

Cómo elige Apache el VirtualHost que responde

Apache agrupa los VirtualHost por par IP:puerto y, dentro de ese grupo, compara la cabecera Host de la petición con ServerName y ServerAlias. Si ninguno coincide, sirve el primero definido, que actúa como host por defecto. De ahí viene el clásico "mi dominio nuevo muestra la web antigua": falta el ServerName o el fichero no está habilitado. Un patrón defensivo consiste en crear un VirtualHost catch-all que devuelva 444 o una página neutra y cargarlo primero (por ejemplo 000-default.conf), de modo que ningún dominio apuntado por error a tu IP herede un sitio real.

El bloque del puerto 80: sólo para redirigir

Con HTTPS obligatorio, el VirtualHost de :80 no debe servir contenido: su único trabajo es responder Redirect permanent / https://dominio/ o una RewriteRule con [R=301,L]. La excepción es la ruta /.well-known/acme-challenge/, que Let's Encrypt necesita en claro para validar el dominio en el método HTTP-01; si la rediriges toda, la renovación automática empieza a fallar a los tres meses y nadie se entera hasta que el certificado caduca. Excluye esa ruta con una RewriteCond explícita.

TLS moderno en el bloque 443

Una configuración razonable en 2026 usa SSLProtocol -all +TLSv1.2 +TLSv1.3, deja fuera TLS 1.0 y 1.1 (obsoletos por el RFC 8996) y activa SSLHonorCipherOrder off para que sea el cliente quien elija entre las suites modernas. Añade OCSP stapling con SSLUseStapling on y una caché compartida: reduce el tiempo de handshake y evita que el navegador consulte al emisor. La cabecera Strict-Transport-Security se añade sólo cuando todo el dominio, subdominios incluidos, funciona ya sobre HTTPS, porque el navegador la recordará durante todo el max-age. Puedes generar el CSR del certificado con el generador de CSR del sitio.

DocumentRoot, Directory y permisos

DocumentRoot marca la raíz servida, pero es el bloque <Directory> quien concede el acceso: sin Require all granted Apache devuelve 403 aunque los permisos de disco sean correctos. Usa Options -Indexes siempre, para que un directorio sin index.html no liste su contenido, y AllowOverride None en producción salvo que necesites .htaccess; leerlo en cada petición y en cada nivel de directorio tiene un coste medible. Si trabajas en hosting compartido y sólo tienes .htaccess, el generador de .htaccess cubre las mismas directivas de reescritura, caché y cabeceras.

Logs por sitio y formato útil

Separar ErrorLog y CustomLog por VirtualHost es lo que hace posible diagnosticar un sitio sin bucear en un fichero común de varios gigas. Merece la pena definir un LogFormat que incluya el tiempo de respuesta en microsegundos (%D) y la IP real del cliente cuando hay proxy (%{X-Forwarded-For}i), porque sin ellos no se pueden detectar ni la degradación de latencia ni el origen real del tráfico. Configura después logrotate con rotación diaria y postrotate que envíe apache2ctl graceful, o el disco acabará lleno un domingo por la noche.

Validar antes de recargar

El orden seguro es siempre: apache2ctl configtest (o httpd -t), luego a2ensite sitio.conf y finalmente systemctl reload apache2. reload aplica la configuración sin cortar conexiones activas; restart sí las corta. Si configtest avisa de "Could not reliably determine the server's fully qualified domain name", falta un ServerName global en apache2.conf: es un aviso inofensivo pero conviene resolverlo. Y ante un 403 o un 500, el fichero de ErrorLog del propio VirtualHost indica la línea y el motivo exactos.

Casos de uso comunes

  • Publicar un dominio nuevo con HTTPS y redirección 301 desde el puerto 80.
  • Alojar varios sitios en un mismo servidor sin que se mezclen entre sí.
  • Configurar un proxy inverso hacia una aplicación Node o Python en localhost.
  • Separar logs por cliente en un servidor compartido.
  • Migrar un sitio de .htaccess a configuración de VirtualHost por rendimiento.

Buenas prácticas

  • Define siempre `ServerName` y crea un VirtualHost por defecto que absorba dominios no configurados.
  • Excluye `/.well-known/acme-challenge/` de la redirección a HTTPS.
  • Usa `Options -Indexes` y `AllowOverride None` en producción.
  • Ejecuta `apache2ctl configtest` antes de cada `reload`.

Preguntas frecuentes

¿Por qué mi dominio muestra otro sitio?

Porque no coincide ningún `ServerName` y Apache sirve el primer VirtualHost del grupo IP:puerto. Añade el `ServerName` correcto y habilita el fichero con `a2ensite`.

¿Redirect o RewriteRule para forzar HTTPS?

`Redirect permanent` es más simple y suficiente si rediriges el sitio entero. Usa `RewriteRule` cuando necesites excepciones, como la ruta de validación de Let's Encrypt.

¿Reload o restart tras cambiar la configuración?

Reload: aplica los cambios sin cortar las conexiones en curso. Restart sólo si cambias puertos de escucha o módulos cargados.

¿Necesito un VirtualHost por subdominio?

No siempre: `ServerAlias` admite varios nombres e incluso comodines para el mismo sitio. Crea VirtualHost separados cuando cambien la raíz, los logs o el certificado.

¿Puedo usar .htaccess en vez de VirtualHost?

Para reescrituras y cabeceras sí, y es la única opción en hosting compartido. En un servidor propio el VirtualHost es más rápido porque se lee una sola vez al arrancar.