De Apache a Caddy

Estándar

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.

Visualizando el consumo energético de casa con Grafana

Estándar

Bueno, en la entrada anterior contaba lo súper fantabuloso que es el Shelly EM como medidor de consumo energético, lo abierto que es y lo fácil que es integrarlo con casi cualquier cosa. Pues ahora falta ver la otra parte: cómo podemos coger los datos de consumo, y visualizarlos de forma bonita y vistosa.

Veamos, esta va a ser una entrada densa, porque hay que introducir muchos conceptos y hay muchas piezas interconectadas. Aunque pueda parecer todo muy complejo, en el fondo no es tan difícil, y la gracia es que, una vez montado el tinglado inicial, luego ir añadiendo cosas es trivial.

Pero al lío. Para poder llegar a ver gráficas chulas, hay que pasar por todas las fases:

  1. Tener un medidor de consumo que nos dé los datos en un formato abierto y procesable: Chachi, eso ya lo tenemos, partiré de que tenemos un Shelly EM publicando los datos por HTTP o MQTT. Obviamente, cualquier otro medidor que proporcione los datos por una vía equivalente es igual de válido.
  2. Ahora hay que recibir los datos de alguna manera. Lo más chulo y versátil para estas cosas domóticas es usar Node-RED (luego más).
  3. Los datos hay que almacenarlos en alguna parte. Podríamos usar cualquier base de datos en plan MySQL, ficheros de texto o lo que sea, pero teniendo en cuenta que este tipo de datos crecen una barbaridad, lo más apropiado es usar una base de datos específica para guardar series temporales, como InfluxDB.
  4. Y ahora que ya tenemos los datos guardaditos, ya podemos hacer gráficas, en este caso con Grafana.

Madre del amor hermoso, menuda movida para ver cuatro gráficas. ¿De verdad vale la pena? ¿No sería más feliz viendo las gráficas en el típico cacharrín propietario mientras dure su app? Afortunadamente, instalar todo esto es 1.000 veces más fácil que si lo hiciéramos a pelo, gracias a…

Docker

¿Ein? ¿No hablábamos de medir energía, de domótica y de instalar programas? Pues ahí andamos, porque resulta que Docker es una forma de instalar en dos patadas programas que serían tremendamente complicados de instalar si se hiciera a pelo.

El concepto de los contenedores Docker reconozco que es espinoso. Para el que esté familiarizado con el concepto de máquina virtual, se podría decir que un contenedor Docker es una especie de máquina virtual, pero «aligerada». Porque si una máquina virtual viene a ser un «miniordenador», con un sistema operativo entero y las aplicaciones que hagan falta, un contenedor Docker vendría a ser el resultado de «podar» esta máquina virtual y dejarla estrictamente con lo que necesita para ejecutar una aplicación concreta. Por eso con las máquinas virtuales hablamos de sistemas operativos (una máquina virtual con Ubuntu, o con Windows) pero con contenedores hablamos de aplicaciones (un contenedor con MySQL, o con Transmission).

La gracia extra de los contenedores es que, a diferencia de las máquinas virtuales, para las que se reserva una porción de memoria y unas cuantas CPUs, los contenedores se ejecutan todos sobre la misma máquina, compartiendo kernel, memoria y recursos. La argucia técnica que permite hacer eso aislando al mismo tiempo unos contenedores de otros lo dejo para otro día, pero el caso es que esta diferencia hace que arrancar o parar contenedores sea rapidísimo, comparado con una máquina virtual.

Otra ventaja de los contenedores es que tenemos dos cosas:

  • Un repositorio en internet (Docker Hub) de contenedores ya hechos, para casi cualquier aplicación que se nos ocurra.
  • Herramientas para orquestar el arranque de varios contenedores enchufados entre ellos, simplemente escribiendo un ficherito de texto.

O sea, que al final es raro que hagamos contenedores a pelo. Más bien cogeremos contenedores ya hechos, con los programas que nos interesen, y los configuraremos e interconectaremos para conseguir lo que queramos.

