Inventario técnico saneado · Verificado el 3 de septiembre de 2026 (America/Santiago)

Arquitectura del servidor SOM

Esta página describe componentes y relaciones. No publica credenciales, tokens, claves privadas ni parámetros sensibles.

Vista general

Internet
   │
   ▼
UFW → Nginx (TLS y enrutamiento)
       ├── :443 /         → Moodle → PHP-FPM → PostgreSQL local
       ├── :443 /arqui/ y doc.minayao.site → documentación estática
       ├── :443 som.minayao.site → SOM Django (Docker :8000 local)
       ├── :443 locker.minayao.site → Learning Locker (Docker :8081 local)
       ├── :443 yet.minayao.site    → Yet SQL LRS (Docker :8080 local)
       ├── :443 kuma.minayao.site → Uptime Kuma (Docker :3002 local)
       └── :443 portainer.minayao.site → Portainer (Docker :9444 local)

Ollama → API privada en 127.0.0.1:11434
Docker → Portainer, Kuma, SOM, Learning Locker y Yet SQL LRS
         ├── SOM → PostgreSQL privado
         ├── Learning Locker → MongoDB y Redis privados
         └── Yet SQL LRS → PostgreSQL privado

Entradas y conexiones

EntradaServicioBackendPersistencia
minayao.siteMoodlePHP-FPM del hostPostgreSQL host + /var/moodledata
som.minayao.siteSOM127.0.0.1:8000PostgreSQL app-db-1
locker.minayao.siteLearning Locker127.0.0.1:8081MongoDB, Redis y archivos
yet.minayao.siteYet SQL LRS127.0.0.1:8080PostgreSQL dedicado
kuma.minayao.siteUptime Kuma127.0.0.1:3002Volumen uptime-kuma
portainer.minayao.sitePortainer127.0.0.1:9444Volumen portainer_data
doc.minayao.siteEsta documentaciónArchivos estáticos/opt/server-architecture

Todos los backends Docker publicados están ligados a loopback; sus bases y cachés no publican puertos. /arqui/, :3001 y :9443 se mantienen como accesos compatibles. El nombre anterior lrs.minayao.site redirige permanentemente a yet.minayao.site.

Core del servidor

ComponenteEstadoFunción y límite
Nginx 1.24ActivoÚnico punto de entrada, TLS y proxy inverso.
Moodle 5.2.1ActivoLMS instalado en el host; raíz pública separada y datos persistentes.
PHP-FPM 8.3ActivoEjecuta Moodle mediante socket Unix local.
PostgreSQL 16.14ActivoDatos de Moodle; escucha sólo en localhost con autenticación SCRAM.
Ollama 0.32.6ActivoIA privada; API sólo en localhost, sin exposición pública.
SOM DjangoSaludableMonolito modular en Docker, publicado exclusivamente bajo /som/.
PostgreSQL SOM 16.14SaludableBase privada en la red interna de SOM, sin puerto publicado.
Learning Locker 7.1.1SaludableLRS en Docker con xAPI Service 7.1.2, MongoDB y Redis privados.
Yet Analytics SQL LRS 0.9.7SaludableLRS en Docker con PostgreSQL privado y volumen dedicado.

Moodle conserva su código, directorio de datos y base. SOM debe integrarse mediante web services, eventos o una capa puente; no escribiendo directamente en tablas internas de Moodle.

Plataforma Docker

ServicioBackend localPersistenciaEntrada
Uptime Kuma127.0.0.1:3002Volumen dedicadoHTTPS :3001 vía Nginx
Portainer127.0.0.1:9444Volumen dedicadoHTTPS :9443 vía Nginx
SOM Django127.0.0.1:8000Imagen reproducibleHTTPS /som/ vía Nginx
PostgreSQL SOMRed interna :5432app_postgres_dataSin entrada pública
Learning Locker127.0.0.1:8081Cinco volúmenes dedicadosHTTPS locker.minayao.site
MongoDB y Redis de Learning LockerRed internaVolúmenes dedicadosSin entrada pública
Yet SQL LRS127.0.0.1:8080yet-lrsql-postgres-dataHTTPS yet.minayao.site
PostgreSQL de Yet SQL LRSRed interna :5432Volumen dedicadoSin entrada pública

Portainer controla el socket Docker y debe considerarse una consola administrativa. SOM, Learning Locker y Yet SQL LRS disponen de manifiestos Compose reproducibles. Los servicios usan redes privadas, volúmenes identificables y políticas de reinicio; sólo Nginx publica las entradas externas.

Plataformas LRS

Learning Locker

El proyecto Compose learning-locker se administra desde /opt/docker-projects/locker/compose.yaml. Incluye MongoDB con replica set, Redis, migraciones, API, interfaz web, worker, scheduler, xAPI Service y un proxy Nginx interno. El host sólo publica 127.0.0.1:8081; Nginx termina TLS en locker.minayao.site.

Los datos sobreviven a recreaciones y reinicios en cinco volúmenes dedicados: MongoDB, configuración de MongoDB, Redis, archivos de aplicación y almacenamiento xAPI. Los servicios continuos usan restart: unless-stopped. Learning Locker 7.1.1 contiene componentes fuera de soporte y debe permanecer aislado, respaldado y accesible sólo mediante TLS.

