From 3fa2b7a5d7f95ac52e9d9472134685ce3698971e Mon Sep 17 00:00:00 2001 From: fenix Date: Tue, 10 Mar 2026 15:30:21 +0100 Subject: [PATCH] docs: add multi-file notes and mount watchdog to README - Document ?f= param for internal .md links in viewer.html - Add nginx location block for per-user .md files to deploy template - Document mount watchdog timer (auto-recovery every 12min) - Update nginx reference copies with new .md location block - Update repo structure and history Co-Authored-By: Claude Opus 4.6 --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++-- nginx/napi-ddaw2.conf | 13 +++++-- nginx/napi2-asir1.conf | 7 ++++ viewer.html | 12 +++++-- 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6614416..74b77b1 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,59 @@ Monitoriza `/home/USER/python/` — detecta entregas de prácticas de Programaci --- +## Notas Multi-fichero (enlaces internos) + +El viewer soporta distribuir el feedback en múltiples ficheros `.md` por alumno. Útil cuando `notas.md` crece demasiado con el feedback acumulado de muchas prácticas. + +### Estructura + +``` +data/barrios/ +├── notas.md ← TOC con tabla resumen y enlaces +├── nota-p3.1-sqlite.md ← feedback detallado P3.1 +├── nota-p3.2-funciones.md ← feedback detallado P3.2 +└── nota-p3.3-ficheros.md ← feedback detallado P3.3 +``` + +### Ejemplo de `notas.md` con enlaces + +```markdown +# Notas — Andrés Barrios + +| **Práctica** | **Nota** | **Estado** | +|:-------------|:--------:|:----------:| +| P3.1 — [SQLite](nota-p3.1-sqlite.md) | 8 | Entregada | +| P3.2 — [Funciones](nota-p3.2-funciones.md) | 7 | Entregada | +| P3.3 — [Ficheros](nota-p3.3-ficheros.md) | — | Pendiente | +| **TOTAL** | **7.5** | | +``` + +### Ejemplo de sub-nota (`nota-p3.1-sqlite.md`) + +```markdown +# Práctica 3.1 — SQLite + +## Feedback +Buen uso de SELECT con WHERE compuestos. Normalización correcta hasta 3FN. + +### A mejorar +- Revisar los JOINs entre tablas con FK compuestas + +**Nota: 8/10** + +[← Volver a notas](notas.md) +``` + +### Cómo funciona + +1. `viewer.html` lee el parámetro `?f=` de la URL (por defecto `notas.md`) +2. Los enlaces internos a `.md` se reescriben automáticamente a `/?f=nombre.md` +3. Nginx sirve cualquier `.md` del directorio del alumno autenticado +4. El alumno navega entre ficheros sin salir del viewer — el botón atrás del navegador funciona +5. **Compatible hacia atrás** — si solo existe `notas.md`, todo funciona igual que antes + +--- + ## Requisitos del Servidor (Debian) - Debian 11/12/... @@ -225,6 +278,14 @@ server { add_header Cache-Control "no-cache"; } + # Notas multi-fichero (enlaces internos desde notas.md) + location ~ ^/(.+\.md)$ { + alias /var/www/napiN/data/$remote_user/$1; + default_type text/plain; + charset utf-8; + add_header Cache-Control "no-cache"; + } + location ~* \.(js|css)$ { expires 7d; } location / { return 404; } } @@ -282,7 +343,9 @@ systemctl --user enable --now 'home-fenix-napi\x2ddataN.mount' │ ├── python-upload-watcher.service ← unit systemd │ ├── nginx-user-config-watcher.service │ ├── home-fenix-napi-data.mount ← sshfs DDAW2 -│ └── home-fenix-napi-data2.mount ← sshfs ASIR1 +│ ├── home-fenix-napi-data2.mount ← sshfs ASIR1 +│ ├── napi-mount-watchdog.service ← watchdog auto-recovery +│ └── napi-mount-watchdog.timer ← timer cada 12 min └── Screenshots/ └── zzz@librebits.info.png ← ejemplo notificaciones XMPP ``` @@ -314,6 +377,15 @@ systemctl --user status home-fenix-napi\\x2ddata.mount # DDAW2 systemctl --user status home-fenix-napi\\x2ddata2.mount # ASIR1 ``` +### Watchdog de mounts (en aldebaran/anka4) + +Si zzz se reinicia o la conexión SSH se corta, los mounts quedan en estado `failed` permanentemente. El watchdog los detecta y reinicia automáticamente cada 12 minutos. + +```bash +systemctl --user status napi-mount-watchdog.timer +systemctl --user list-timers napi-mount-watchdog.timer +``` + ### Logs ```bash @@ -331,7 +403,7 @@ sudo tail -f /var/log/nginx/napi-error.log # Nginx errors | `401 Unauthorized` | Credenciales incorrectas o PAM mal configurado | Verificar `/etc/pam.d/common-auth` | | `twemoji is not defined` | Falta `twemoji.min.js` en el root del site | `sudo cp /var/www/napi/twemoji.min.js /var/www/napiN/` | | `404` en `/notas.md` | Carpeta del alumno no existe en `data/` | Crear carpeta + copiar plantilla | -| sshfs zombie | Conexión SSH caída | `fusermount -uz ~/napi-dataN && systemctl --user restart ...mount` | +| sshfs zombie | Conexión SSH caída | `fusermount -uz ~/napi-dataN && systemctl --user restart ...mount` (el watchdog lo hace automáticamente cada 12 min) | | Emacs muestra datos stale tras editar | sshfs cachea lecturas del kernel | Añadir `auto_cache` a las Options del mount (ver abajo) | | Watcher no detecta re-entregas | Versión antigua del watcher | Actualizar a v7+ y reiniciar servicio | | `__pycache__` en notificaciones | Watcher < v6 | Actualizar a v7+ | @@ -357,4 +429,6 @@ sudo tail -f /var/log/nginx/napi-error.log # Nginx errors | 2026-02-25 | ASIR1 desplegado: asir1.qu3v3d0.tech para Programación (21 alumnos) | | 2026-02-25 | Watcher ASIR1 v7: batching, re-entregas, Windows-safe, __pycache__ filter, nombres completos | | 2026-03-02 | sshfs mounts: añadido `auto_cache` para evitar datos stale en Emacs | +| 2026-03-10 | Watchdog timer para auto-recovery de mounts sshfs caídos | +| 2026-03-10 | Soporte notas multi-fichero: viewer.html `?f=` + nginx `location ~ .md` | | 2027-02-04 | Renovar certificado SSL wildcard (caduca ~365 días desde 2026-02-04) | diff --git a/nginx/napi-ddaw2.conf b/nginx/napi-ddaw2.conf index 4a942de..dbca786 100644 --- a/nginx/napi-ddaw2.conf +++ b/nginx/napi-ddaw2.conf @@ -1,6 +1,6 @@ # napi — Notas API (notas.qu3v3d0.tech) # Auth: PAM (mismas credenciales que SFTP) -# Datos: /var/www/api/data/$remote_user/notas.md +# Datos: /var/www/napi/data/$remote_user/notas.md server { listen 80; @@ -15,7 +15,7 @@ server { ssl_certificate /etc/ssl/certs/qu3v3d0.tech.crt; ssl_certificate_key /etc/ssl/private/qu3v3d0.tech.key; - root /var/www/api; + root /var/www/napi; auth_pam "Notas DDAW2"; auth_pam_service_name "common-auth"; @@ -25,7 +25,7 @@ server { } location = /notas.md { - alias /var/www/api/data/$remote_user/notas.md; + alias /var/www/napi/data/$remote_user/notas.md; default_type text/plain; charset utf-8; add_header Cache-Control "no-cache"; @@ -35,6 +35,13 @@ server { expires 7d; } + location ~ ^/(.+\.md)$ { + alias /var/www/napi/data/$remote_user/$1; + default_type text/plain; + charset utf-8; + add_header Cache-Control "no-cache"; + } + location / { return 404; } diff --git a/nginx/napi2-asir1.conf b/nginx/napi2-asir1.conf index 4fbfb7f..a79ee7b 100644 --- a/nginx/napi2-asir1.conf +++ b/nginx/napi2-asir1.conf @@ -35,6 +35,13 @@ server { expires 7d; } + location ~ ^/(.+\.md)$ { + alias /var/www/napi2/data/$remote_user/$1; + default_type text/plain; + charset utf-8; + add_header Cache-Control "no-cache"; + } + location / { return 404; } diff --git a/viewer.html b/viewer.html index 96f4609..46e0b59 100644 --- a/viewer.html +++ b/viewer.html @@ -20,9 +20,17 @@
Cargando...