Como esto es muy teórico, se ve mucho mejor con un ejemplo. Pongamos que quiero montarme un blog con WordPress. Tradicionalmente, empezaríamos a instalar todos los requisitos: que si un Apache, que si el soporte de PHP, una base de datos MySQL… Y luego ponte a configurar todo.

Usando contenedores, bastaría crear un ficherito llamado docker-compose.yaml, tal que asín:

version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress
   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
volumes:
    db_data: {}

Con esto le estoy diciendo que quiero dos contenedores, uno con una BD MySQL, y otro con un WordPress. Y luego para cada uno configuro cuatro cosas: que si usuarios/passwords de la BD, que si en qué puerto servirá… El caso es que, una vez tengo esto, basta ejecutar:

docker-compose up

Y él solo ya se encargaría de bajarse los contenedores que le he indicado (wordpress y MySQL), configurarlos según mis instrucciones y ejecutarlos, con lo que ya puedo abrir el navegador, apuntar al puerto que corresponda, y ya tengo mi WordPress en marcha.

Chachi, ¿no? Pues después de la introducción, vamos a utilizar esto mismo para montarnos en dos patadas nuestro tinglado domótico.

Primer paso: Node-RED

Node-RED es… una cosa difícil de describir. Se podría decir que es una plataforma para interconectar diferentes sistemas de forma visual, a base de unir cajitas con líneas. Es una descripción poco científica, pero de verdad que es más fácil verlo y probarlo que intentar describirlo con palabras.

En nuestro caso, lo vamos a usar para coger lo que nos envíe el medidor de consumo, y enviarlo a nuestra base de datos.

Como hemos dicho, vamos a montarlo todo con Docker. Nos vamos a cualquier directorio, y editamos el fichero docker-compose.yaml, con el siguiente contenido:

version: "3.3"
services:
  nodered:
    image: nodered/node-red
    container_name: nodered
    restart: unless-stopped
    user: "1000"
    volumes:
      - $PWD/data:/data
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/TZ:ro
    environment:
      - TZ=Europe/Madrid
    ports:
      - 1880:1880

Con esto le estamos diciendo que queremos un Node-RED en el puerto 1880, que queremos que guarde los datos en el subdirectorio data, y luego le hemos añadido un par de cosas para que tenga bien los permisos de los ficheros, coja bien la hora y esté siempre arrancado aunque reiniciemos el servidor.

Y ya está. Ejecutamos «docker-compose up», y ya deberíamos tener Node-RED en marcha.

Como la idea de Node-RED es enganchar el medidor con la base de datos, vamos a instalar esta última antes de configurar nada.

InfluxDB

InfluxDB es una base de datos como tantas, pero con una particularidad: está optimizada para guardar series temporales. ¿Qué quiere decir eso? Pues que si una base de datos normal guarda todos los datos en un registro de tamaño fijo, y tenemos muchos datos, eso va a ocupar un montón con el tiempo. Lo que hace InfluxDB es guardar las diferencias entre un dato y otro, de una forma muy compacta, de manera que lo que en otra base de datos ocuparía GB, aquí ocupa MB. Ideal para nuestro caso de guardar consumos eléctricos ad-infinitum.

Para instalarlo, volvemos a abrir el docker-compose.yaml, y añadimos un servicio nuevo, para InfluxDB:

version: "3.3"
services:
  nodered:
    image: nodered/node-red
    container_name: nodered
    restart: unless-stopped
    user: "1000"
    volumes:
      - $PWD/data:/data
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/TZ:ro
    environment:
      - TZ=Europe/Madrid
    ports:
      - 1880:1880
  influxdb:
    image: influxdb:latest
    container_name: influxdb
    environment:
      - TZ=Europe/Madrid
      - INFLUXDB_DB=energia
      - INFLUXDB_ADMIN_USER=influxdb
      - INFLUXDB_ADMIN_PASSWORD=influxdb
      - INFLUXDB_WRITE_USER=influxdb_w
      - INFLUXDB_WRITE_PASSWORD=influxdb_w
      - INFLUXDB_HTTP_FLUX_ENABLED=true
    ports:
      - 8086:8086
      - 8083:8083
      - 2003:2003
    volumes:
      - $PWD/influxdb:/var/lib/influxdb
    restart: unless-stopped

