Los ficheros de definición de Virtual Hosts en nginx se almacenan en directorios muy similares a los de apache. Tenemos un directorio llamado sites-available y otro que se llama sites-enabled y ambos están bajo el directorio principal de configuración que es /etc/nginx. En el primero se deberían de guardar todos los virtual hosts del servidor (estén disponibles o no) y en el segundo aquellos que están activos. La forma correcta de activar o desactivar un Virtual Host debería de ser crear un enlace en el segundo directorio al archivo correspondiente del primero, al igual que en Apache. Para desactivarlo temporal o definitivamente borraríamos ese enlace. La diferencia aquí con apache es que no contamos con comandos similares a los a2ensite y a2dissite que hacen estas operaciones de forma cómoda, pero tampoco se nos van a caer los anillos por hacer un enlace manualmente en línea de comando a estas alturas ¿verdad? Bueno, por si acaso, el siguiente comando realizaría un enlace del fichero de definición de Virtual Host llamado miweb del directorio sites-availabe en el directorio sites-enabled:
ln -s /etc/nginx/sites-available/miweb /etc/nginx/sites-enabled/
Veamos ahora el «esqueleto» de configuración más básico en Apache:
<VirtualHost *:80> ServerName www.miweb.com ServerAlias blog.miweb.com *.miweb.es DocumentRoot /var/www/miweb/ DirectoryIndex index.php index.html index.htm; </VirtualHost>
Y su equivalente en nginx:
server { listen 80; server_name www.miweb.com blog.miweb.com *.miweb.es; root /var/www/miweb/; index index.php index.html index.htm; }
Puesto que partimos de que conocemos la sintaxis en Apache no deberíamos de encontrar problemas en entender la de nginx ¿verdad? Sólo un detalle adicional sobre estas líneas. Si tenemos un servidor con más de un interfaz y/o dirección IP y queremos que el servidor web sólo atienda a una de ellas en Apache sustituiríamos la primera línea del ejemplo anterior por esta:
<VirtualHost 123.45.67.89:80>
En nginx haríamos lo propio modificando así la segunda línea:
listen 123.45.67.89:80;
Cualquier configuración adicional del Virtual Host se realizaría incluyendo las directrices adecuadas en el interior del bloque de definición. Veamos algunas de las más comunes. Por ejemplo, si queremos dar una ubicación concreta y separada del lugar donde se almacenan los logs de acceso y error, en Apache lo hacíamos con estas líneas:
CustomLog /var/log/apache2/miweb-access.log combined ErrorLog /var/log/apache2/miweb-error.log LogLevel warn
Y en nginx lo haríamos así:
access_log /var/log/nginx/miweb-access.log; error_log /var/log/nginx/miweb-error.log warn;
El formato del log de accesos por defecto en nginx es idéntico al modo combined de Apache. No obstante, tenemos un montón de opciones adicionales que puedes consultar aquí. Los niveles permitidos para el log de error son, además de warn, error, crit, alert, y emerg.
¿Cómo redefinimos las páginas de error que nos mostrará el servidor web? En Apache usábamos la directiva ErrorDocument:
ErrorDocument 404 /errores/404.html ErrorDocument 500 /errores/500.html ErrorDocument 502 /errores/502.html ErrorDocument 503 /errores/503.html ErrorDocument 504 /errores/504.html
En nginx usamos error_page:
error_page 404 /errores/404.html; error_page 500 /errores/500.html; error_page 502 /errores/502.html; error_page 503 /errores/503.html; error_page 504 /errores/504.html;
Si queremos redireccionar varios errores a una misma página podemos hacerlo de esta forma:
error_page 500 502 503 504 /errores/500bis.html;
Veamos ahora como se restringe el acceso a ciertos directorios. En Apache, para denegar el acceso a todo el mundo a un directorio del servidor web lo hacíamos de esta forma:
<Directory /secreto> Deny from all </Directory>
Mientras que en nginx haríamos lo mismo así:
location /secreto { deny all; }
Para restringir el acceso a determinados clientes, en Apache «jugamos» con las directrices Order, Deny y Allow. En nginx no existe ninguna directiva similar a Order. Debemos de poner una a una todas las instrucciones deny y allow que necesitemos. El servidor las analizará una a una y en orden hasta encontrar la primera que «cuadre» con la petición que está atendiendo de forma similar a como se comportaría un cortafuegos. Las siguientes reglas son todas válidas:
location /secreto2 { deny 192.168.1.1; allow 192.168.1.0/24; allow 10.1.1.0/16; allow 2001:0db8::/32; deny all; }
Si lo que queremos es restringir el acceso mediante usuario y contraseña con un fichero generado con htpasswd como hacíamos habitualmente con Apache, podemos hacerlo de forma fácil. El fichero de contraseña lo generamos de la misma forma que ya sabemos (tienes que tener instalado el paquete apache2-utils para contar con esta utilidad) e incluir las siguientes directivas:
location /secreto3 { auth_basic "Control de Acceso"; auth_basic_user_file /etc/nginx/.htpasswd; }
La línea auth_basic sólo aporta un mensaje de texto que aparecerá en la ventana en la que se nos pide el usuario y contraseña. La directiva auth_basic_user_file es la que marca el lugar y el nombre del fichero que contiene los usuarios y las contraseñas (las hashes de estas, en realidad) autorizadas para acceder al directorio /secreto3 de nuestro Virtual Host.
Si nuestro Virtual Host necesita interpretar páginas en PHP, debemos de pasar estas peticiones al módulo adecuado y tenemos que expecificarlo aquí, y no como ocurría en Apache que se hacía de forma automática con sólo tener activo el módulo php5. Yo uso php5-fpm (aunque existen otras alternativas) y para que funcione debemos de incluir un bloque como este:
location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
En Debian hay que instalar el paquete correspondiente (apt-get install php5-fpm) y asegurarse de que el módulo aceptará las peticiones en la dirección que hemos indicado con la directiva fastcgi_pass. Esto lo comprobamos en el fichero de configuración /etc/php5/fpm/pool.d/www.conf y buscando la línea siguiente:
listen = /var/run/php5-fpm.sock