Ir al contenido principal

Configuracion de dns y apache para facilitar microservicios de php

Muchos de los conceptos detras de los microservicios son excepcionales: el aislamiento de dependencias externas, y la capacidad de desplegar de forma autónoma permiten una enorme flexibilidad a cualquier proyecto empresarial en el que conviben diferentes lineas de negocio, con requisitos cambiantes y en ocasiones contradictorios.

Las implementaciones existentes de micro servicios actuales funcionan en base a imagenes docker que en muchos casos ejecutan un springboot, y que son desplegados en openshift o kubernetes... Lo que resultan en unas necesidades de RAM extraordinarias: montar un entorno de desarollo capaz de ejecutar seis microservicios con springboot (acceso, notificaciones, inventario, tarifas, pagos, y transportes) va a consumir unos 5Gb de RAM. Con quarkus el consumo podría bajar a unos 2Gb, pero sigue siendo un consumo enormemente elevado. Hay que tener en cuenta que a mayores en muchos casos se va a necesitar al menos un servidor de base de datos, y otros servicios.

Php parece un lenguaje perfecto para los microservicios:

  • Funciona en base a respuesta a invocaciones a scripts: levanta el entorno para responder a la petición, y lo destruye al terminar.
  • Cada script es un contexto separado: las dependencias y librerías se incluyen explicitamente en cada script. Dos scripts en el mismo directorio pueden incluir ficheros de versiones diferentes de una determinada librería sin conflictos.
  • No require configuración, ni instalación, ni preparación: copiar los scripts es suficiente para tenerlo disponible.

Con todo esto en mente, vamos a ver si podemos hacer alguna prueba de concepto con php.

Creación de un espacio de trabajo en apache

El enfoque en micro servicios requiere que desde el inicio del desarrollo se enfoque cada micro como una aplicación diferenciada, desplegada en un servidor diferenciado. Con php y apache podemos alojar varias aplicaciones que compartan la misma versión de php en el mismo servidor, y configurar virtual hosts para poder "aislarlas".

Si configuramos nuestro servidor para que acceso.app.servidor.net apunte a un directorio, notificaciones.app.servidor.net apunte a otro, y así sucesivamente ya tenemos una configuración inicial orientada a micro servicios que nos facilitará mucho un escalado en el tiempo moviendo aplicaciones y dominios a otros servidores para conseguir mayor potencia.

Lets encrypt para los certificados

Si disponemos de un certificado, o no queremos usar ssl, podemos saltarnos esta primera parte.

En mi caso, esto nace como un side project, sin cpd ni nada que pueda ser parecido, simplemente un servidor vps en ovh que sirva como punto de pruebas publico, asi que el uso de lets encrypt es una opción magnifica.

En nuestro proveedor de domimnios vamos a crear un registro dns de tipo A o NAME que apunte *.app.servidor.net hacia nuestro servidor. Cualquier petición a un subhost de app.servidor.net se resolverá en nuestro servidor, evitandonos la necesidad de configurar en el registro de dns por cada nuevo servicio.

Instalamos certbot (yo ya lo tenía instalado, asi que no recuerdo el proceso exacto); y luego instalamos los scripts de actualización de dns.

sudo apt install python3-certbot-dns-ovh
sudo apt install python3-certbot-apache
  