Y ya está. Sólo le hemos indicado el nombre de la base de datos («energia») y hemos indicado que cree dos cuentas de usuario: una para administrar, y otra sólo con permisos de escritura, que será la que usemos para cargar los consumos.

Si volvemos a ejecutar docker-compose, veremos cómo se descarga y arranca la BD.

Enviar consumos a InfluxDB con Node-RED

Ahora que ya tenemos la BD en marcha, vamos a usar Node-RED para leer los consumos del medidor, y enviarlos a InfluxDB. Para esto abrimos Node-RED, y tenemos que añadir dos nodos al tablero: uno para leer del medidor, y otro para escribir en InfluxDB. Los unimos con una flechita, y listos:

Hay que clicar en cada uno de los nodos, y configurar ahí lo que haga falta.

En el caso del medidor, yo leo los valores por MQTT, por lo que habría que indicar a qué «topic» escribe el medidor. Si se quisiera hacer por HTTP, habría que usar otro tipo de nodo, e indicar la URL y la frecuencia de lectura. Es un poco más complicado, sería algo así:

En vez de esperar a que llegue el valor, al leerlo por una web hay que leer periódicament (nodo timestamp, configurado para leer cada 10 segundos o así), luego hacer la petición (nodo http request) y luego, de entre todo lo que nos llega, sacar el consumo en W (nodo tipo Change, cogiendo el valor «power»).

En el caso del nodo de influxdb, hay que indicar el host y el puerto en los que tenemos la base de datos (son los valores que hemos indicado en docker-compose.yaml), así como el usuario y contraseña definidos antes.

Con esto ya tenemos los consumos eléctricos guardados en nuestra base de datos. Ahora sólo queda hacer gráficas.

Grafana

Grafana es una aplicación web para hacer gráficas chulas en tiempo real. Permite recuperar los datos de un montón de fuentes diferentes, entre ellas InfluxDB. Para añadir una instancia de Grafana a nuestro Docker, simplemente habría que añadir un servicio más a nuestro docker-compose.yaml:

version: "3.3"
services:
  nodered:
    image: nodered/node-red
    container_name: nodered
    restart: unless-stopped
    user: "1000"
    volumes:
      - $PWD/data:/data
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/TZ:ro
    environment:
      - TZ=Europe/Madrid
    ports:
      - 1880:1880
  influxdb:
    image: influxdb:latest
    container_name: influxdb
    environment:
      - TZ=Europe/Madrid
      - INFLUXDB_DB=energia
      - INFLUXDB_ADMIN_USER=influxdb
      - INFLUXDB_ADMIN_PASSWORD=influxdb
      - INFLUXDB_WRITE_USER=influxdb_w
      - INFLUXDB_WRITE_PASSWORD=influxdb_w
      - INFLUXDB_HTTP_FLUX_ENABLED=true
    ports:
      - 8086:8086
      - 8083:8083
      - 2003:2003
    volumes:
      - $PWD/influxdb:/var/lib/influxdb
    restart: unless-stopped
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    depends_on:
      - influxdb
    environment:
      - TZ=Europe/Madrid
      - GF_SERVER_ROOT_URL=https://midominio/grafana
      - GF_SERVER_SERVE_FROM_SUB_PATH=true
      - GF_SECURITY_ADMIN_USER=miusuario
      - GF_SECURITY_ADMIN_PASSWORD=passadmin
      - GF_ENABLE_ALPHA=true
      - GF_INSTALL_PLUGINS=grafana-influxdb-flux-datasource,grafana-piechart-panel
    volumes:
      - $PWD/grafana-storage:/var/lib/grafana
    ports:
      - 3000:3000
    restart: unless-stopped

