# Instrucciones para Copilot ## Comandos de build, test y lint - Este repositorio no tiene un build, lint o suite de tests centralizados; la validacion principal se hace con `docker compose config` por stack. - Validar el stack raiz de Portainer: `docker compose -f docker-compose.yml config` - Validar la variante inicial de bootstrap por 9443: `docker compose -f docker-compose.yml -f docker-compose.9443.yml config` - Levantar el bootstrap inicial de Portainer: `docker compose -f docker-compose.yml -f docker-compose.9443.yml up -d` - Validar un stack individual usando su plantilla versionada de variables: `docker compose --env-file /stack.env -f /docker-compose.yml config` - Levantar un stack individual en local con su plantilla de variables: `docker compose --env-file /stack.env -f /docker-compose.yml up -d` - Los unicos scripts ejecutables del repo estan en `n8n-observability/`: - Validar la sintaxis de un script: `bash -n n8n-observability/scripts/server-summary.sh` - Ejecutar un script: `./n8n-observability/scripts/server-summary.sh` - Ejecutar el digest de logs para una ventana concreta: `SINCE="24 hours ago" ./n8n-observability/scripts/log-digest.sh` ## Arquitectura de alto nivel - El repositorio agrupa varios stacks Docker Compose pensados para desplegarse desde Portainer. El orden base es: stack raiz de Portainer, despues `Traefik/`, luego `authentik/` y despues el resto de stacks de aplicaciones. - El `docker-compose.yml` de la raiz define Portainer detras de Traefik. Separa la UI autenticada del host de API/app movil, protegido con una IP allowlist. `docker-compose.9443.yml` no es un stack independiente: es solo un override para anadir el puerto de bootstrap y debe combinarse con el compose raiz. - `Traefik/` es la capa compartida de entrada. Mantiene la red externa `proxy`, el estado de ACME/Let's Encrypt y la configuracion dinamica basada en ficheros bajo `/opt/traefik/dynamic`. - `authentik/` es la capa compartida de SSO. Publica el middleware reutilizable de Traefik `ths-authentik@docker` y la ruta del outpost bajo `/outpost.goauthentik.io/`; los demas stacks consumen ese middleware en vez de redefinir su propia integracion de auth. - Cada carpeta de stack es autocontenida: incluye su propio `docker-compose.yml`, una plantilla `stack.env` versionada y, normalmente, un README con notas de despliegue y operacion. - La mayoria de stacks de aplicacion siguen el mismo patron de red: una red bridge privada para trafico app/base de datos/cache, mas la red externa `proxy` solo para los servicios publicados por Traefik. - `mail-relay/` es infraestructura compartida para SMTP saliente. Los stacks que necesitan correo se conectan a la red `mail_internal` y usan `mail-relay` como host SMTP. - Hay integraciones cruzadas deliberadas entre stacks: Gitea incluye un contenedor runner para Actions, Nextcloud monta `/opt/paperless/media` en solo lectura y Paperless sincroniza su bandeja de entrada desde Nextcloud WebDAV mediante `paperless-inbox-sync`. ## Convenciones clave - `stack.env` es la plantilla versionada de configuracion de cada stack. La documentacion de despliegue indica de forma consistente copiar `stack.env` a `.env` o cargarlo directamente como archivo de entorno; al anadir variables nuevas, actualiza `stack.env` y respeta los nombres ya existentes. - Los datos persistentes del host se guardan en bind mounts bajo `/opt//...`, no dentro del arbol del repositorio. Las rutas nuevas deben seguir esa convencion. - Los bind mounts usan de forma consistente sufijos de relabel SELinux como `:Z`. No los elimines salvo que el stack deje de usar bind mounts del host de forma intencionada. - Los servicios expuestos por HTTP deben unirse a la red `proxy` y definir labels de Traefik para router y service, especialmente `traefik.http.services..loadbalancer.server.port`. - Los servicios solo internos se mantienen fuera de `proxy` y normalmente no llevan labels de Traefik. Solo anade `mail_internal` cuando el servicio necesite llegar al relay SMTP. - El nombre del middleware compartido de Authentik es `ths-authentik@docker`. Reutilizalo desde las labels de los routers en vez de crear variantes por stack, salvo que el stack necesite un comportamiento distinto de verdad. - El stack raiz de Portainer mantiene de forma intencionada routers de Traefik separados para la UI, el acceso directo a la API y dominios adicionales. Conserva esa separacion cuando cambies el enrutado raiz. - La documentacion del repositorio esta mayoritariamente en espanol. Mantén ese estilo al editar READMEs o documentacion de servicios. - Cuando cambies un stack, lee siempre su README junto con `docker-compose.yml` y `stack.env`; muchos README contienen restricciones operativas que no se deducen solo del compose.