Vamos a crear un token de ovh en la url https://eu.api.ovh.com/createToken/, y le damos permisos para modificar los dns (y responder automáticamente a los desafios de ovh):

  • GET /domain/zone/*
  • PUT /domain/zone/*
  • POST /domain/zone/*
  • DELETE /domain/zone/*

Los datos a introducir son:

dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = xxxx
dns_ovh_application_secret = xxxx
dns_ovh_consumer_key = xxxx
  

Con esos datos, rellenamos el fichero /etc/letsencrypt/ovh.ini y nos aseguramos que tenga la mascara de permisos 600:

sudo vi /etc/letsencrypt/ovh.ini
sudo chmod 600 /etc/letsencrypt/ovh.ini
  

Ya estamos listos para pedir el certificado y para comprobar si se podrá renovar automáticamente. El proceso de generación del certificado incluye la generación de un registro dns de tipo txt (para verificar que somos los dueños del dns servidor.net) y el script introduce un delay de 2 minutos para esperar a la propagación del registro que se crea de forma automática. Entiendo que es posible que si la propagación de dns no funciona agil tendrémos un error en el script, y tocará repetirlo.

sudo certbot certonly --dns-ovh --dns-ovh-credentials /etc/letsencrypt/ovh.ini -d "*.app.servidor.net" -d "app.servidor.net"
sudo certbot rew --dry-run

Y con esto ya tenemos certificados ssl para cualquier subdominio que exista bajo app.servidor.net

Vhost dinámicos con apache

Utilizaremos el módulo mod_vhost_alias para redirigir dinámicamente las solicitudes a un directorio basado en el subdominio: 

Ejecuta el siguiente comando para habilitar el módulo:
sudo a2enmod vhost_alias
sudo systemctl reload apache2
Y creamos un fichero en sites-availables con la configuración del site.
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster@app.servidor.net
ServerName app.servidor.net
ServerAlias *.app.servidor.net

SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/app.servidor.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/app.servidor.net/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

# Usar el nombre del subdominio para encontrar el directorio
UseCanonicalName Off
VirtualDocumentRoot /var/www/app.servidor.net/hosts/%1

# Archivos de logs
ErrorLog ${APACHE_LOG_DIR}/app.servidor.net-error.log
CustomLog ${APACHE_LOG_DIR}/app.servidor.net-access.log combined
</VirtualHost>
</IfModule> 

Tenemos que tener en cuenta que Apache intrepreta los archivos de "sites-enabled" por orden alfabetico, y si tenemos algun site que configura rutas de servidor "superiores" con wildcard, nuesta configuración de app.servidor.net no funcionará. Para controlarlo, podemos usar prefijos numéricos 000-, 001- etc para asegurarnos el orden de interpretación, y poniendo "muy hacia el final" los ficheros de más alto nivel.

Con esto, activamos el vhost:

sudo a2ensite 010-app.servidor.net.conf
sudo systemctl reload apache2

Y creamos un par de directorios para sendas aplicaiones futuras:

sudo mkdir -p /var/www/app.servidor.net/hosts/acceso
sudo chown -R www-data:www-data /var/www/app.servidor.net/hosts/acceso
sudo chmod -R 755 /var/www/app.servidor.net/hosts/acceso

sudo mkdir -p /var/www/app.servidor.net/hosts/notificaciones
sudo chown -R www-data:www-data /var/www/app.servidor.net/hosts/notificaciones
sudo chmod -R 755 /var/www/app.servidor.net/hosts/notificaciones

Copiamos un sencillo "Hola mundo desde acceso|notificaciones" y un "php info" en cada directorio... y verificamos:

  • https://acceso.app.servidor.net para ver un hola desde acceso.
  • https://notificacioens.app.servidor.net para ver un hola desde notificaciones
  • https://nono.app.servidor.net para tener un error 404.

Como colofon: podemos usar apache2ctl -S para ver la configuracion ssl que se ha configurado en el servidor y debuguear posibles errores.

sudo apache2ctl -S

Con esta configuración, Apache actuará como un enrutador dinámico para *.app.servidor.net, sirviendo contenido basado en el subdominio solicitado. Utilizando mod_vhost_alias y VirtualDocumentRoot, cada subdominio apuntará a un directorio específico sin necesidad de crear un VirtualHost separado para cada uno. Este enfoque es muy flexible y te permitirá manejar múltiples subdominios de manera eficiente, ya que Apache buscará automáticamente los directorios basados en el subdominio sin necesidad de configuraciones adicionales para cada uno.

Comentarios