Que viene a ser más de lo mismo que ya hemos visto: cuatro configuraciones sobre usuarios y compañía, puertos y directorio donde ser guardarán los datos. Aquí hay un par de cosas adicionales que no son imprescindibles: unos cuantos plugins extras que no vienen de serie, y un par de configuraciones en las que le indico un dominio, para poder acceder a la instancia de Grafana desde fuera de mi red local. Pero vamos, que no hacen falta.

Con esto arrancamos Grafana, y ya podríamos configurar un datasource de tipo InfluxDB e ir añadiendo gráficas con lo que nos apetezca. En esto no voy a entrar porque esta entrada ya queda demasiado larga, hay guías a patadas sobre cómo usar Grafana, cada cuál tiene sus gustos y en el fondo el interfaz es muy intuitivo y amigable. Sólo pongo un pantallazo de cómo queda mi configuración de monitorización de energía:

Mi dashboard en Grafana

Chulo, ¿verdad? Y actualizado en tiempo real y totalmente interactivo para cambiar el intervalo de tiempo a analizar, hacer zoom o quitar o poner medidas. Bueno, en mi caso es un poco trampa, porque no tengo un solo Shelly EM, sino dos, midiendo cuatro circuitos, más un Shelly 1PM para medir las luces, más dos Shelly Plug S para medir los calefactores del baño, más un TP-Link HS-110 (este no es tan abierto como los Shellys, pero se puede usar con Node-RED Home Assistant mediante) para medir el termo… Si es que esto de ponerse a monitorizar es empezar, y no querer parar 🙂

En definitiva, que en dos patadas y gracias a Docker nos hemos montado un tinglado considerable, muy fácil de instalar y mantener. ¿Que mañana cambiamos el servidor? Pues cogemos el docker-compose.yaml, lo copiamos al nuevo, y con un docker-compose up lo tenemos todo de nuevo en marcha en segundos. Así da gusto instalar cosas.

De Dropbox a Nextcloud, almacenamiento en la nube sin salir de casa

Estándar

Llevo bastantes años usando Dropbox, y francamente estoy contento: a base de múltiples triquiñuelas tenía un espacio considerable, la web es amigable y usable, y las herramientas son más que correctas. Hasta había cliente para Linux, que no es algo habitual. Pero hace unas semanas los señores de Dropbox hicieron un cambio en las condiciones que, aunque aparentemente es pequeño, nos fastidia la vida a muchos: a partir de ahora, sólo se podrá vincular un máximo de tres dispositivos. Eso parece suficiente y razonable, pero luego empiezas a contar y no salen los números: móvil, más ordenador de casa, más ordenador del trabajo… ya sale justo. Como tengas más de un ordenador en casa, un portátil o una tablet, ya no llega. Además es un cambio sutil, porque como Dropbox no desconecta nada «a las bravas», ni te enteras. Yo me he dado cuenta cuando he formateado el móvil de fábrica porque se me arrastraba un poco, y al ir a instalar Dropbox me ha dicho que tururú, que tengo que desvincular unos cuantos dispositivos primero o nanay de la China.

¿Qué hacer ahora? Bueno, la solución obvia (y hacia donde barre la compañía) es contratar un plan de pago. Que la verdad no es descabellado, y en el pasado me había tentado: 9 euritos al mes, y tienes nada menos que 1 TB. Es un precio razonable, lo que pasa es que no necesito tanto espacio (ahora mismo vivo muy bien con mis 20 y pico GB) y, lo peor, en casa somos varios que usamos Dropbox. Como no hay ningún plan familiar, eso quiere decir 9 eur/mes para cada uno, lo cual lo hace ya inasumible. Así las cosas, y antes de pasar por caja, me vino a la cabeza montarme el tinglado por mi cuenta, y de eso va esta entrada.

