Bueno pues a hacerlo todo manualmente, ahora que hemos pasado un rato toqueteandolo con Docker. Me he dado cuenta que quizás no era necesario hacerlo primero con Docker, no me ha facilitado nada realmente… pero no pasa nada, así he probado de hacerlo de ambas maneras.
Cuando haya terminado de hacerlo manualmente, probaré a hacer esta misma configuración manual en Docker usando volúmenes, aunque ya no sé si lo documentaré por aquí ese proceso porque creo que ya lo tendré bastante claro y será simplemente una cuestión de montar el volúmenes locales los directorios o los ficheros que necesite tocar, modificarlos y arrancar contenedores.
Instalar y configurar Nginx
apt-get install nginx
En teoría en Ubuntu no es necesario iniciar el servicio de ninguna forma adicional, lo hace automáticamente. Por lo que si visitamos la IP pública del servidor (navegador o CURL) nos debería devolver la página de bienvenida de Nginx.
Virtual Hosts
Son la forma de tener varios sitios diferentes, en el mismo servidor (todos apuntan a la misma IP y servidor) pero diferenciados por el dominio o subdominio.
Normalmente al instalar un servicio como Nginx, tenemos el directorio de configuración en /etc. No es una excepción. En /etc/nginx/ vemos dos directorios importantes
- sites-available/: configuración de los diferentes sitios en este servidor (podría ser cada uno ejecutando un lenguaje diferente por ejemplo). Tendremos default que es el sitio por defecto.
- sites-enabled/: los virtual hosts que queremos tener activados
Creemos un virtual host nuevo
Copiamos default a otro fichero, normalmente con el nombre del dominio, así tenemos una base
cd /etc/nginx/sites-available
cp default nombredominio.com
Modificando este fichero recién creado, vamos línea por línea:
##1
# antigua
server_name _;
#modificada
server_name nombredominio.com;
##2
# antigua
root /var/www/html;
#modificada
root /var/www/nombredominio;
##3
# antigua
listen 80 default_server;
listen [::]:80 default_server;
# modificada
listen 80;
listen [::]:80;
##4
# descomentar el bloque donde pone "# deny access to .htaccess files"
Detalles:
- server_name: identifica el nombre del servidor, el dominio… en este caso estaba «_» que es el caso en el que le llegue a Nginx un dominio que no coincida con ninguno de los server_name configurados. En ese caso, ejecutará el primer virtual host configurado. Es decir, no le estamos configurando a este virtual host ningún nombre en concreto si dejamos «_»
- root: directorio donde se alojarán los ficheros del sitio. Hay que asegurarse de crear el directorio en algún momento
- default_server: solo puede haber 1 virtual host identificado como default server… será el que se cargue cuando el dominio que le llegue a Nginx y que no coincida con ninguno de los server_name configurados
- Las líneas que deniegan el acceso a los ficheros .htaccess, las descomentamos también ya que estamos (donde pone deny access to .htaccess files). ¿Por qué? Si hemos copiado todo un sitio donde se ejecutaba Apache como servidor, seguramente nos hemos traído varios de estos ficheros .htaccess… Nginx no los usa y los mostrará como texto, y quizás haya información sensible.
Estos virtual hosts están «availables» (disponibles o creados) pero aún no están «enabled» (activados)
Habilitar un virtual host
Normalmente se crean enlaces simbólicos desde sites-available a sites-enabled
cd /etc/nginx/sites-available/
ln -s /etc/nginx/sites-enabled/nombredominio.com
Faltará crear un fichero index.html en /var/www/nombredominio.com
Probar y reiniciar
Cuando cambiamos la configuración de alguna cosa del servicio de Nginx, hemos de reiniciarlo.
Pero hacer cambios y reiniciar, se presta a que hayamos cometido un error y paremos el servidor al reiniciar. Antes probamos la configuración:
nginx -t
Si nos informa que todo ok
service nginx reload
Y listo, visitando la IP del servidor (o haciendo un CURL), su dominio (si apunta a la IP, si no lo hace lo hacemos por hosts) debería cargarnos ya este virtual host.
Cuidado porque los navegadores por defecto intentan cargar por https que escucha en el puerto 443 por defecto, y eso aún no lo tenemos. Para probarlo hay que asegurarse que estamos llamando a http://nombredominio.com (http, no https)
Instalar y configurar PHP
Pues como trabajo mucho con PHP, lo suyo sería hacer que Nginx pueda interpretar PHP por lo menos. Es el servicio de php-fpm
Instalación y configuración php-fpm
apt-get install php-fpm
Nos lo va a instalar e iniciar. Veremos que crea un montón de archivos .ini y algunos enlaces simbólicos
Ahora debemos habilitarlo en Nginx, y para ello editamos nuestro virtual host
vim /etc/sites-available/nombredominio.com
Y vemos que hay una sección comentada para PHP que pone «pass PHP scripts to FastCGI server» donde hemos de descomentarla y elegir entre las líneas que usan el archivo .sock o la conexión tcp. Por defecto en ubuntu debería ser el archivo .sock (o habría que habilitar el puerto para tcp, etc…). Así que dejamos comentada (o borramos…) la línea fastcgi_pass 127.0.0.1:9000 y el resto las descomentamos. Quedando así el bloque
# pass PHP scripts to FastCGI server
#
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
Cuidado que por defecto a mi me vino php.7.4-fpm.sock… pero la versión que se me ha instalado de PHP fue la última, la 8.1. Localizamos ese fichero y corregimos la ruta.
Además, hemos de añadir index.php a la lista de ficheros que Nginx buscará para ejecutar, donde pone comentado # Add index.php to the list if you are using PHP para que Nginx sepa qué fichero buscar y asegurarnos que la prioridad de lectura sea la que queremos
# Add index.php to the list if you are using PHP
index index.php index.html index.htm index.nginx-debian.html;
Creemos ahora un fichero index.php (/var/www/nombredominio.com/index.php) con algún contenido… lo normal es ponerle de contenido un phpinfo
<?php phpinfo()
Probar y reiniciar
Como antes:
nginx -t
# si todo ok
service nginx reload
Ya deberíamos poder ver el phpinfo en el navegador
Instalar y configurar MySQL
Muy rápidamente por no hacerlo largo
# instalar mysql y lo necesario para que PHP interaccione con MySQL
apt-get install mysql-server php-mysql
# crear usuario inicial (nunca uses root 1234 por favor jeje)
mysqladmin --user=root password "1234"
# si hemos instalado phpmyadmin, no permitirá que se conecte con user root
## logearnos en mysql
mysql -u root -p
## creamos otro usario superadmin para conectarnos desde phpmyadmin
CREATE USER 'phpmyadmin'@'localhost' IDENTIFIED BY '1234';
GRANT ALL PRIVILEGES ON *.* TO 'phpmyadmin'@'localhost' WITH GRANT OPTION;
SSL
Lo más habitual es usar Let’s Encrypt, que además de ser gratuito, permite automatizar la generación, renovación, etc, de certificados mediante scripts.
El más conocido es Certbot que en su web, basta con seleccionar el tipo de servidor y sistema operativo (Nginx y Ubuntu 20 en nuestro caso).
Seguimos los pasos para instalar Certbot, que nos envía a instalar snapd previamente que en Ubuntu ya viene preinstalado:
sudo snap install core; sudo snap refresh core
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
A partir de aquí podemos elegir que Certbot autoconfigure Nginx o que simplemente descargue los certificados y los configuramos nosotros. Vamos a elegir que lo autoconfigure. Importante: en la configuración de Nginx hemos puesto un server_name, debe ser público y accesible desde internet (porque el servidor de Let’s Encrypt se conectará al nuestro a revisar ciertos archivos… y si no es público no podrá hacerlo)
certbot --nginx
## introducimos email
## nos pregunta en qué server_name de los detectados queremos el HTTPS
## nos pregunta si queremos que haga el redirect HTTP>HTTPS
Nos devuelve el mensaje:
Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/[nombredominio.com]/fullchain.pem Key is saved at: /etc/letsencrypt/live/[nombredominio.com]/privkey.pem This certificate expires on 2023-02-17. Deploying certificate Successfully deployed certificate for [nombredominio.com] to /etc/nginx/sites-enabled/[nombredominio.com] Congratulations! You have successfully enabled HTTPS on [nombredominio.com]
¿Qué cambios a hecho en el archivo de configuración del virtual host?
Veremos que añade unas líneas que terminan con el comentario «# magaged by Certbot». Estas líneas las trae el fichero de configuraicón de Nginx por defecto pero comentadas más arriba.
## fichero: /etc/nginx/sites-enabled/[nombredominio.com]
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/nombredominio.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/nombredominio.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
Detalles:
- escucha en el puerto 443
- ssl_certificate: ruta al fullchain.pem
- ssl_certificate_key: ruta al privkey.pem
- include: hace un «include» de ese fichero de configuración de Nginx que tiene cosas de seguridad de certbot y nos advierte que si el fichero es modificado manualmente, no se podrá renovar automáticamente
- ssl_dhparam:
Certbot además habrá creado un cronjob para ejecutar la renovación del certificado, aunque podemos probarlo manualmente:
certbot renew --dry-run
El cronjob podemos verlo con systemctl list-timers.
Nota: en la forma manual que no nos autoconfigura Nginx, habría que hacer esos cambios citados anteriormente, a mano y mover los ficheros a los directorios correspondientes
SSL sin autoconfigurar Nginx
En el momento que ejecutaríamos certbot –nginx, en su lugar ejecutamos lo siguiente:
certbot certonly --nginx
Diferencias con la forma de antes:
- nos tirará las rutas en donde se encuentran los certificados en nuestra máquina pero no hará nada con ellos
- los cambios citados antes en el virtual host para enlazar ese virtual host con su certificado SSL tenemos que hacerlo nosotros
Nginx proxy
¿Qué es un proxy server?
Podríamos decir que es un servidor que se interpone entre quien hace la petición y quien la sirve, de forma que reenvía la petición.
El servidor proxy recibe la petición, a veces la procesa un poco (según configuraciones) y pasa esta petición a otro servidor. Este otro servidor, siempre que tenga un servicio http funcionando (no es necesario que sea otro Nginx).
Configuración básica
En nuestro virtual host, añadimos un location para la ruta que queramos que actúe de proxy. Por ejemplo /app
location /app {
proxy_pass http://11.111.11.111:8080;
proxy_set_header Host $host;
proxy_set_eader X-Real_Ip $remote_addr;
}
Detalles:
- proxy_pass: es lo que define el servidor al que reenviaremos la petición
- http://11.111.11.111: será la dirección al servidor
- proxy_set_header: como la petición llega al servidor proxy, todas las cabeceras originales las conoce este servidor… si pasamos la petición a otro servidor, este otro servidor no conoce ni si quiera la IP del cliente (conoce la IP del proxy…). Esto lo usamos para definir cabeceras y reenviarlas también
Balanceador de carga
Simplemente me interesa saber que en ese proxy_pass a veces podemos ver algo como
location /app {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_eader X-Real_Ip $remote_addr;
}
Ese http://backend está definido en el nginx.conf como un upstream. En el nginx.conf tenemos el bloque http y en los virtual hosts tenemos el bloque server. En este upstream veremos definidos unos server con una dirección de dominio o IP.
upstream backend {
server 11.111.11.111:8080 weight=5;
server 22.222.22.222:8080;
}
Detalles:
- server: define cada uno de los servers a los que queremos redirigir las peticiones
- weight: define cuántas peticiones debe recibir un server antes de enviar la siguiente petición al siguiente server definido