Configurar vhosts en nginx
10.04.2017 Hosting Apache Nginx vhostsComo ya comenté en el pasado, para este sitio (y otros en el mismo server) estoy utilizando Apache para servir el PHP en el puerto 8080 y al frente un nginx como reverse proxy, que redirecciona las peticiones PHP al Apache y sirve los archivos estáticos, utilizando el prótocolo http2.
Entonces vamos a ver como configurar los vhosts en ambos servers para poder servir más de un sitio desde la misma VM.
Configurar Apache
Para agregar vhosts a Apache vamos a ir a /etc/apache2/sites-available y agregar ahi las configuraciones. En este ejemplo vamos a suponer que agregamos sitio1.com y sitio2.com, cuyos dominios ya deberían estar apuntando a los nameservers de nuestro hosting.
Entonces vamos a crear el archivo sitio1.conf:
<VirtualHost *:8080>
ServerAdmin [email protected]
ServerName sitio1.com
#esta linea NO HACE FALTA, ya que nginx se encargará de redireccionar www, la dejamos a modo de ejemplo
ServerAlias www.sitio1.com
DocumentRoot /var/www/vhosts/sitio1/htdocs
<Directory /var/www/vhosts/sitio1/htdocs>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
AccessFileName .htaccess
LogLevel warn
ErrorLog /var/www/vhosts/sitio1/logs/error.log
CustomLog /var/www/vhosts/sitio1/logs/access.log combined
</VirtualHost>
Y sitio2.conf:
<VirtualHost *:8080>
ServerAdmin [email protected]
ServerName sitio2.com
DocumentRoot /var/www/vhosts/sitio2/htdocs
<Directory /var/www/vhosts/sitio2/htdocs>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
AccessFileName .htaccess
LogLevel warn
ErrorLog /var/www/vhosts/sitio2/logs/error.log
CustomLog /var/www/vhosts/sitio2/logs/access.log combined
</VirtualHost>
Observando el archivo se ve que sitio1 se sirve desde /var/www/vhosts/sitio1/htdocs y sitio2 desde /var/www/vhosts/sitio2/htdocs. También tengo la costumbre de separar los logs por vhost, de esta forma es más simple encontrar errores o tomar métricas específicas para cada sitio. Por esto vamos a crear los directorios que necesitamos:
mkdir -p /var/www/vhosts/sitio1/htdocs
mkdir /var/www/vhosts/sitio1/logs
mkdir -p /var/www/vhosts/sitio2/htdocs
mkdir /var/www/vhosts/sitio2/logs
Como último paso, nos queda habilitar las configs, para esto hacemos:
a2ensite sitio1
a2ensite sitio2
service apache2 restart
Con esto terminamos la configuración de apache, pero todavía no podemos acceder a nuestros sitios porque, recordemos, el que sirve desde el puerto 443 es nginx, asi que vamos al siguiente paso.
Configurar nginx
La configuración de nginx es muy similar a la de Apache, de hecho usan la misma estructura de directorios (solo que los archivos de configuración de nginx, al igual que los de apache anteriores a la versión 2.4, no tienen extensión). Asi que nos vamos al directorio /etc/nginx/sites-available y creamos nuestros dos archivos, sitio1 y sitio2:
#archivo /etc/nginx/sites-available/sitio1
server {
listen 443 deferred ssl http2 default_server;
listen [::]:443 deferred ssl http2 default_server;
# gzip should not be used with ssl
gzip off;
ssl_certificate /etc/letsencrypt/live/sitio1.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sitio1.com/privkey.pem;
root /var/www/vhosts/sitio1/htdocs;
index index.php;
server_name sitio1.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
location ~* \.(gif|jpg|jpeg|js|css)$ {
try_files $uri =404;
}
location ~ /\.ht {
deny all;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/sitio1.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sitio1.com/privkey.pem;
server_name www.sitio1.com;
return 301 https://sitio1.com$request_uri;
}
server {
listen 80;
listen [::]:80;
server_name sitio1.com www.sitio1.com;
return 301 https://$server_name$request_uri;
}
#archivo /etc/nginx/sites-available/sitio2
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# gzip should not be used with ssl
gzip off;
ssl_certificate /etc/letsencrypt/live/sitio2.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sitio2.com/privkey.pem;
root /var/www/vhosts/sitio2/htdocs;
index index.php;
server_name sitio2.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
location ~* \.(gif|jpg|jpeg|js|css)$ {
try_files $uri =404;
}
location ~ /\.ht {
deny all;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/sitio2.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sitio2.com/privkey.pem;
server_name www.sitio2.com;
return 301 https://sitio1.com$request_uri;
}
server {
listen 80;
listen [::]:80;
server_name sitio2.com www.sitio2.com;
return 301 https://$server_name$request_uri;
}
Básicamente acá lo que hacemos es: escuchar en el puerto 443 y servir contenido de sitio1.com y sitio2.com, en el mismo puerto redireccionar www.sitio1.com y www.sitio2.com a sus correspondientes URLs sin el www y escuchar el puerto 80 para redireccionar a https. Recordemos que esta configuración se complementa con la configuración de SSL de nginx.
Para que nginx efectivamente lea las configuraciones tenemos que crear los links simbólicos desde sites-enabled:
cd /etc/nginx/sites-enabled
ln -s /etc/nginx/sites-available/sitio1 sitio1
ln -s /etc/nginx/sites-available/sitio2 sitio2
Esto es exactamente lo mismo que hace apache automáticamente si usamos a2ensite.
Validamos que la config esté OK y reiniciamos Nginx:
nginx -t
service nginx restart
Y con esto estamos listos para servir nuestros dos sitios desde el mismo server.
Ya se pueden agregar los archivos a las carpetas /var/www/vhosts/sitio1/htdocs y /var/www/vhosts/sitio2/htdocs y ver el contenido de ambos sitios. Igual más que subir via ftp o scp yo prefiero utilizar git para hacer los despliegues.
Espero les sea útil.