La primera opción que me sonaba de un «Dropbox libre que me pueda instalar en mi casa» era Owncloud. Ahora bien, resulta que en Owncloud hubo hace unos años un «cisma» similar al de LibreOffice/OpenOffice, por lo que ahora mismo tenemos Owncloud… y Nextcloud. Aunque la cosa es como un culebrón venezolano, y a día de hoy sigo sin tener claro cuál «tiene razón», resumiendo mucho el tema parece que la cosa fue así:

  • Nextcloud lo montaron los desarrolladores originales de Owncloud, que se largaron casi en masa, por tanto sería el más fiel al espíritu original, y los que controlan más el cotarro. Claro que según a quién le preguntes te dirán que sí, que fueron los originales pero se acabaron largando a otros sitios también.
  • Parece ser que el código de Nextcloud tiene más vidilla que el de Owncloud. Que luego los de Owncloud dicen que es que ellos acumulan más cambios en menos commits, y que realmente avanzan igual. A saber.
  • Nextcloud me parece un poco más libre y menos «turbio» que Owncloud. En este último veo como mucha tendencia a pedirte la VISA: la app de Android es de pago, hay características que sólo están disponibles en la versión de pago… En cambio en Nextcloud es todo libre y completo de principio a fin, y si quieres pagas el soporte. Me parece mucho más limpio y claro.
  • El logo de Nextcloud me gusta más, y la web me parece más clara e inteligible. No es un argumentazo, pero todo suma 🙂

Vamos, que me he decidido por Nextcloud, que me parece el «LibreOffice» de este caso. Pero vamos, que tampoco hay una gran diferencia entre los dos, por lo que el proceso para ponerse Owncloud me da a mí que sería prácticamente el mismo.

Una vez decidido qué vamos a instalar, hay que hacer la lista de la compra: necesitamos Nextcloud, una base de datos para que Nextcloud guarde sus cosillas, un servidor web (Nextcloud está hecho en PHP, supongo que nada es perfecto 🙂 )… Podría instalarlo todo a pelo, o tirar de contenedores Docker, y tenerlo todo en dos patadas. Un día de estos escribiré una entrada de cómo Docker es lo mejor que se ha inventado desde el pan de molde, pero de momento basta saber que permite tener montado en un plis plas un tinglado con varias aplicaciones interenchufadas entre ellas, con apenas cuatro líneas de texto y de una manera similar a las máquinas virtuales, pero sin serlo y por tanto gastando muchos menos recursos. Yo lo he montado usando docker-compose, que permite configurar los contenedores que necesitemos y sus dependencias usando un ficherito de texto, y la cosa es tan sencilla como esto:

version: "3.3"
  services:
    db:
      image: mysql:5.7
      container_name: mysql
      volumes:
        - db_data:/var/lib/mysql
      restart: unless-stopped
      environment:
        - MYSQL_ROOT_PASSWORD=contraseñaroot
    nextcloud:
      image: nextcloud
      container_name: nextcloud
      depends_on:
        - db
      restart: unless-stopped
      volumes:
        - nextcloud:/var/www/html
        - /misficheros/nextcloud:/usr/local/data:rw
      environment:
        - MYSQL_HOST=db
        - MYSQL_USER=root
        - MYSQL_PASSWORD=contraseñaroot
        - MYSQL_DATABASE=nextcloud
        - NEXTCLOUD_TRUSTED_DOMAINS="midominio.com 127.0.0.1 localhost"
        - NEXTCLOUD_DATA_DIR=/usr/local/data
      ports:
        - 8080:80
  volumes:
    nextcloud:
    db_data: {}

El fichero prácticamente se explica sólo, pero básicamente defino dos contenedores:

  • Una base de datos MySQL, configurando la contraseña de administrador
  • El Nextcloud en sí, añadiendo variables para decirle que use el MySQL anterior, cómo conectarse a él, y un par de cosillas más
    • NEXTCLOUD_DATA_DIR: Dónde van a estar los datos de Nextcloud (los ficheros, vamos), en este caso /usr/local/data. Pero ojo, porque esta es una ruta interna del contenedor, que en realidad será un «alias» a la ruta real, que he definido en volumes, y que será el directorio de mi servidor donde quiero que se guarden los datos
    • NEXTCLOUD_TRUSTED_DOMAINS: Aquí le digo desde qué direcciones admitiré conexiones. Por defecto la cosa es muy estricta, y por seguridad sólo se admiten conexiones desde la propia máquina. Con esto puedo añadir las IPs de las máquinas que accederán, un dominio si voy a dar acceso externo, o lo que sea

