diff --git a/bookstack/README.md b/bookstack/README.md index d4642f4..ee60a38 100644 --- a/bookstack/README.md +++ b/bookstack/README.md @@ -2,6 +2,21 @@ Base de conocimiento y documentación desplegada con MariaDB, acceso por Traefik y envío de correo mediante `mail-relay`. +## Arquitectura y propósito + +`bookstack` sirve la aplicación y guarda adjuntos/configuración en `BOOKSTACK_DATA_PATH`; `bookstack-db` conserva páginas, permisos y estructura en MariaDB. La base sólo usa la red interna `bookstack`. La aplicación se añade a `proxy` para Traefik y a `mail_internal` para enviar correo sin publicar la base de datos ni el relay. + +## Configuración + +- `BOOKSTACK_DOMAIN` y `APP_URL` deben coincidir para que enlaces, cookies y redirecciones HTTPS sean válidos. +- `APP_KEY` cifra datos de aplicación: genérala una vez, mantenla estable y respáldala como secreto. +- Las variables `BOOKSTACK_DB_*` conectan ambos contenedores; las contraseñas deben existir sólo en `.env`. +- `BOOKSTACK_PUID` y `BOOKSTACK_PGID` deben tener acceso a `BOOKSTACK_DATA_PATH`. +- `BOOKSTACK_LANG` y `BOOKSTACK_DARK_MODE` fijan los valores iniciales de interfaz. +- `BOOKSTACK_MAIL_FROM*` identifica el remitente; el transporte usa el servicio interno `mail-relay`. + +Separar datos y base permite actualizar la imagen sin perder contenido y respaldar cada componente con el método adecuado. + ## Requisitos - Docker Compose diff --git a/changedetection/README.md b/changedetection/README.md index ca34c47..51d5c5d 100644 --- a/changedetection/README.md +++ b/changedetection/README.md @@ -2,9 +2,22 @@ changedetection.io published at `https://changedetection.sherlockhomeless.net`. -Deploy with: +## Qué hace y cómo funciona + +Supervisa páginas y avisa cuando cambia su contenido. `changedetection` guarda reglas e histórico en `CHANGEDETECTION_DATA_PATH`; `changedetection-browser` renderiza sitios con JavaScript mediante Playwright. El navegador sólo está en `changedetection_internal`, porque su puerto de depuración no debe exponerse. + +## Configuración + +- `CHANGEDETECTION_DOMAIN` forma `BASE_URL` y debe coincidir con Traefik. +- `CHANGEDETECTION_IMAGE` y `CHANGEDETECTION_BROWSER_IMAGE` fijan las versiones de aplicación y navegador. +- `CHANGEDETECTION_DATA_PATH` contiene toda la configuración que debe respaldarse. +- `PLAYWRIGHT_DRIVER_URL` ya apunta al sidecar; elige el fetcher Playwright dentro de la UI sólo para páginas que lo necesiten, ya que consume más recursos. +- El router dinámico combina CrowdSec, Authentik y Sablier: seguridad, control de identidad y arranque bajo demanda, respectivamente. + +## Despliegue ```bash +docker compose --env-file .env config docker compose --env-file .env up -d ``` diff --git a/finance/README.md b/finance/README.md index af687bb..a1901c2 100644 --- a/finance/README.md +++ b/finance/README.md @@ -2,9 +2,22 @@ Actual Budget published at `https://finance.sherlockhomeless.net`. -Deploy with: +## Qué hace y cómo funciona + +Actual Budget permite administrar presupuesto personal con un modelo local-first y sincronización mediante el servidor. Los datos del servidor se guardan en `ACTUALBUDGET_DATA_PATH`; no hay base de datos separada. + +## Configuración + +- `ACTUALBUDGET_DOMAIN` define el dominio publicado. +- `ACTUALBUDGET_IMAGE` controla la versión que se despliega. +- `ACTUALBUDGET_DATA_PATH` debe incluirse en backups y tener permisos de escritura. +- La red interna aísla el servicio y `proxy` permite a Traefik alcanzarlo. +- El router externo aplica CrowdSec, Authentik y Sablier. Authentik protege el acceso al servidor, pero no sustituye las credenciales/cifrado que configure Actual Budget. + +## Despliegue ```bash +docker compose --env-file .env config docker compose --env-file .env up -d ``` diff --git a/freshrss/README.md b/freshrss/README.md index 4891974..e23cae5 100644 --- a/freshrss/README.md +++ b/freshrss/README.md @@ -2,10 +2,21 @@ Lector RSS personal publicado en `rss.sherlockhomeless.net`. +## Qué hace y arquitectura + +FreshRSS agrega feeds, actualiza artículos mediante cron y ofrece una API compatible con clientes móviles. Este despliegue usa SQLite: datos, usuarios y configuración viven en `FRESHRSS_DATA_PATH`; las extensiones se separan en `FRESHRSS_EXTENSIONS_PATH`. + +## Configuración + +- `FRESHRSS_DOMAIN` define el dominio usado por Traefik. +- `FRESHRSS_CRON_MIN` controla la frecuencia de actualización; una frecuencia agresiva aumenta carga y peticiones a los sitios origen. +- `FRESHRSS_ENV` debe permanecer en producción. +- La web pasa por Authentik, pero la ruta de API no puede usar ese forward-auth porque los clientes móviles no completan el flujo web. Activa la API en el perfil de FreshRSS y usa una contraseña API distinta de la contraseña principal. +- No usa Sablier para que cron pueda actualizar feeds incluso sin visitas. + ## Despliegue ```bash -cp .env.example .env docker compose --env-file .env config docker compose --env-file .env up -d ``` diff --git a/ghost-me/README.md b/ghost-me/README.md index 4c1a716..9cd01b9 100644 --- a/ghost-me/README.md +++ b/ghost-me/README.md @@ -4,9 +4,25 @@ Ghost publication for the personal site currently exposed as: - `https://me.thehomelesssherlock.com` -Deploy with Docker Compose from this directory: +## Qué hace y arquitectura + +Es el sitio personal y portfolio. `ghost-me-db` conserva contenido en MySQL y `ghost-me` sirve Ghost con el tema local `theme-source-personal`. `routes.yaml` separa inicio, blog y proyectos mediante colecciones y etiquetas. + +## Configuración + +- `GHOST_ME_DOMAIN` es el dominio canónico; `GHOST_ME_DOMAIN_ALT` redirige permanentemente al principal. +- `GHOST_ME_DB_*` configura MySQL y debe permanecer sólo en `.env`. +- `GHOST_ME_CONTENT_PATH` conserva uploads y configuración de Ghost. +- `GHOST_ME_ROUTES_PATH` monta las rutas de contenido y debe apuntar a `./routes.yaml`. +- `GHOST_ME_MAIL_FROM` y `mail_internal` permiten correo mediante `mail-relay`. +- El tema se monta desde el repositorio para poder versionarlo; valida sus cambios con `npm test` dentro de `theme-source-personal` antes de actualizarlo. + +La base queda aislada en `ghost_me_internal`; únicamente Ghost se conecta a `proxy` y `mail_internal`. + +## Despliegue ```bash +docker compose --env-file .env config docker compose --env-file .env up -d ``` diff --git a/ghost/README.md b/ghost/README.md index 82c144e..6bd5b4e 100644 --- a/ghost/README.md +++ b/ghost/README.md @@ -2,6 +2,18 @@ Ghost publica `news.sherlockhomeless.net` como archivo de informes diarios. +## Arquitectura y configuración + +- `ghost-db` conserva contenido y miembros en MySQL; sólo pertenece a `ghost_internal`. +- `ghost` sirve la publicación, persiste temas y medios en `GHOST_CONTENT_PATH`, usa `mail-relay` y se publica mediante `proxy`. +- `ghost-ops-gate` protege el índice privado `/ops` comprobando el miembro autenticado contra `GHOST_OPS_ALLOWED_EMAIL` y consultando posts con `GHOST_CONTENT_API_KEY`. + +`GHOST_DOMAIN` fija la URL canónica; las variables `GHOST_DB_*` deben coincidir entre Ghost y MySQL. `GHOST_MAIL_FROM` controla el remitente. La Content API key sólo permite lectura, pero sigue siendo secreta y debe vivir únicamente en `.env`. + +Los overrides de `theme-overrides/headline` ocultan publicaciones etiquetadas `#private-ops`. Deben aplicarse sobre la versión compatible del tema; tras actualizar Ghost o Headline, revisa diferencias antes de copiarlos. + +La capa `/ops` no reemplaza la seguridad de cada post: usa miembros de Ghost, etiqueta interna y visibilidad adecuada, además del gate. + ## Despliegue ```bash diff --git a/guacamole/README.md b/guacamole/README.md index dfab3fe..a3ab4c1 100644 --- a/guacamole/README.md +++ b/guacamole/README.md @@ -8,3 +8,25 @@ Guacamole runs in Docker and connects to the host XFCE desktop through local `xr - Backend RDP target: `host.docker.internal:3389` Use a local host account that is allowed to start an XRDP session. + +## Qué hace y arquitectura + +Apache Guacamole ofrece escritorio remoto desde el navegador. `guacamole` gestiona usuarios y conexiones, `guacd` traduce el protocolo web a RDP y PostgreSQL conserva la configuración. Sólo la aplicación web llega a `proxy`; guacd y PostgreSQL permanecen en la red interna. + +## Configuración + +- `GUACAMOLE_DOMAIN` define el acceso publicado por Traefik. +- `GUACAMOLE_DB_*` debe coincidir en PostgreSQL y Guacamole. +- `GUACAMOLE_DATA_PATH` persiste la base; `initdb` sólo inicializa una base vacía. +- `host.docker.internal` se fija a `10.0.4.1` para alcanzar XRDP del host. Si cambia la IP del bridge/host, actualiza ambos servicios. +- `WEBAPP_CONTEXT=ROOT` elimina el prefijo `/guacamole`. + +Authentik protege el perímetro, pero Guacamole mantiene sus propios usuarios y permisos sobre conexiones. Evita cuentas compartidas y no publiques el puerto RDP en la zona pública. + +## Despliegue + +```bash +cd guacamole +docker compose --env-file .env config +docker compose --env-file .env up -d +``` diff --git a/homepage/README.md b/homepage/README.md index 1fa5af5..a467241 100644 --- a/homepage/README.md +++ b/homepage/README.md @@ -2,6 +2,10 @@ Stack para desplegar [Homepage](https://gethomepage.dev/) detrás de Traefik como dashboard principal en `www.sherlockhomeless.net`. +## Qué hace y arquitectura + +Homepage crea un portal a partir de los YAML guardados en `HOMEPAGE_CONFIG_PATH` y descubre servicios mediante labels `homepage.*`. El socket Docker está montado en sólo lectura para descubrir contenedores, pero ese acceso sigue revelando metadatos sensibles; la UI se protege con CrowdSec y Authentik. + ## 🚀 Despliegue con Docker Compose Asegurate de tener `homepage/.env` configurado y despliega: @@ -31,3 +35,7 @@ mkdir -p /opt/homepage/config ``` Homepage leerá su configuración desde `/opt/homepage/config` y expondrá la UI interna en el puerto `3000`, publicado externamente a través de Traefik y protegido con Authentik mediante `ths-authentik@docker`. + +`HOMEPAGE_ALLOWED_HOSTS` evita peticiones con cabeceras Host inesperadas y debe incluir el dominio público. `TRAEFIK_AUTH_MIDDLEWARE` referencia un middleware existente, no credenciales de Authentik. El router adicional redirige el dominio raíz a `www`; se mantiene separado para no mezclar la redirección con el servicio real. + +Respalda los YAML de configuración, pero no incluyas tokens de widgets directamente: usa el mecanismo de secretos/variables admitido por Homepage. diff --git a/it/README.md b/it/README.md index 3d3742c..9295d83 100644 --- a/it/README.md +++ b/it/README.md @@ -2,6 +2,12 @@ Coleccion de herramientas tecnicas self-hosted. +## Qué hace y configuración + +IT-Tools reúne conversores, generadores y utilidades que se ejecutan principalmente en el navegador. `IT_TOOLS_BASE_IMAGE` fija la imagen upstream usada por el build y `IT_TOOLS_IMAGE` nombra la imagen local resultante. `IT_TOOLS_DOMAIN` y `TRAEFIK_DOCKER_NETWORK` controlan la publicación por Traefik. + +La imagen se construye localmente porque el `Dockerfile` aplica un parche al generador FIGlet. Esta decisión evita depender de una URL rota del upstream; al actualizar la imagen base, verifica si el parche sigue siendo necesario y que aplique sin ocultar cambios incompatibles. + - URL: `https://it.sherlockhomeless.net/` - Contenedor: `it-tools` - Red externa: `proxy` diff --git a/karakeep/README.md b/karakeep/README.md index b68b21b..47638b2 100644 --- a/karakeep/README.md +++ b/karakeep/README.md @@ -2,6 +2,22 @@ Servicio para guardar, buscar y enriquecer enlaces. Incluye Karakeep, un navegador Chromium para capturas y Meilisearch para indexación. +## Arquitectura y propósito + +Karakeep guarda el contenido principal en `/opt/karakeep/data`, delega la búsqueda a `karakeep-meilisearch` y usa `karakeep-chrome` para renderizar páginas dinámicas y generar capturas. Sólo la aplicación se une a `proxy`; Chrome y Meilisearch permanecen en `karakeep_internal`. + +## Configuración + +- `KARAKEEP_DOMAIN` define la URL canónica usada por NextAuth. +- `NEXTAUTH_SECRET` firma sesiones; debe ser aleatorio y estable. +- `MEILI_MASTER_KEY` protege el índice. Debe coincidir en Karakeep y Meilisearch y nunca contener un valor real en `stack.env`. +- `DISABLE_SIGNUPS` debe permanecer activado tras crear las cuentas necesarias. +- `OCR_LANGS` controla los idiomas de reconocimiento. +- Las variables `INFERENCE_*`, `OPENAI_API_KEY` y `EMBEDDING_TEXT_MODEL` habilitan etiquetado, resumen y embeddings. Si se usa LiteLLM, configura una URL compatible soportada por Karakeep y entrega una clave de LiteLLM, nunca `auth.json` de Codex. +- `INFERENCE_NUM_WORKERS` y los límites de contexto/salida controlan consumo y concurrencia; aumenta estos valores sólo después de medir memoria y cuota. + +Chrome se ejecuta con `--no-sandbox`; por eso no debe exponerse a redes externas. + ## Requisitos - Docker Compose diff --git a/litellm/README.md b/litellm/README.md index 0e28f7a..0b208ad 100644 --- a/litellm/README.md +++ b/litellm/README.md @@ -1,14 +1,83 @@ # LiteLLM -Proxy unificado para proveedores de modelos LLM, con configuración en `config.yaml`, proveedor local en `codex_provider.py` y PostgreSQL para persistencia. +LiteLLM es la pasarela central de modelos del repositorio. Ofrece una API compatible con OpenAI a aplicaciones como Open WebUI, n8n y Paperless AI, mientras mantiene las credenciales reales de los proveedores en un único servicio. -## Requisitos +## Qué despliega -- Docker Compose -- Red externa `proxy` -- Un archivo `.env` local con las claves de proveedores, claves maestras de LiteLLM y credenciales PostgreSQL -- El archivo de autenticación de Codex montado en la ruta definida por el Compose -- Enrutamiento dinámico de Traefik configurado fuera de esta aplicación +- `litellm`: proxy, catálogo de modelos y proveedor personalizado de Codex. +- `litellm-db`: PostgreSQL para configuración y estado persistente de LiteLLM. +- `config.yaml`: alias públicos y proveedor asociado a cada modelo. +- `codex_provider.py`: adaptación entre la API de LiteLLM y la API Responses de Codex. + +Esta separación evita configurar una credencial de OpenAI o Codex distinta en cada consumidor. Las aplicaciones sólo conocen la URL de LiteLLM, una clave de acceso de LiteLLM y el alias del modelo. + +## Redes y exposición + +LiteLLM pertenece a su red interna `litellm` y a la red externa `proxy`. PostgreSQL sólo está en la red interna. Los consumidores conectados a `proxy` pueden usar: + +```text +http://litellm:4000/v1 +``` + +El acceso público y la interfaz se enrutan mediante la configuración dinámica de Traefik en `/opt/traefik/dynamic/litellm.yml`. La API debe exigir `LITELLM_MASTER_KEY`; la protección SSO de la interfaz no sustituye esa clave. + +## Configuración + +El `.env` local debe definir, como mínimo: + +| Variable | Función | Motivo | +| --- | --- | --- | +| `LITELLM_MASTER_KEY` | Autentica a los consumidores de la API | Impide usar los modelos sólo por alcanzar la red | +| `LITELLM_SALT_KEY` | Cifra datos sensibles almacenados por LiteLLM | Debe permanecer estable tras el primer arranque | +| `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB` | Base de datos interna | No se exponen fuera de la red `litellm` | +| `LITELLM_DB_DATA_PATH` | Persistencia de PostgreSQL | Permite recrear contenedores sin perder estado | +| `DEEPSEEK_API_KEY` | Acceso directo a DeepSeek | Sólo se necesita para los alias `thsllm-*` | + +`config.yaml` publica alias estables. Los consumidores deben pedir el alias, no el identificador interno del proveedor. Así se puede cambiar el backend sin reconfigurar cada aplicación. + +## Autenticación de Codex + +El Compose monta: + +```text +/home/felidae/.codex/auth.json -> /root/.codex/auth.json +``` + +La variable `CODEX_AUTH_FILE` apunta a la ruta interior. El montaje es de lectura y escritura porque `codex_provider.py` renueva el access token mediante el refresh token y guarda el resultado en el mismo archivo. + +Flujo: + +1. El usuario inicia sesión con Codex en el host y genera `~/.codex/auth.json`. +2. Docker monta ese archivo únicamente dentro de LiteLLM. +3. El proveedor lee `access_token`, `refresh_token` y `account_id`. +4. Si el JWT vence en menos de 60 segundos, solicita un token nuevo y actualiza el archivo montado. +5. LiteLLM envía la petición a Codex y devuelve una respuesta compatible con OpenAI al consumidor. + +El archivo contiene credenciales reutilizables. No debe copiarse al repositorio, incluirse en imágenes, logs, backups sin cifrar ni montarse en Paperless, n8n u Open WebUI. `.gitignore` excluye `.codex`, pero conviene comprobar antes de cada commit: + +```bash +git status --ignored --short | grep codex +``` + +El usuario que ejecuta Docker debe poder leer y escribir el archivo. Si el host o usuario cambia, actualiza la ruta del volumen en `docker-compose.yml`; una ruta inexistente puede terminar creada como directorio y provocar errores de autenticación. + +## Modelos Codex + +Los alias `gpt-*` configurados con `custom_llm_provider: codex` pasan por `codex_provider.py`. Internamente se usa el prefijo `cx-` para evitar colisiones con los modelos OpenAI nativos de LiteLLM; el proveedor vuelve a convertirlo antes de llamar a Codex. + +El proveedor admite llamadas síncronas, asíncronas y streaming. Codex responde siempre mediante streaming; para una llamada no streaming, el proveedor agrega los fragmentos antes de responder. + +## Configurar consumidores + +Un consumidor compatible con OpenAI necesita: + +```text +Base URL: http://litellm:4000/v1 +API key: valor de LITELLM_MASTER_KEY +Model: gpt-5.6-sol +``` + +Usa la URL interna cuando ambos contenedores compartan `proxy`. Usa la URL HTTPS sólo para clientes externos. Nunca uses el token de Codex como API key del consumidor. ## Despliegue @@ -18,11 +87,19 @@ docker compose --env-file .env config docker compose --env-file .env up -d ``` -## Operación +## Verificación ```bash docker compose --env-file .env ps docker compose --env-file .env logs -f litellm +curl -sS http://127.0.0.1:4000/v1/models \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" ``` -La API se autentica con `LITELLM_MASTER_KEY`; no publiques esa clave ni el `.env`. +Si no se publica el puerto en el host, ejecuta la prueba desde un contenedor unido a `proxy` o usa el dominio HTTPS. + +Errores `401` que mencionen Codex suelen indicar que `auth.json` falta, no tiene permisos o ya no puede renovarse. Errores `401` devueltos antes de seleccionar modelo suelen indicar una `LITELLM_MASTER_KEY` incorrecta. + +## Persistencia y copias de seguridad + +Respalda la ruta `LITELLM_DB_DATA_PATH`. Trata `auth.json` como un secreto independiente: si se respalda, debe hacerse cifrado y con acceso restringido. No restaures simultáneamente versiones distintas del archivo desde varios hosts, porque la rotación del refresh token puede invalidar la copia anterior. diff --git a/memos/README.md b/memos/README.md index d56514f..e92c5db 100644 --- a/memos/README.md +++ b/memos/README.md @@ -2,6 +2,20 @@ Aplicación de notas ligeras respaldada por PostgreSQL. El contenedor `memos-proxy` actúa como punto de entrada hacia Memos. +## Arquitectura y propósito + +`memos-db` conserva usuarios y notas, `memos` ofrece la aplicación en la red interna y `memos-proxy` aplica la adaptación HTTP necesaria antes del enrutamiento externo. La base y Memos no se publican directamente. + +## Configuración + +- `MEMOS_DB_NAME`, `MEMOS_DB_USER` y `MEMOS_DB_PASSWORD` deben coincidir entre PostgreSQL y el DSN generado por el Compose. +- `MEMOS_DOMAIN` establece la URL pública que Memos usa en enlaces y respuestas. +- `TZ` mantiene consistencia en fechas y tareas. +- `/opt/memos/postgres` contiene la base y `/opt/memos/data` los recursos propios de la aplicación. +- `proxy/server.js` se monta en sólo lectura; cualquier cambio requiere recrear `memos-proxy`. + +El proxy tiene `traefik.enable=false` porque el routing se administra externamente. No actives un segundo router sin comprobar prioridades y autenticación. + ## Requisitos - Docker Compose diff --git a/n8n-observability/README.md b/n8n-observability/README.md index 6563ad6..e4c3ff5 100644 --- a/n8n-observability/README.md +++ b/n8n-observability/README.md @@ -1,11 +1,43 @@ # n8n Observability Toolkit Carpeta dedicada para automatizar en n8n: + - Resumen diario de estado del servidor - Alertas de caida real de servicios - Informes automaticos de logs y errores - Resumen IA (texto ejecutivo) +No despliega un contenedor propio. Los scripts se ejecutan en el host porque necesitan consultar systemd, Docker, certificados y endpoints locales; n8n los invoca mediante una credencial SSH con permisos limitados. + +## Configuración + +- Copia `config/services.example.json` a una ubicación local no versionada y define los endpoints que deben comprobarse. +- `HEALTH_ENDPOINTS` permite pasar endpoints directamente; `HEALTH_EXPECTED_CODES` ajusta los códigos aceptados. +- `TARGET_CONTAINERS` limita los contenedores incluidos en el resumen de logs. +- `SINCE` fija la ventana temporal, por ejemplo `24 hours ago`. +- `CERT_EXCLUDE_DOMAINS` omite dominios que no deban auditarse. +- Las variables `OPENCLAW_*` configuran únicamente la comprobación/renovación OAuth del proveedor indicado; no deben imprimirse tokens. + +Se recomienda un usuario SSH dedicado que pueda ejecutar estos scripts y los comandos de lectura necesarios, sin shell administrativa general. Si requiere `sudo`, limita comandos y argumentos en `sudoers`. + +## Integración con LiteLLM y Codex + +El nodo de IA de n8n debe consumir LiteLLM mediante su API compatible con OpenAI, usando una clave de LiteLLM y un alias de modelo. n8n no necesita acceso al archivo `auth.json` de Codex. LiteLLM mantiene y renueva esa sesión, mientras n8n sólo envía el digest ya filtrado. + +```text +n8n -> http://litellm:4000/v1 -> alias de modelo -> proveedor Codex +``` + +Esta separación permite revocar el acceso de n8n sin cerrar la sesión de Codex y evita distribuir el refresh token. El chequeo `openclaw_codex_oauth` de este toolkit es independiente del montaje usado por LiteLLM; no asumas que validar uno valida automáticamente el otro. + +## Instalación + +No se usa Docker Compose. Conserva el directorio en el host, da permisos de ejecución a los scripts y configura en n8n la conexión SSH: + +```bash +chmod +x n8n-observability/scripts/*.sh n8n-observability/scripts/ops-report +``` + ## Estructura - `scripts/ops-report`: motor Python unificado para `summary`, `logs`, `health` y `all` diff --git a/nextcloud/README.md b/nextcloud/README.md index ba08fc9..40f213f 100644 --- a/nextcloud/README.md +++ b/nextcloud/README.md @@ -2,6 +2,21 @@ Plataforma de archivos y colaboración con MariaDB, Redis, tareas cron y OnlyOffice Document Server. +## Arquitectura y propósito + +MariaDB guarda metadatos, Redis aporta bloqueo y caché, `nextcloud` sirve la web y `nextcloud-cron` ejecuta tareas en segundo plano sobre los mismos volúmenes. OnlyOffice es un servicio independiente para editar documentos y se integra mediante JWT. + +## Configuración + +- `NC_DOMAIN`, `TRUSTED_PROXIES` y las variables `OVERWRITE*` hacen que Nextcloud genere HTTPS correctamente detrás de Traefik. +- `MYSQL_*` debe coincidir en Nextcloud, cron y MariaDB. +- `NEXTCLOUD_ADMIN_*` sólo inicializa la primera instalación; después administra usuarios desde Nextcloud. +- `SMTP_*` configura notificaciones a través de `mail_internal`. +- `OO_DOMAIN`, `OO_JWT_SECRET` y `OO_SECURE_LINK_SECRET` protegen la comunicación con OnlyOffice; el JWT configurado en la app de Nextcloud debe ser idéntico. +- `/opt/nextcloud/html`, `config`, `data`, `custom_apps` y `themes` se comparten con cron para ejecutar el mismo código y configuración. + +Redis no sustituye una copia de seguridad. Respalda MariaDB, configuración y datos de forma consistente, preferiblemente activando antes el modo mantenimiento. + ## Requisitos - Docker Compose diff --git a/onetimesecret/README.md b/onetimesecret/README.md index 913f09e..75069f4 100644 --- a/onetimesecret/README.md +++ b/onetimesecret/README.md @@ -2,6 +2,20 @@ Servicio para compartir secretos de un solo uso, con Redis para persistencia temporal y autenticación OIDC mediante Authentik. +## Arquitectura y propósito + +OneTimeSecret cifra y entrega secretos temporales; Redis mantiene su estado. El navegador recibe el enlace, pero la política de acceso exige autenticación OIDC. El Compose usa `AUTH_SSO_ONLY=true`, desactiva altas y evita cuentas locales como vía habitual. + +## Configuración + +- `OTS_SECRET` alimenta las distintas claves criptográficas internas. Debe ser largo, aleatorio, estable y exclusivo de esta app. +- `OTS_DOMAIN` debe coincidir con `OIDC_REDIRECT_URI` y con el cliente creado en Authentik. +- `OTS_OIDC_ISSUER`, `OTS_OIDC_CLIENT_ID` y `OTS_OIDC_CLIENT_SECRET` enlazan el cliente OIDC. +- `OTS_DATA_PATH` conserva datos de aplicación y `OTS_REDIS_PATH` el estado de Redis. +- Las imágenes se fijan con `OTS_IMAGE` y `OTS_REDIS_IMAGE` para controlar actualizaciones. + +Un secreto de un solo uso sigue siendo sensible mientras exista. Restringe backups, logs y acceso administrativo a Redis. + ## Requisitos - Docker Compose diff --git a/opengist/README.md b/opengist/README.md index 2547cc6..a2b6701 100644 --- a/opengist/README.md +++ b/opengist/README.md @@ -2,6 +2,20 @@ Repositorio privado de gists y fragmentos de código, publicado mediante Traefik y autenticado por OIDC. +## Arquitectura y propósito + +OpenGist concentra snippets versionados en un único contenedor. La ruta `OPENGIST_DATA_PATH` almacena repositorios, configuración y base de datos, mientras `proxy` proporciona acceso HTTPS. + +## Configuración + +- `OPENGIST_DOMAIN` se usa como URL externa y debe coincidir con el dominio de Traefik. +- `OPENGIST_OIDC_PROVIDER_NAME` define el texto mostrado al iniciar sesión. +- `OPENGIST_OIDC_CLIENT_ID`, `OPENGIST_OIDC_CLIENT_SECRET` y `OPENGIST_OIDC_DISCOVERY_URL` conectan Authentik mediante discovery OIDC. +- `OPENGIST_DATA_PATH` debe ser escribible por el contenedor y estar incluido en las copias de seguridad. +- `TRAEFIK_DOCKER_NETWORK` debe apuntar a `proxy` para que Traefik elija la interfaz correcta. + +OIDC centraliza identidad, pero los permisos sobre cada gist siguen administrándose en OpenGist. + ## Requisitos - Docker Compose diff --git a/openwebui/README.md b/openwebui/README.md index fe08083..a5643c5 100644 --- a/openwebui/README.md +++ b/openwebui/README.md @@ -1,40 +1,42 @@ -# Open WebUI — Interfaz web para LLMs +# Open WebUI -Open WebUI conectado al stack de Ollama. Expone una UI de chat accesible en `chat.sherlockhomeless.net`, protegida por CrowdSec. Tiene su propio sistema de login, no usa Authentik. +Interfaz de chat para los modelos publicados por LiteLLM. Ollama está deshabilitado explícitamente; este despliegue usa únicamente la API compatible con OpenAI. -## Prerequisitos +## Arquitectura -- Stack **Ollama** desplegado y en la red `proxy` -- DNS + Tunnel registrado para `chat.sherlockhomeless.net` +Open WebUI se une a `proxy`, desde donde Traefik lo publica y puede alcanzar `litellm:4000`. Los chats, usuarios y ajustes se guardan en `OPENWEBUI_DATA_PATH`. -```bash -cd cloudflared -./add-domain.sh chat -``` +## Configuración + +| Variable | Uso | +| --- | --- | +| `OPENAI_API_BASE_URL` | `http://litellm:4000/v1` para tráfico interno | +| `OPENAI_API_KEY` | Valor de `LITELLM_MASTER_KEY`, no una credencial de Codex | +| `WEBUI_SECRET_KEY` | Firma sesiones; debe ser aleatoria y estable | +| `OPENWEBUI_DOMAIN`, `WEBUI_URL` | URL pública detrás de Traefik | +| `ENABLE_SIGNUP` | Debe desactivarse salvo durante un alta controlada | +| `ENABLE_LOGIN_FORM` | Mantiene o elimina el login local según la estrategia SSO | +| `WEBUI_AUTH_TRUSTED_*_HEADER` | Cabeceras de identidad entregadas por el proxy autenticado | + +Las cabeceras de usuario sólo son seguras si Open WebUI no puede alcanzarse evitando Traefik y si el proxy elimina cualquier cabecera equivalente enviada por el cliente. `WEBUI_SECRET_KEY` no debe cambiarse en cada recreación porque invalidaría sesiones. + +## Relación con Codex + +Open WebUI nunca monta ni lee `auth.json`. Envía una petición OpenAI-compatible a LiteLLM; LiteLLM valida su clave, selecciona el alias y, si corresponde, usa su proveedor Codex. Esto limita la exposición del refresh token a un único contenedor. ## Despliegue ```bash -mkdir -p /opt/openwebui/data -# Editar openwebui/.env: cambiar WEBUI_SECRET_KEY por un valor aleatorio -openssl rand -hex 32 -docker compose --env-file openwebui/.env -f openwebui/docker-compose.yml up -d +cd openwebui +docker compose --env-file .env config +docker compose --env-file .env up -d ``` -## Primer acceso +## Verificación -La primera cuenta registrada se convierte en administrador. Después de crearla, pon `ENABLE_SIGNUP=false` en `.env` y redespliega para bloquear nuevos registros. +```bash +docker compose --env-file .env ps +docker compose --env-file .env logs -f openwebui +``` -## Conexión con Ollama - -OpenWebUI se conecta a Ollama via red interna Docker: `http://ollama:11434`. -Ambos contenedores deben estar en la red `proxy`. - -## Variables clave - -| Variable | Descripción | -|----------|-------------| -| `WEBUI_SECRET_KEY` | Clave para firmar sesiones — generar con `openssl rand -hex 32` | -| `OLLAMA_BASE_URL` | URL interna de Ollama (`http://ollama:11434`) | -| `ENABLE_SIGNUP` | `false` para bloquear nuevos registros | -| `WEBUI_NAME` | Nombre mostrado en la interfaz | +Si no aparecen modelos, prueba primero `/v1/models` contra LiteLLM con la misma clave. Si los modelos aparecen pero fallan sólo los alias Codex, revisa el montaje y renovación de `auth.json` en LiteLLM. diff --git a/paperless/README.md b/paperless/README.md index fbc3cf0..c29c996 100644 --- a/paperless/README.md +++ b/paperless/README.md @@ -1,14 +1,83 @@ # Paperless-ngx -Gestión documental con PostgreSQL, Redis, Tika y Gotenberg. El despliegue también incluye Paperless AI y una sincronización unidireccional desde una carpeta de Nextcloud. +Paperless-ngx convierte documentos en un archivo digital consultable. Importa ficheros, extrae texto, ejecuta OCR, clasifica metadatos y conserva el original junto con su versión procesada. -## Requisitos +## Qué despliega -- Docker Compose -- Redes externas `proxy` y `mail_internal` -- Un archivo `.env` local con dominios, credenciales, correo, proxy de confianza y acceso WebDAV a Nextcloud -- Directorios persistentes bajo `/opt/paperless`, `/opt/paperless-ai` y `/opt/rclone` -- Script `/opt/paperless/rclone-sync.sh` +- `paperless`: aplicación principal y consumidor de documentos. +- `paperless-db`: PostgreSQL para metadatos. +- `paperless-redis`: cola y caché. +- `paperless-tika`: extracción de texto de formatos Office y similares. +- `paperless-gotenberg`: conversión de documentos a PDF. +- `paperless-ai`: clasificación y enriquecimiento asistido por un LLM. +- `paperless-inbox-sync`: copia periódica desde una carpeta WebDAV de Nextcloud hacia `consume`. + +Los servicios de datos viven en `paperless_internal`. Paperless y Paperless AI también se unen a `proxy` para ser alcanzables por Traefik y por servicios compartidos como LiteLLM. + +## Configuración principal + +El `.env` local agrupa: + +| Grupo | Variables principales | Por qué existe | +| --- | --- | --- | +| PostgreSQL | `PAPERLESS_DBNAME`, `PAPERLESS_DBUSER`, `PAPERLESS_DBPASS` | Conserva índices, usuarios y metadatos | +| URL y seguridad | `PAPERLESS_DOMAIN`, `PAPERLESS_SECRET_KEY`, `PAPERLESS_ALLOWED_HOSTS`, `TRUSTED_PROXIES` | Genera enlaces correctos y valida peticiones tras Traefik | +| Administrador | `PAPERLESS_ADMIN_USER`, `PAPERLESS_ADMIN_PASSWORD`, `PAPERLESS_ADMIN_MAIL` | Crea el usuario inicial; cambia la contraseña tras el alta | +| Correo | variables `PAPERLESS_EMAIL_*` | Notificaciones mediante `mail_internal` | +| Nextcloud | `NC_DOMAIN`, `NC_WEBDAV_USER`, `NC_WEBDAV_PASS` | Lee la bandeja de entrada remota | +| Sincronización | `RCLONE_SYNC_INTERVAL`, `PAPERLESS_INBOX_DIR` | Controla frecuencia y carpeta origen | + +`PAPERLESS_CONSUMER_POLLING` hace la importación más fiable cuando los archivos llegan por sincronización o montaje y no generan eventos `inotify` normales. + +## Persistencia + +| Ruta | Contenido | +| --- | --- | +| `/opt/paperless/pgdata` | PostgreSQL | +| `/opt/paperless/data` | Índices y estado de Paperless | +| `/opt/paperless/media` | Originales y documentos procesados | +| `/opt/paperless/export` | Exportaciones | +| `/opt/paperless/consume` | Bandeja de importación | +| `/opt/paperless-ai/data` | Configuración y estado de Paperless AI | +| `/opt/rclone` | Configuración auxiliar de rclone | + +La copia de seguridad debe mantener coherencia entre PostgreSQL, `data` y `media`. Respaldar sólo la base de datos no conserva los documentos. + +## Integración de Paperless AI con LiteLLM y Codex + +Paperless AI no se conecta directamente a Codex. Se configura como cliente compatible con OpenAI y llama a LiteLLM: + +```text +API provider: OpenAI compatible +Base URL: http://litellm:4000/v1 +API key: valor de LITELLM_MASTER_KEY +Model: gpt-5.6-sol +``` + +Ambos contenedores comparten la red externa `proxy`, por lo que `litellm` se resuelve por DNS interno. La configuración de Paperless AI se guarda en `/opt/paperless-ai/data`; actualmente no se declara mediante variables en el Compose y debe introducirse desde su interfaz. + +Flujo de una clasificación: + +```text +Paperless -> Paperless AI -> LiteLLM -> proveedor Codex -> Codex +``` + +Esta arquitectura es intencionada: + +- `auth.json` y el refresh token de Codex permanecen sólo en LiteLLM. +- Paperless AI recibe una clave de LiteLLM revocable, no la sesión de Codex. +- El alias de modelo puede cambiar de proveedor sin reconfigurar Paperless AI. +- LiteLLM centraliza control, logs y futuros límites de consumo. + +No montes `/home/felidae/.codex/auth.json` en Paperless AI. Tampoco uses el dominio público de LiteLLM desde Docker salvo que necesites atravesar Traefik; la URL interna evita una vuelta innecesaria por DNS público y TLS. + +Antes de activar clasificación automática, prueba con pocos documentos y revisa qué contenido se envía al modelo. Los documentos pueden contener datos personales o confidenciales. + +## Sincronización desde Nextcloud + +`paperless-inbox-sync` usa WebDAV y el script `/opt/paperless/rclone-sync.sh` para copiar la carpeta configurada hacia `/consume`. Es un flujo unidireccional; comprueba el comportamiento exacto del script antes de cambiarlo por una sincronización con borrado. + +La contraseña WebDAV debe ser una contraseña de aplicación dedicada, con el mínimo acceso necesario. No uses la contraseña principal del usuario de Nextcloud. ## Despliegue @@ -18,11 +87,13 @@ docker compose --env-file .env config docker compose --env-file .env up -d ``` -## Operación +## Verificación y operación ```bash docker compose --env-file .env ps -docker compose --env-file .env logs -f paperless paperless-ai paperless-inbox-sync +docker compose --env-file .env logs -f paperless +docker compose --env-file .env logs -f paperless-ai +docker compose --env-file .env logs -f paperless-inbox-sync ``` -La sincronización copia documentos desde Nextcloud a `/opt/paperless/consume`; revisa sus logs antes de cambiar rutas o credenciales WebDAV. +Comprueba que PostgreSQL, Redis, Tika y Gotenberg estén sanos antes de diagnosticar la aplicación. Si no entran documentos, revisa primero el sync, después `/opt/paperless/consume` y finalmente los logs del consumidor. diff --git a/pdf/README.md b/pdf/README.md index 29fab6b..9a445e4 100644 --- a/pdf/README.md +++ b/pdf/README.md @@ -2,6 +2,19 @@ Servicio self-hosted para manipular PDF. +## Qué hace y configuración + +Stirling PDF combina, divide, convierte, firma y transforma documentos desde una interfaz web. `SECURITY_ENABLELOGIN=false` deja la autenticación en Traefik + Authentik; no debe publicarse una ruta alternativa que evite ese middleware. + +- `STIRLING_PDF_IMAGE` fija la versión. +- `STIRLING_PDF_DOMAIN` define el dominio público. +- `STIRLING_PDF_CONFIG_PATH` guarda configuración. +- `STIRLING_PDF_CUSTOM_PATH` contiene personalización. +- `STIRLING_PDF_LOGS_PATH` conserva logs y debe tener rotación. +- `STIRLING_PDF_PIPELINE_PATH` guarda automatizaciones. + +Los documentos procesados pueden ser confidenciales. Revisa retención de temporales, permisos de los volúmenes y evita registrar nombres o contenido sensible. + - URL: `https://pdf.sherlockhomeless.net/` - Contenedor: `stirling-pdf` - Datos persistentes: `/opt/stirling-pdf/` diff --git a/privatebin/README.md b/privatebin/README.md index 872f8d4..61a78cb 100644 --- a/privatebin/README.md +++ b/privatebin/README.md @@ -2,6 +2,20 @@ Pastebin con cifrado de extremo a extremo en el navegador, ejecutado en modo de sólo lectura y publicado mediante Traefik. +## Arquitectura y propósito + +PrivateBin cifra y descifra en el navegador: el servidor almacena ciphertext, no el texto claro. El contenedor tiene sistema raíz de sólo lectura, usuario sin privilegios y únicamente escribe en `PRIVATEBIN_DATA_PATH`. + +## Configuración + +- `PRIVATEBIN_DOMAIN` define la URL expuesta por Traefik. +- `PRIVATEBIN_IMAGE` debe fijarse a una versión revisada para evitar cambios inesperados. +- `PRIVATEBIN_DATA_PATH` conserva los pastes cifrados y necesita permisos para UID/GID `65534`. +- `nginx-site.conf` separa las operaciones públicas de lectura de las rutas de creación/borrado protegidas por autenticación externa. +- `TRAEFIK_DOCKER_NETWORK` debe coincidir con la red `proxy` existente. + +El cifrado del navegador no protege metadatos, disponibilidad ni clientes comprometidos. Mantén TLS y revisa la política de expiración. + ## Requisitos - Docker Compose diff --git a/sablier/README.md b/sablier/README.md index dd360a6..5c1e1be 100644 --- a/sablier/README.md +++ b/sablier/README.md @@ -2,6 +2,19 @@ Proveedor de arranque bajo demanda para servicios Docker. Se conecta al socket de Docker y a la red externa `proxy`. +## Arquitectura y propósito + +Sablier recibe peticiones desde el middleware correspondiente y arranca contenedores que estaban detenidos, permitiendo reducir consumo de servicios esporádicos. La versión se controla con `SABLIER_VERSION`. + +## Configuración + +- La red `proxy` permite comunicación con Traefik y los servicios activables. +- El socket Docker se monta en sólo lectura, pero sigue otorgando capacidad de inspección y control significativo sobre el host. +- Los servicios gestionados necesitan sus propias etiquetas/middleware de Sablier y una política de parada coherente. +- No gestiones con Sablier bases de datos u otros componentes con arranque lento sin ajustar timeouts y dependencias. + +La etiqueta `prune.protect` debe aplicarse a servicios bajo demanda para que una limpieza no elimine contenedores detenidos que Sablier espera arrancar. + ## Requisitos - Docker Compose diff --git a/vikunja/README.md b/vikunja/README.md index c337ac8..5f67ec7 100644 --- a/vikunja/README.md +++ b/vikunja/README.md @@ -2,6 +2,21 @@ Gestor de tareas y proyectos con PostgreSQL, soporte CalDAV y envío de recordatorios por correo. +## Arquitectura y propósito + +`vikunja` ofrece interfaz, API y CalDAV; `vikunja-db` guarda usuarios, proyectos y tareas. PostgreSQL sólo está en `vikunja_internal`; Vikunja se conecta además a `proxy` y `mail_internal`. + +## Configuración + +- `VIKUNJA_DOMAIN` forma `VIKUNJA_SERVICE_PUBLICURL`; incluye HTTPS y la barra final esperada. +- `VIKUNJA_JWT_SECRET` firma sesiones. Debe ser aleatorio, exclusivo y estable. +- `VIKUNJA_DB_*` debe coincidir en aplicación, healthcheck y PostgreSQL. +- Las variables `VIKUNJA_MAILER_*` configuran SMTP y recordatorios. +- El registro público está desactivado; crea usuarios de forma administrativa. +- `/opt/vikunja/files` guarda adjuntos y `/opt/vikunja/postgres` la base; ambos son necesarios para una restauración completa. + +CalDAV está activado para clientes externos; publica siempre mediante HTTPS y revoca credenciales de clientes perdidos. + ## Requisitos - Docker Compose