locker.minayao.site → Nginx host → 127.0.0.1:8081 → Nginx del stack
                                                        ├── ui
                                                        ├── api
                                                        └── xapi
api/ui → MongoDB       worker/scheduler → Redis y tareas asíncronas
ContenedorResponsabilidadDato o límite
mongoMongoDB 4.4.29 con replica setDos volúmenes; 27017 no publicado
mongo-init / migrateInicialización y migraciones puntualesNo son daemons permanentes
redisCoordinación y colasVolumen propio; sin puerto público
api / uiAPI de gestión e interfazAlmacenamiento compartido persistente
worker / schedulerTrabajo asíncrono y programadoSin entrada web
xapixAPI Service 7.1.2Volumen xAPI propio
nginxProxy del stackÚnico puerto publicado: loopback 8081

La red learning-locker_locker-internal no tiene el atributo Docker internal: true; el aislamiento de datos se basa en que sólo el proxy publica un puerto.

Yet Analytics SQL LRS

El proyecto Compose yet-lrsql se administra desde /opt/docker-projects/yet/compose.yaml. SQL LRS escucha en 127.0.0.1:8080 y Nginx lo publica en yet.minayao.site. PostgreSQL permanece exclusivamente en la red privada yet-lrsql-internal.

PostgreSQL conserva sus datos en yet-lrsql-postgres-data. Ambos contenedores tienen health checks y restart: unless-stopped. La administración está bajo /admin y el endpoint xAPI bajo /xapi.

yet.minayao.site → Nginx host → 127.0.0.1:8080 → SQL LRS
                                                         └── PostgreSQL :5432

lrsql usa yetanalytics/lrsql:v0.9.7 y guarda su estado durable en PostgreSQL 16.15 Alpine. Sólo la aplicación publica loopback; la base vive en yet-lrsql-internal y no publica 5432. La red tampoco usa internal: true, por lo que la ausencia de puertos publicados es el límite comprobado.

SOM: monolito modular desplegado

SOM Django
├── API y autenticación
├── integración Moodle
├── identidad
├── LRS y eventos
├── instructores
├── analítica
└── integración IA/Ollama

La entrada activa es https://169.58.128.68/som/api/.... Nginx envía exclusivamente /som/ al contenedor Django enlazado a loopback.

El arranque espera a PostgreSQL, aplica migraciones, recopila estáticos e inicia Gunicorn con dos workers. Django y PostgreSQL tienen health checks. PostgreSQL vive sólo en la red interna; Django utiliza además una red con salida para futuras integraciones.

RutaEstado
/som/Interfaz disponible
/som/api/health/Salud pública, JSON 200
/som/api/API REST navegable
/som/lrs/Módulo autenticado
/som/admin/Administración Django
/som/static/Estáticos mediante WhiteNoise

Los módulos deberían extraerse sólo cuando exista una necesidad medible: escalado independiente, aislamiento de fallos, despliegues diferentes o propiedad por equipos separados.

Operación y administración

Uptime Kuma

Contenedor único, imagen mayor 2, health check y reinicio automático. Su configuración está en el volumen uptime-kuma. Nginx publica 127.0.0.1:3002 mediante el subdominio; HTTPS :3001 continúa por compatibilidad.

Portainer

Contenedor único con estado en portainer_data, publicado en loopback 9444 y mediante su subdominio. Monta el socket Docker, de modo que es una consola privilegiada equivalente al control de contenedores. Tiene reinicio automático, pero no health check declarado.

Documentación

No usa Docker. Nginx sirve esta misma carpeta tanto en doc.minayao.site como bajo /arqui/; el Markdown canónico es único, evitando documentación divergente.

Orden de subdominios y casos de fallo

El DNS comodín hace que incluso un subdominio inexistente llegue a este servidor. Cada servicio válido tiene un server_name explícito y Nginx dispone ahora de servidores por defecto para HTTP y HTTPS. Un host desconocido conserva su ruta, pero redirige con 301 a https://minayao.site; ya no puede caer por orden de carga en Learning Locker. Los desafíos ACME quedan exceptuados para permitir la renovación TLS.

Límites recomendados

  1. Nginx controla toda exposición pública y TLS.
  2. Moodle se consume mediante contratos API explícitos.
  3. Ollama permanece privado detrás de una interfaz interna controlada.
  4. Cada servicio es propietario de sus datos, volúmenes y credenciales.
  5. Los trabajos largos de analítica salen del ciclo de petición HTTP.
  6. Eventos y tareas asíncronas pueden introducirse antes de separar microservicios.

Pendientes prioritarios

  1. Definir y probar respaldos de PostgreSQL, Moodledata, configuraciones y volúmenes Docker.
  2. Restringir el acceso administrativo a Portainer.
  3. Revisar los límites PHP de carga frente al límite configurado en Nginx.
  4. Convertir Portainer y Kuma en proyectos Compose reproducibles; SOM ya dispone de manifiesto.
  5. Definir y probar respaldos de los volúmenes de Learning Locker y Yet SQL LRS.
  6. Mantener las bases de datos y cachés de los LRS sin puertos publicados.
  7. Mantener SOM publicado exclusivamente bajo /som/.
  8. Diseñar el acceso privado y auditable de SOM a Ollama.