7.2.2.2.2. Dominios virtuales¶
Es común que un mismo servidor web sirva páginas cuyo nombre de sitio es distinto. Por ejemplo, un sitio puede ser sitio1.dominio.org y otro distinto sitio2.dominio.org. Sin embargo, ambos están alojados en nuestro servidor web.
Para lograr tal, debemos utilizar tres sentencias: server, listen y server_name. Por ejemplo:
# cat /etc/nginx/sites-available/sitio1
server {
listen 80;
server_name sitio1.dominio.org;
try_files $uri $uri/ =404;
root /srv/www/sitio1;
}
# cat /etc/nginx/sites-available/sitio2
server {
listen 80;
server_name sitio2.dominio.org;
try_files $uri $uri/ =404;
root /srv/www/sitio2;
}
Por lo general, cada sentencia server
se corresponde con un dominio virtual
distinto, y cada dominio se coloca en un fichero distinto. Además, para que
estén habilitados, los ficheros tienen que estar enlazados en
sites-enabled
por lo que es necesario:
# cd /etc/nginx/sites-enabled
# ln -fs ../sites-available/sitio1
# ln -fs ../sites-available/sitio2
7.2.2.2.2.1. server_name¶
No obstante lo anterior, las cosas pueden complicarse hasta el punto de que server_name tiene un apartado dedicado en exclusiva a su explicación[1]. De hecho, server_name no tiene por qué contener un nombre sin más, sino que puede contener:
Un nombre, como sitio1.dominio.org.
Un nombre con comodín al comienzo (p.e. *.dominio.org) o al final (p.e. www.dominio.*).
Una expresión regular (con sintaxis PCRE), en cuyo caso debe comenzarse la expresión con una virgulilla, como ~^www.([^.]+.[^.]+)$.
Una combinación cualquiera de las tres posibilidades anteriores:
server_name dominio.org *.dominio.org;
Nota
La documentación nos advierte de que el nombre .dominio.org se trata de forma especial y equivale a la combinación de nombres usada justamente encima de esta nota:
server_name .dominio.org;
Las expresiones regulares, además de permitir definir patrones bastantes complicados de coincidencia, permiten almacenar parte del nombre en una variable y usarlo luego en la configuración. Por ejemplo:
server {
listen 80;
server_name ~^([^.]+)\..*;
root /srv/www/$1;
try_files $uri $uri/ =404;
}
Advertencia
Cuando una expresión regular contiene llaves de apertura o cierre, o punto y coma es preciso encerrarla entre comillas dobles.
no sólo eso, sino que se puede usar la captura con nombres para facilitar la lectura de la configuración:
server {
listen 80;
server_name ~^(?P<vhost>[^.]+)\..*;
root /srv/www/$vhost;
try_files $uri $uri/ =404;
}
Nota
Como valor se puede usar también una ip o una ip con comodín:
server_name 172.22.0.2 192.168.*;
Nota
Hay algunas apuntes en la documentación oficial sobre la forma en que
nginx procesa y compara el campo Host:
con los valores de la
directiva y nos explica que, obviamente, es más eficiente la comparación de
nombres exactos y luego de nombres con comodines que la comparación con
expresiones regulares. Además, nos advierte de que, si a un servidor se
accede mayoritariamente con un nombre, es mejor declarar explícitamente ese
nombre. Por tanto es mejor desde el punto de vista del rendimiento, esto:
server_name www.dominio.org dominio.org *.dominio.org;
que esto otro:
server_name .dominio.org;
7.2.2.2.2.2. Selección del dominio virtual¶
Conocido cómo escribir la directiva server_name, lo interesante es saber cuál es el algoritmo que sigue nginx para seleccionar cuál es el bloque server que usará para responder a una petición. El algoritmo es el siguiente:
Se seleccionan aquellos bloques cuya directiva listen esté en consonancia con la petición.
Para los bloques anteriores, se escoge aquel en que el valor de la directiva server_name concuerde con el campo
Host:
de la peticiónSi son varios los bloques, entonces la precedencia en la concordancia con server_name es la siguiente:
Nombre exacto.
Nombre con comodín al principio. Cuanto más largo, más precedente.
Nombre con comodín al final. Cuanto más largo, más precedente.
Expresión regular. Si hay concordancia con varias expresiones regulares se coge el bloque server concordante que aparece en primer lugar dentro del fichero[2].
Si no hay bloque seleccionado por falta de concordancia, se toma aquel que incluya el parámetro
default_server
en su sentencia listen:listen 80 default_server;
y, si ningún bloque tenía una sentencia listen que incluyera el parámetro, se toma el primer server[2][3].
Notas al pie