Y con esto ya basta con ejecutar docker-compose up, y veremos cómo los contenedores se descargan, construyen, configuran y arrancan. Una vez arrancado, podemos ir con el navegador a la URL de la máquina en la que se ejecute docker, al puerto 8080, y entraremos a la pantalla inicial de Nextcloud. Como ya le hemos indicado la mayoría de cosas que necesita (base de datos, dónde guardar los ficheros), sólo hará falta crearse un usuario, y ya estará listo para funcionar.

Con esto tan simple ya tenemos Nextcloud en marcha y funcionando, pero sólo desde nuestra red local. Como la gracia es poder acceder desde cualquier sitio, o desde el móvil, hay que abrir el tema al exterior. Aquí hay mil formas de hacerlo, lo que he hecho yo es algo muy típico:

  • Me compro un dominio nextcloud.midominio.com, que apunte a mi router (por ejemplo gestionándolo con FreeDNS).
  • Configuro en el router todas las conexiones HTTP (puerto 80) y HTTPS (puerto 443) hacia mi servidor.
  • En el servidor tengo un Apache, que hace que todas las conexiones que vengan desde nextcloud.midominio.com se redireccionen hacia el puerto 8080 del servidor (que es donde escucha Nextcloud)

Para conseguir esto, tengo el siguiente site de Apache:

<IfModule mod_ssl.c>
  <VirtualHost *:443>
    ServerName nextcloud.midominio.com

    <IfModule mod_headers.c>
        Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
    </IfModule>

    ProxyPreserveHost on
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    # Fix the HTTP Authorization header so the Android app can login (https://github.com/nextcloud/server/issues/8956)
    RewriteEngine On
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
    RewriteRule ^/\.well-known/carddav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
    RewriteRule ^/\.well-known/caldav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]

    LogLevel info

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Certificados de Let's Encrypt
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/backup.midominio.com-0005/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/backup.midominio.com-0005/privkey.pem
  </VirtualHost>
</IfModule>

Es la configuración básica para hacer de proxy inverso con Apache, con algún añadido para arreglar cosillas de Nextcloud que he ido encontrando en foros (las Rewriterules o las cabeceras añadidas). También está el tema de los certificados para usar HTTPS, pero eso ya es otro tema que no viene al caso aquí (y del que por cierto hablé hace un tiempo).

Y con esto más o menos ya está. Queda pulir algunos detalles que tengo que resolver (por ejemplo hay aspectos de la configuración de Nextcloud que no se pueden parametrizar en el fichero de configuración de docker-compose y habrá que hacerlo de alguna manera), pero ya iré actualizando el post según los vaya resolviendo.

De momento la verdad es que la impresión es muy buena. Me esperaba algo bastante chusquero y pedestre (por eso de ser libre y tal) pero estoy gratamente sorprendido por lo bonito, suave y agradable que es todo. De hecho toda la interfaz y funcionamiento es muy, muy parecida a la de Dropbox, y funciona igual o mejor (por ejemplo la compartición de archivos por enlace es mucho más transparente, en Dropbox te obliga a tragarte un diálogo de confirmación). Las aplicaciones tanto de escritorio como de móvil también funcionan de lujo, y estoy francamente contento. Que es fácil que acabe volviendo a Dropbox cuando se bajen del burro y ofrezcan un plan familiar decente, o al menos más granular que el actual (300 GB por 3 eur/mes, por ejemplo, sería fabuloso). Pero la verdad es que Nextcloud me lo está poniendo complicado, porque es verdaderamente agradable de usar, y encima con Docker muy sencillo de gestionar.