Como ya he contado otras veces, tengo montado un tinglado creo que bastante estándar: un montón de contenedores Docker con todo tipo de servicios, con un servidor web por delante haciendo de proxy inverso, dirigiendo el tráfico hacia donde corresponda, en función de por qué URL hayan entrado. En mi caso, usaba Apache.
Pero conforme pasa el tiempo y cada vez tienes más cosas, este servidor web frontal se va complicando notablemente. Porque no es sólo redirigir el tráfico, hay casos concretos que tienen particularidades que hay que resolver (malditos websockets). Y también hay que añadir autenticación para no tenerlo todo expuesto, y por supuesto hoy en día o sales con HTTPS, o te arriesgas a que cualquier día tu web la tengan unos hackers turcos para usos poco edificantes.
Y no sé si es que Apache muestra ya su edad, o simplemente es potentísimo y te permite hacer cualquier cosa, pero el caso es que me encuentro haciendo un montón de cosas «a pelo», cuando tengo la sensación de que podrían ser un poco más automáticas. Tampoco ayuda que yo no soy un experto mundial en Apache, digamos que sé hacer lo básico y poco más, con lo que al final me paso el día googleando cómo hacer tal o cual cosa, y copiando y pegando directivas de StackOverflow o similar, llegando un punto en el que ni sé lo que estoy haciendo. Por no hablar de la de veces que acabo desistiendo, y por mucho que dirija y redirija, no hay manera de que el dichoso ProxyPass funcione como toca.
A esto se une que, cuando googleas sobre estos temas, te surgen otros nombres. NGINX, HAProxy, Traefik, Caddy… Vamos, que era hora de analizar si realmente no hay una forma mejor de hacer las cosas. NGINX lo medio conozco y me parece parecido a Apache en cuanto a potencia y gestión (con el rollo de tener que reaprender todo). HAProxy francamente lo descarté porque su página web parece hecha en el año 1997. Eso me dejó dos posibilidades:
- Traefik: Muy buena pinta. Básicamente es implementar toda la configuración del servidor web como anotaciones en los contenedores Docker. Vamos, que no hay (apenas) configuración en sí. Simplemente, si quiero que tal contenedor esté expuesto al exterior, le añado unas anotaciones en el fichero de configuración de docker-compose, diciendo bajo qué dominio, etc., y toda la configuración se hace de forma transparente.
- Caddy: Un servidor web más clásico, en el sentido de que sí es un programa externo, y sí tiene ficheros de configuración. Pero al mismo tiempo está pensado para ser muy simple, y gestionar automáticamente y por defecto cosas que en otro servidores web habría que hacer de forma explícita.
El que me atraía más era Traefik, porque eso de quitar de en medio toda la configuración y convertirla en simples anotaciones me parecía ideal. Ahora podría hacer un razonamiento muy sesudo de por qué finalmente lo descarté, pero el motivo fue muy sencillo: no fui capaz de hacerlo funcionar. Al principio es muy sencillo, pero conforme van apareciendo particularidades (por ejemplo Home Assistant que funciona en modo host), iba añadiendo más y más cositas por aquí y por allá, y para cuando me di cuenta tenía una configuración casi más compleja que la que tenía con Apache, y encima con cosas que todavía no funcionaban. Vamos, que tiré la toalla. No quiero decir que Traefik no esté bien, muy probablemente el problema esté en el hardware que hay entre la silla y pantalla (o sea, yo).
Vamos, que al final me decidí por Caddy. De entrada no muy motivado, porque el planteamiento de Traefik como que mola mucho, y Caddy parece más «clásico», pero la verdad es que se me pasó rápido. Es ponerse a hacer las cosas con Caddy, y la sensación es «¿Ya? ¿De verdad no hay que hacer nada más?». Es alucinante cómo en dos patadas tienes definido un tinglado que en Apache tiene telita. Como ejemplo un botón. Un servicio clásico en Apache sería una cosa así:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName hass.midominio.com
# Permitir acceso sin autenticación a manifest.json para poder añadir a pantalla de inicio en Android
<Location /manifest.json>
Order deny,allow
Allow from all
Satisfy any
</Location>
<Location /static/icons>
Order deny,allow
Allow from all
Satisfy any
</Location>
<Location />
AuthType Basic
AuthName "Cosas sensibles"
AuthBasicProvider file
AuthUserFile /etc/apache2/passwords
Require user miusuario
</Location>
ProxyPreserveHost On
ProxyRequests off
ProxyPass /api/websocket ws://localhost:8123/api/websocket disablereuse=on
ProxyPassReverse /api/websocket ws://localhost:8123/api/websocket
ProxyPass / http://localhost:8123/ disablereuse=on
ProxyPassReverse / http://localhost:8123/
ProxyPass /static/translations/ http://localhost:8123/static/translations/
ProxyPassReverse /static/translations/ http://localhost:8123/static/translations/
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:8123/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://localhost:8123/$1 [P,L]
LogLevel info
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/backup.fkes.bid-0002/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/backup.fkes.bid-0002/privkey.pem
</VirtualHost>
</IfModule>
Lo que viene a ser una cosa normal para servir un Home Assistant: le dices bajo qué dominio lo servirás, pones los Proxypass hacia la máquina/puerto que toque, ajustas los permisos sobre qué usuario hará falta para entrar, y luego toda una serie de magia negra para que el ProxyPass vaya bien en los diferentes casos (accesos normales, websockets, excepciones…). Finalmente la información sobre los certificados que tiene que usar para HTTPS. Y no he puesto otras cosas que van en otros ficheros, como la redirección de HTTP a HTTPS, o toda la gestión de pedir y renovar los certificados.
Lo mismo, pero con Caddy, queda así:
hass.midominio.com {
reverse_proxy localhost:8123
basicauth {
miusuario JDJhaDs0fd5Ef3d5saNsddUfaksdf0J23mUsdEfyMw543TsjdfUsdaRfL2sdLfZasXd4f3sdfUasdWf1
}
}
Y ya está, no hay más. Todas las pirulas para que el tráfico fluya no hay que hacerlas, la autenticación es una línea, y sobre certificados HTTPS no hay que hacer nada, porque el mismo Caddy gestiona este tema internamente de forma automática (si no le dices nada, sirve por HTTPS, gestionando él mismo la emisión y renovación de certificados con LetsEncrypt, añadiendo además la redirección automática de HTTP a HTTPS).
Vamos, que me he quedado a cuadros. En 5 minutos literales había migrado toda mi configuración de una veintena de ficheros de Apache a un único ficherín Caddy de menos de 100 líneas, con todo funcionando perfectamente (incluso cosas que con Apache fui incapaz de hacer andar). La sensación era que era todo demasiado bonito para ser verdad, y que algo fallaría y me obligaría a volver a Apache mientras buceo en foros a ver cómo arreglarlo, pero de momento todo funciona perfectamente, y encima mejor: por ejemplo, la pantalla para servir ficheros estáticos de Caddy le pega mil vueltas a la de Apache (es más bonita, incluye un filtro de búsqueda integrado…).
En definitiva, que igual un experto en Apache se lo pasa mejor teniendo el control total sobre todos los aspectos de la comunicación, pero en mi caso Caddy me ha solucionado muchísimo la vida. Está claro que vale la pena hacer un poco de prospección, cada 5-10 años o así, para ver cómo va evolucionando la tecnología, que a veces por inercia de usar lo de siempre, nos acabamos complicando la vida.