
🌐 También en: English · Deutsch · Français
Deep Dive de la serie en torno al Ansible Tour. Nivel: administración Linux avanzada. El tour explica los roles; los deep dives explican la técnica que hay debajo – cómo funciona, por qué está aquí, qué hace exactamente esta instalación con ella, cómo operarla en el día a día y qué otras opciones habría habido.
En esta instalación corren dos servidores Nextcloud, uno para una organización con unas 150 cuentas y casi 400 GB de ficheros, otro para un grupo pequeño. Ambos se construyen con los mismos roles (parte 4 del tour). Este artículo explica cómo está construido Nextcloud, cómo se reparten las piezas entre el host y el clúster y qué ha enseñado su operación hasta ahora.
🧭 Cómo funciona Nextcloud
Una aplicación PHP, muchas entradas
Nextcloud es PHP. Cada página del navegador, cada petición WebDAV de un cliente de sincronización y cada llamada a la API de las apps móviles es una petición PHP que pasa por nginx hasta PHP-FPM. Los ficheros están en un directorio de datos; la base de datos conoce cada fichero a través de la tabla file cache – nombre, tamaño, ETag, permisos – para que los listados nunca tengan que tocar el disco.
Bloqueos y cachés
Cuando dos clientes cambian el mismo fichero, el bloqueo transaccional de ficheros decide quién gana. Los bloqueos deben ser visibles al instante para cada proceso PHP, por eso viven en Redis. Al lado, APCu cachea por proceso y Redis entre procesos.
Tareas en segundo plano
Limpieza, caducidad de la papelera y de versiones, notificaciones, comprobación de actualizaciones de apps, generación anticipada de vistas previas – Nextcloud mantiene una cola de tareas en la base de datos. Algo tiene que ejecutar cron.php con regularidad para procesarla; Nextcloud recomienda cada cinco minutos.
Push, vistas previas, ofimática
- notify_push es un pequeño demonio en Rust que viene dentro de una app. Los clientes mantienen un WebSocket abierto con él y conocen los cambios al instante, en lugar de preguntar cada 30 segundos.
- Las vistas previas son miniaturas, generadas en la primera visualización o por adelantado con la app Preview Generator, y guardadas en la carpeta de datos de las apps.
- Nextcloud Office es la app richdocuments más un servidor Collabora Online. El navegador carga el editor desde Collabora; Collabora obtiene y guarda el documento en Nextcloud mediante el protocolo WOPI, con un token por sesión.
Apps y occ
Casi todo lo que va más allá de los ficheros es una app – calendario, contactos, Talk, carpetas de grupo. occ es la herramienta de línea de comandos para toda la administración: estado, actualizaciones, modo mantenimiento, configuración, escaneos de ficheros, reparaciones de la base de datos.
🛡️ Por qué está aquí
- Ficheros, calendarios, contactos y ofimática en un solo sitio, para personas que no deberían necesitar saber qué es WebDAV.
- Los datos se quedan en los servidores propios de la organización. Ningún proveedor decide sobre accesos, precios o funciones.
- Un ecosistema. Apps para casi cualquier necesidad, clientes para todas las plataformas, una gran comunidad.
🔧 Qué hace este repositorio
Qué corre dónde
| Componente | Dónde | Rol |
|---|---|---|
| nginx + PHP-FPM + exportador | Pod nextcloud | next_k3s_deploy |
| notify_push | Deployment propio, misma imagen | next_k3s_deploy |
| Collabora Online | Deployment propio | next_k3s_deploy |
| Tareas en segundo plano | CronJob cada 5 min | next_k3s_deploy |
| MariaDB | Host, mysqld_t | next_mariadb |
| Redis | Host, redis_t | next_redis |
| Ajustes, apps, WOPI, política de contraseñas | mediante occ | next_config |
Los componentes pesados y valiosos – base de datos y datos – están en el host, con la sandbox completa de systemd y sus propios dominios SELinux. Los reemplazables – PHP, Collabora, el demonio de push – corren en el clúster. Services de Kubernetes sin selector, que apuntan a la IP del nodo, hacen que MariaDB y Redis sean accesibles para los pods con los nombres mariadb y redis; nftables solo permite esos puertos desde la red de pods. El código PHP (/srv/nextcloud-www) y los datos (/data) son volúmenes hostPath con sus propias etiquetas SELinux.
Configuración en capas
Nextcloud lee config.php y después cada *.config.php del directorio de configuración en orden alfabético, ganando los ficheros posteriores. El repositorio lo aprovecha: custom.config.php, de un ConfigMap, lleva los ajustes (cachés, vistas previas, proxys, logs), redis.config.php, de un Secret, la contraseña de Redis. Ambos se montan con subPath, que nunca se actualiza en un pod en marcha; una suma de comprobación de todo lo montado es una anotación del pod, de modo que un cambio lo vuelve a desplegar. Esa suma cubría al principio solo los ConfigMaps – un nuevo ajuste de vistas previas estuvo un día entero en el ConfigMap mientras el pod seguía usando el fichero antiguo. Desde esta serie cubre también el Secret, después de que el deep dive de Redis mostrara que una contraseña cambiada no habría llegado al pod.
Collabora
extra_params: --o:ssl.enable=false --o:ssl.termination=true
--o:num_prealloc_children=10 --o:per_document.max_concurrency=6TLS termina en el ingress, así que Collabora corre detrás con HTTP simple y se le indica. num_prealloc_children mantiene arrancados de antemano tantos procesos de documento; abrir un documento toma uno, y si no hay ninguno listo, el usuario espera a que arranque uno nuevo. El ocasional «no se pudo cargar, reintentar funciona» justo después de reiniciar Collabora es exactamente eso. El servidor mayor mantiene diez listos, el pequeño seis. next_config fija la lista de permitidos de WOPI en la red de pods – solo Collabora puede llamar a los endpoints WOPI – y hace que Nextcloud vuelva a leer el documento de descubrimiento de Collabora tras cada cambio de este.
Un detalle de instalación costó una tarde: occ app:install richdocuments truncaba de forma reproducible un fichero de la app al extraerla, y la comprobación de integridad fallaba después. Por eso el rol descarga él mismo el tarball de la tienda de apps, lo extrae con tar y verifica las firmas de la app con occ integrity:check-app.
Dos tipos de actualizaciones
Un cambio de versión es una nueva etiqueta de imagen en versions.yml y una ejecución del playbook principal; el entrypoint del contenedor ejecuta occ upgrade al arrancar. Nextcloud se niega por sí mismo a saltarse una versión mayor, así que pasar de 32 a 34 son dos pasos. Las imágenes reconstruidas – Docker Hub reconstruye etiquetas sin cambios por correcciones de la imagen base, y K3s nunca vuelve a descargar por su cuenta – son tarea de nextcloud-update.yml. Se niega a ejecutarse sin --limit (un servidor cada vez), se niega a empezar en una instancia en modo mantenimiento o con una actualización de base de datos pendiente, reinicia solo los Deployments cuya imagen cambió de verdad, ejecuta occ upgrade como red de seguridad, actualiza las apps, reinicia una segunda vez (OPcache no comprueba fechas, ver el deep dive de PHP-FPM) y comprueba el estado. Si algo falla, un bloque rescue recoge el estado para decidir a mano. Ambos servidores corren Nextcloud 34.
Aislamiento
- Una NetworkPolicy deja que Collabora hable solo con Nextcloud y con el DNS, y que acepte conexiones solo de Nextcloud y del nodo. El pod de Nextcloud y el demonio de push aún no tienen ninguna – a diferencia del blog, donde cada pod está aislado. En un clúster que no contiene nada más no es una puerta abierta, pero falta una capa; encontrado al escribir este artículo y propuesto.
- Una política de admisión solo admite imágenes de una lista de registros permitidos – incluida la imagen del solucionador ACME de cert-manager, que corre en este namespace; en el blog, su ausencia dejó una vez una solicitud de certificado pendiente sin ningún mensaje de error.
- Ningún token de cuenta de servicio en los pods – nada en ellos habla con la API de Kubernetes.
- ClamAV escanea los ficheros en segundo plano a las 04:30, excluidas las vistas previas y los formatos multimedia – antes de ese cambio, el escaneo era la causa de un servidor que aparecía «ocupado» sin motivo visible.
📊 Medido
| Nextcloud A | Nextcloud B | |
|---|---|---|
| Versión | 34.0.5 | 34.0.5 |
| Cuentas / activas en los últimos 7 días | 152 / 27 | 26 / 1 |
| Datos | 388 GB | 16 GB |
| Entradas en el file cache | 73.061 | 7.415 |
| Apps activadas / desactivadas | 43 / 22 | 61 / 8 |
| Ejecución de tareas (cron.php) | 8–16 s cada 5 min | 6–8 s cada 5 min |
| Tarea individual más larga | 133 s (comprobación de actualizaciones) | 59 s (comprobación de actualizaciones) |
| Resumen de administración | todas las comprobaciones en verde | un error en el log, esperado (ver abajo) |
El file cache del servidor mayor tenía más de diez veces más entradas tras la migración desde el servidor antiguo: la base restaurada aún contenía todo el índice de ficheros del servidor antiguo, y occ files:cleanup no hacía nada mientras existiera la fila de almacenamiento de la ruta antigua. Una cuarta parte de lo que quedaba pertenecía a restos de una app ofimática usada antes. Ambas cosas se eliminaron – tras una copia de seguridad y tras contar las filas vivas, porque los datos de apps desactivadas se conservan por principio, por si alguien los quiere recuperar.
🧰 Operación diaria
occ() { k3s kubectl -n nextcloud exec deploy/nextcloud -c nextcloud-fpm -- \
runuser -u www-data -- php /var/www/html/occ "$@"; }
occ status
occ setupchecks # the admin overview, on the command line
occ maintenance:mode --on # before anything that touches data
occ files:scan --path="/alice/files" # after files were changed outside Nextcloud
occ db:add-missing-indices
occ background-job:list --limit=20
occ app:list --disabledAvisos esperados
- «Errores en el log» en el servidor pequeño: un error de base de datos a las 03:30 – el reinicio nocturno, durante el cual un pod de tareas no pudo resolver
mariadb. Inofensivo, pero sigue en el resumen hasta que rota el log. - «No se pudo cargar Office, reintentar funciona» justo después de un reinicio: Collabora aún no tenía ningún proceso arrancado de antemano.
- Los avisos de integridad tras un cambio manual en el directorio de apps son reales: Nextcloud firma su código, y cualquier fichero editado salta a la vista. Nunca editar el código de una app en su sitio.
Copias de seguridad y restauración
Cada noche una máquina de copias recoge por SSH el volcado de la base de datos, config.php y el directorio de datos, y los versiona durante 365 días. Restaurar es el camino inverso más occ maintenance:data-fingerprint, que indica a los clientes de sincronización que el estado del servidor cambió, para que no borren lo que creen nuevo.
🆘 Chuleta: síntoma → comando
La versión corta de este artículo para el momento en que algo va mal. Ejecutar en el host como root; <…> son marcadores. occ y wp son las funciones de shell de los deep dives de Nextcloud y WordPress.
| Síntoma | Comando |
|---|---|
| Primer vistazo | occ status |
| Atascado en modo mantenimiento | occ maintenance:mode --off |
| Faltan ficheros cambiados fuera de Nextcloud | occ files:scan --path="/<user>/files" |
| Código viejo tras actualizar una app | k3s kubectl -n nextcloud rollout restart deployment/nextcloud |
| Las tareas en segundo plano van con retraso | occ background-job:list --limit=20 |
| Los documentos de Office no se abren | k3s kubectl -n nextcloud logs deploy/collabora --tail=50 |
| Los clientes no sincronizan al instante | occ notify_push:self-test |
| Las miniaturas llenan el disco | occ preview:cleanup # never rm: previews live in the database |
| Avisos tras una actualización | occ db:add-missing-indices |
| Tras restaurar una copia | occ maintenance:data-fingerprint |
🔭 Lo que viene
- Nextcloud 35, cuando salga la primera versión de corrección, primero en el servidor pequeño.
- S3 como almacenamiento principal haría los datos independientes del disco del host – relevante solo con más de un nodo.
- El backend de alto rendimiento de Talk, si las videollamadas llegan a ser algo más que ocasionales.
⚖️ Alternativas – y por qué Nextcloud
| Opción | Punto fuerte | Por qué no aquí |
|---|---|---|
| Seafile | Sincronización mucho más rápida, almacenamiento por bloques | Menos funciones de groupware, los datos no se guardan como ficheros normales. |
| ownCloud Infinite Scale | Go, sin PHP ni base de datos | Otra arquitectura, ecosistema de apps más pequeño, supondría migrarlo todo. |
| Una nube propietaria | Nada que operar | Datos y acceso decididos por un proveedor – lo contrario del objetivo. |
| Nextcloud | Funciones, apps, clientes, comunidad, los datos existentes | Elegido. |
Nextcloud no es difícil de instalar; es exigente de operar bien, porque son una docena de servicios que fingen ser uno solo. Repartirlos según «valioso o reemplazable» – base de datos y ficheros en el host, PHP y ofimática en el clúster – hizo cada parte más fácil de entender. Los errores de este artículo estaban casi todos en las costuras entre ellas.


