Día 1 — OpenCloud, proxy y web del proyecto
OpenCloud en Docker Compose, Nginx con TLS en loopback, Fail2ban, subdominio cloud y la landing Astro KM0 publicada como segundo backend.
Introducción
El día 1 convierte la base Debian en una plataforma completa: OpenCloud sobre Docker Compose con overlays oficiales, Nginx terminando TLS y encaminando solo al loopback, políticas de firewall coherentes y la landing Astro del proyecto publicada como segundo backend detrás del mismo frontal.
También se introducen mejoras posteriores al primer corte — Fail2ban y el subdominio dedicado del cloud — porque forman parte del relato operativo real del despliegue.
OpenCloud
Core sin Collabora/WOPI
El modo elegido arranca OpenCloud como servicio único desde la composición oficial (opencloud-eu/opencloud-compose), usando una imagen rodante etiquetada (opencloud-rolling con tag fijado en despliegue) para poder actualizar de forma deliberada (docker compose pull + ventana de mantenimiento).
- Overlay external-proxy: adapta variables como
PROXY_HTTP_ADDRpara escuchar dentro del contenedor y publicar el puerto HTTP del proxy solo como127.0.0.1:<puerto>en el host. - COMPOSE_PROJECT_NAME=opencloud: ancla los nombres de volumen Docker sin depender del cwd.
- Fichero .env: fuente única de variables de despliegue; permisos estrictos en disco y fuera del control de versiones.
- COMPOSE_FILE: lista los overlays necesarios (base más overlay de proxy externo).
Dentro del contenedor coexisten microservicios que conversan por gRPC/HTTP en localhost interno; ese rango no se expone directamente al host salvo por los endpoints previstos por el chart upstream.
Arquitectura
OpenCloud tras el proxy
Browser │ HTTPS :443 ▼ Nginx (Debian, site dedicado OpenCloud) │ HTTP http://127.0.0.1:9200 (solo loopback) ▼ Contenedor OpenCloud (UID/GID fijo) │ microservicios internos ~9140–9300 ▼ Volúmenes Docker: • opencloud-data → ficheros, índices, NATS, IDM... • opencloud-config → opencloud.yaml, CSP, políticas...
PROXY_TLS=false indica que la terminación TLS ocurre fuera del contenedor (en Nginx). OpenCloud genera URLs coherentes cuando recibe cabeceras X-Forwarded-* correctas.
Puertos
Mapa de superficie expuesta
- 22 (sshd): administración SSH — Internet según política.
- 80/443 (Nginx): HTTP/S público — redirección ACME y virtual hosts KM0 + OpenCloud.
- 9200 (Docker → OpenCloud): solo
127.0.0.1— backend HTTP que ve Nginx. - 9140–9300: microservicios internos del contenedor — no publicados en el host.
Nginx
Directivas clave hacia OpenCloud
- proxy_buffering off: SSE para actualizaciones en tiempo real del cliente web.
- proxy_request_buffering off: subidas resumibles TUS sin bufferizar todo el cuerpo.
- proxy_pass http://127.0.0.1:9200: TLS ya resuelto en el borde.
- X-Forwarded-Proto $scheme: redirects y cookies coherentes para HTTPS.
- Upgrade/Connection passthrough: WebSockets para el UI interactivo.
- Timeouts 3600s y client_max_body_size 10G: sesiones largas y ficheros grandes.
Despliegue
Árbol en /opt/opencloud
/opt/opencloud/ ├── opencloud-compose/ # clon upstream + overlays │ ├── docker-compose.yml │ ├── external-proxy/opencloud.yml │ └── .env # activo — fuera de git, chmod 600 ├── nginx/ # plantillas TLS + proxy ├── scripts/backup-volumes.sh └── docs/runbook.md
Los snippets en repo sirven como referencia; los ficheros activos bajo /etc/nginx/sites-available/ deben revisarse siempre con nginx -t antes de systemctl reload nginx.
Datos
Volúmenes Docker y persistencia
OpenCloud centraliza persistencia en dos volúmenes nombrados. El contenido relevante incluye:
- idm/ e idp/: directorio LDAP interno y estado del proveedor OIDC.
- nats/: bus de eventos JetStream entre microservicios.
- search/: índice full-text (Bleve).
- storage/: metadatos CS3 y nodos del driver decomposed.
- web/: activos estáticos del frontal integrado.
Cifrado en reposo: blobs ordinarios dentro del volumen; opciones de endurecimiento incluyen LUKS, SSE en backend objeto o cifrado E2E en clientes. Cifrado en tránsito: TLS cliente↔Nginx.
Web KM0
Flujo HTTPS del sitio corporativo
Internet :443 ─► Nginx host (TLS, km0digital.com)
└──► http://127.0.0.1:9180 (km0-web — solo loopback)
Astro estático + nginx Alpine- Stack: Astro 5 + Tailwind 3, salida estática.
- i18n: JSON en
src/i18n/+ rutas/ca/,/en/,/de/; español por defecto en raíz. - Build: Node 22 Alpine multi-stage; repo en
/opt/km0-web. - SEO:
@astrojs/sitemapcon alternativas hreflang.
Perímetro
Fail2ban y subdominio del cloud
Tras el primer corte estable se añadió Fail2ban como red complementaria al firewall. El cloud quedó publicado en cloud.km0digital.com, separado de la marca de marketing en km0digital.com:
- Certificados y políticas CSP pueden divergir.
- Los usuarios entienden qué URL usar para trabajo vs comunicación.
- Los equipos pueden delegar DNS/TLS sin mezclar configuraciones del Astro estático.
Operación
Comandos rutinarios
cd /opt/opencloud/opencloud-compose docker compose ps docker compose logs -f opencloud docker compose pull && docker compose up -d git -C /opt/opencloud/opencloud-compose pullss -tulpn | grep -E ‘:22|:80|:443|:9200’ ufw status verbose bash /opt/opencloud/scripts/backup-volumes.sh
Laboratorio vs producción
Fases del despliegue
- TLS provisional: certificado autofirmado útil para validar proxy — alertas en navegador hasta Let's Encrypt con DNS estable.
- Dominio: pasar de IP cruda a FQDN mejora enlaces internos y cookies.
- INSECURE relajado: solo coherente mientras los certificados internos no forman PKI confiable.
- Backups: script manual hasta cron supervisado; vigilar
certbot.timeren producción.
Siguiente paso
Día 2
El día 2 madura autenticación OIDC con Dex, actualiza OpenCloud 7.x y establece el primer backup integral. Mientras tanto, explora los servicios o el relato del día 2.