hbox-docs/DESPLIEGUE.md

15 KiB

Despliegue — sitio, backend de actas y usuarios

Servidor: git.helgen.online · dominio público: https://drogheda.helgen.online

Qué vive dónde

Parte Ruta en el servidor Cómo se actualiza
Sitio (docs, formularios, tableros) /srv/projects/drogheda/hbox-docs/site ./scripts/deploy.sh desde la Mac
Backend de actas (app.py) /srv/projects/drogheda/hbox-docs/backend git pull en el servidor + systemctl restart actas-hbox
Actas recibidas (JSON + índice CSV) /srv/projects/drogheda/actas las escribe el backend
Fotos de campo /srv/projects/drogheda/adjuntos las escribe el backend
Pendientes del tablero (kanban) /srv/projects/drogheda/tareas las escribe el backend — 13-oct
Inventario (ítems y movimientos) /srv/projects/drogheda/inventario las escribe el backend — 13-oct
Sitios /srv/projects/drogheda/sitios las escribe el backend — 13-oct
Plan de producción /srv/projects/drogheda/plan-produccion.json lo escribe el backend (admin) — 13-oct
Equipo (miembros, bitácora de accesos) /srv/projects/drogheda/equipo las escribe el backend — 14-oct
Usuarios (HTTP Basic) /etc/nginx/hbox-docs.htpasswd htpasswd

Lo importante: deploy.sh publica solo el sitio. Si cambió backend/app.py —como en esta versión— hay que hacer además el git pull + restart en el servidor, o el sitio nuevo hablará con un backend viejo (las fotos darían 404 y el diagnóstico se bloquearía como si fuera un acta de banco).


A · Despliegue de esta versión (diagnóstico en campo)

Los pasos 3, 4 y 5 son de una sola vez; los pasos 1 y 2 son el ciclo normal de siempre.

1 · Desde la Mac — publicar el sitio

cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
git add -A && git commit -m "diagnóstico en campo: acta, fotos, tablero y procedimiento"
git push
./scripts/deploy.sh                 # mkdocs build --strict + rsync a /srv/.../site

2 · En el servidor — actualizar el backend

cd /srv/projects/drogheda/hbox-docs && git pull
sudo systemctl restart actas-hbox
curl -s http://127.0.0.1:8081/api/salud        # {"ok":true,"servicio":"actas-hbox"}

3 · Carpeta de fotos (una sola vez)

sudo mkdir -p /srv/projects/drogheda/adjuntos
sudo chown -R leo:leo /srv/projects/drogheda/adjuntos

El backend la deduce sola de ACTAS_DIR; si prefieres fijarla, agrega a /etc/systemd/system/actas-hbox.service (y luego daemon-reload + restart):

Environment=ADJUNTOS_DIR=/srv/projects/drogheda/adjuntos
Environment=ADJUNTO_MAX_MB=8
Environment=ARCHIVO_MAX_MB=20
Environment=ACTAS_REPETIBLES=diagnostico-campo,diagnostico-banco,instalacion-campo,reflasheo,dano,envio,recepcion,prueba-bateria-modem,prueba-ethernet-serie

4 · nginx — subida de fotos e identidad del técnico (una sola vez)

En el bloque server { listen 443 … } de drogheda.helgen.online, el location /api/ queda así:

    location /api/ {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Remote-User     $remote_user;   # ← quién es el técnico
        client_max_body_size 25m;                          # ← sin esto, las fotos dan 413
        proxy_read_timeout   120s;                         # ← subidas con señal mala
    }

Las dos líneas marcadas son nuevas y obligatorias:

  • Sin client_max_body_size, nginx corta la subida en 1 MB y el técnico ve "la foto pesa demasiado" aunque no lo pese. (El formulario ya reduce cada foto a ~1600 px / 300-400 kB antes de subirla; el margen es para ráfagas de varias fotos.)
  • Sin X-Remote-User, el backend no sabe quién envió cada acta: el nombre no se precarga y —más serio— cualquier usuario autenticado podría mandar la cabecera a mano y hacerse pasar por leo para borrar actas. Al fijarla en nginx, el valor del cliente se sobrescribe siempre. Revisa si ya la tienes: es fácil que no, porque no venía en el README original.
sudo nginx -t && sudo systemctl reload nginx

5 · Usuarios de los técnicos (una sola vez)

sudo htpasswd /etc/nginx/hbox-docs.htpasswd alan
sudo htpasswd /etc/nginx/hbox-docs.htpasswd daniel
# (sin -c: -c CREA el archivo de cero y borraría a leo y a luz)
sudo cut -d: -f1 /etc/nginx/hbox-docs.htpasswd     # lista de usuarios

Administradores (quién puede borrar o reabrir actas) = variable ACTAS_ADMINS del servicio, hoy leo. Alan y Daniel quedan como técnicos: llenan y envían, no borran.

7 · Permisos para que los técnicos cambien su contraseña (una sola vez)

La página Mi cuenta (/cuenta.html) deja que cada quien cambie su propia contraseña, y que el administrador restablezca la de otro. Para eso el servicio tiene que poder escribir el archivo de usuarios que nginx solo lee:

# quién es el usuario de nginx (normalmente www-data)
grep -E "^\s*user" /etc/nginx/nginx.conf

sudo chown leo:www-data /etc/nginx/hbox-docs.htpasswd
sudo chmod 640          /etc/nginx/hbox-docs.htpasswd
sudo systemctl restart actas-hbox

Así: leo (el servicio) escribe, www-data (nginx) lee, y nadie más puede ni leerlo.

Comprueba que las contraseñas estén en el formato que el servicio sabe verificar:

sudo cut -d: -f2 /etc/nginx/hbox-docs.htpasswd | cut -c1-6

Todas deben decir $apr1$. Si alguna sale distinta ($2y$ es bcrypt), esa persona no va a poder cambiar la suya sola: restablécesela desde la propia página, que la vuelve a guardar en $apr1$.

!!! note "Por qué no se usa el comando htpasswd desde el servicio" Pasar una contraseña como argumento (htpasswd -b … clave) la deja visible en ps para cualquiera con sesión en el servidor. El hash $apr1$ se calcula dentro del proceso; está verificado carácter por carácter contra la salida de htpasswd, incluyendo acentos y espacios.

!!! tip "Al cambiar la contraseña, la sesión no se cae" HTTP Basic se guarda en el navegador: quien cambie la suya sigue navegando con la anterior hasta que cierre sesión o cierre el navegador. La página lo explica y ofrece la liga de Salir para probarla de inmediato. No es un error.


A2 · Despliegue 13-oct — tableros, inventario, sitios e instalación en campo

Esta versión agrega al backend cuatro colecciones nuevas (pendientes del tablero, plan de producción, inventario con movimientos, sitios) y páginas que las usan (tableros/, inventario/, sitios/, formularios/instalacion.html). Igual que siempre: el sitio se publica desde la Mac; el backend se actualiza en el servidor. Si solo publicas el sitio, los tableros dirán «No se pudo cargar» porque hablan con endpoints que el backend viejo no tiene.

1 · Desde la Mac — publicar el sitio

cd ~/Documents/Claude/Projects/Drogheda/hbox-docs
git add -A && git commit -m "tableros kanban, inventario, sitios, acta de instalación (13-oct)"
git push
./scripts/deploy.sh

2 · En el servidor — backend y carpetas (las carpetas, una sola vez)

ssh leo@git.helgen.online
cd /srv/projects/drogheda/hbox-docs && git pull

# carpetas de las colecciones nuevas (junto a /actas; el backend las deduce de ACTAS_DIR)
sudo mkdir -p /srv/projects/drogheda/{tareas,inventario/items,inventario/movimientos,sitios}
sudo chown -R leo:leo /srv/projects/drogheda/{tareas,inventario,sitios}
sudo chown leo:leo /srv/projects/drogheda      # (sin -R) el backend escribe plan-produccion.json en esta carpeta

sudo systemctl restart actas-hbox
curl -s http://127.0.0.1:8081/api/salud                       # {"ok":true,"servicio":"actas-hbox"}
curl -s -H 'X-Remote-User: leo' http://127.0.0.1:8081/api/tareas/resumen   # {"ok":true,"total":0,...}

Variables de entorno: no hace falta tocar el .service. Si quieres mover las carpetas, descomenta en /etc/systemd/system/actas-hbox.service las líneas TAREAS_DIR, INVENTARIO_DIR, SITIOS_DIR, PLAN_FILE (vienen comentadas en backend/actas-hbox.service) y luego daemon-reload + restart.

3 · Siembra inicial (una sola vez; repetirla no duplica nada)

cd /srv/projects/drogheda/hbox-docs
./backend/venv/bin/python3 backend/seed_1013.py --usuario leo

Crea: el plan (570 → 113 V5.6 / 327 V5.7 / 130 v6), los 4 sitios (icave, lzc, eit, timsa — ubicación y contactos «por confirmar» donde no se sabe), 18 ítems de inventario con stock 0 (Jesús hace el conteo físico con movimientos «ajuste») y los 12 pendientes del tablero del 13-oct. Lo que ya exista con el mismo id se deja intacto. Para importar los pendientes del Task Tracker de Notion, exporta una lista JSON con id, titulo, pista, estado, responsable y pásala con --extra archivo.json.

4 · Verificar

curl -s -u leo:PASS https://drogheda.helgen.online/api/tareas | head -c 300
curl -s -u leo:PASS https://drogheda.helgen.online/api/plan | head -c 200
curl -s -u leo:PASS https://drogheda.helgen.online/api/inventario | head -c 200
curl -s -u leo:PASS https://drogheda.helgen.online/api/sitios | head -c 200

Y desde el navegador: /tableros/kanban.html (arrastra un pendiente y revisa que el historial anote quién lo movió), /inventario/inventario.html (registra un «ajuste» con el conteo real), /sitios/sitio.html?id=icave, /formularios/instalacion.html con la unidad PRUEBA.

5 · Respaldo

Se suman tres carpetas y un archivo a la rutina de siempre:

rsync -az leo@git.helgen.online:/srv/projects/drogheda/tareas/     ~/respaldo-tareas/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/inventario/ ~/respaldo-inventario/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/sitios/     ~/respaldo-sitios/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/plan-produccion.json ~/respaldo-plan/

A3 · 14-oct: equipo y usuarios

Agrega la colección equipo (quién es quién; los responsables de los pendientes), la administración de accesos desde el sitio (/tableros/equipo.html, solo admin) y hace obligatorio el responsable en cada pendiente. Compatible con lo ya desplegado: los pendientes viejos siguen funcionando; la siembra les calcula responsable_ids y pone leo solo donde el responsable estaba vacío.

# Mac
cd ~/Documents/Claude/Projects/Drogheda/hbox-docs && git add -A && git commit -m "equipo, usuarios y responsables (14-oct)" && git push && ./scripts/deploy.sh

# servidor
ssh leo@git.helgen.online
cd /srv/projects/drogheda/hbox-docs && git pull
sudo systemctl restart actas-hbox
./backend/venv/bin/python3 backend/seed_1013.py --usuario leo     # crea equipo/ (9 miembros, sin accesos) + el pendiente de ferretería; no duplica
curl -s -H 'X-Remote-User: leo' http://127.0.0.1:8081/api/equipo | head -c 200

La carpeta equipo/ la crea la siembra (o el backend al primer alta) junto a /actas; no hay variables nuevas que fijar (EQUIPO_DIR, HTPASSWD_LOCK vienen comentadas en el .service).

Para crear o quitar accesos desde la página, el servicio tiene que poder escribir el htpasswd — es lo mismo que ya pide «Mi cuenta» (§7): sudo chown leo:www-data /etc/nginx/hbox-docs.htpasswd && sudo chmod 640 /etc/nginx/hbox-docs.htpasswd. Si no está hecho, la página de Equipo lo avisa y solo deja editar miembros. A partir de aquí los usuarios se crean en Equipo → Nuevo usuario / miembro (la contraseña inicial se muestra una sola vez), no con htpasswd en el servidor. Las cuentas que ya existen y no son miembro (p. ej. luz) aparecen como «cuentas con acceso que no están en el equipo»: dales de alta como miembro sin marcar «crear acceso».

Verificar: /tableros/equipo.html como leo (botones) y como un técnico (solo lectura); crear un pendiente sin responsable debe rechazarse; backend/tests-1014.sh reproduce todo con un htpasswd temporal.

Síntoma Causa Arreglo
Los tableros dicen «No se pudo cargar (HTTP 404)» backend viejo paso 2 (git pull + restart)
«El servicio no tiene permiso de escribir el archivo de usuarios» al crear un acceso falta el chown/chmod del htpasswd §7
«Falta el responsable del pendiente» al crear regla del 14-oct elige a alguien del equipo (o escríbelo en texto libre)
«No puedo identificarte (falta X-Remote-User…)» al crear o mover nginx no manda la cabecera paso 4 del despliegue anterior
El tablero sale vacío falta la siembra paso 3
«Solo un administrador…» al borrar o editar sitios/plan ese usuario no está en ACTAS_ADMINS así debe ser; pide a Leo
PermissionError al guardar el plan /srv/projects/drogheda no es de leo chown del paso 2

B · Verificación después de desplegar

# 1. el backend responde y sabe quién eres
curl -s -u leo:PASS   https://drogheda.helgen.online/api/whoami   # {"user":"leo","admin":true}
curl -s -u alan:PASS  https://drogheda.helgen.online/api/whoami   # {"user":"alan","admin":false}

Si user sale vacío, falta la línea X-Remote-User del paso 4.

# 2. la subida de fotos funciona de punta a punta
curl -s -u alan:PASS -F tipo=diagnostico-campo -F serie=CAMPO-PRUEBA \
     -F foto=@cualquier-foto.jpg \
     https://drogheda.helgen.online/api/adjuntos
# → {"ok":true,"fotos":[{"ruta":"diagnostico-campo/CAMPO-PRUEBA/2026…jpg",…}]}

# 3. el acta de campo NO se bloquea al segundo envío
curl -s -u alan:PASS https://drogheda.helgen.online/api/historial\?tipo=diagnostico-campo\&serie=CAMPO-PRUEBA

Y la prueba que de verdad cuenta, desde un teléfono: abrir https://drogheda.helgen.online/formularios/diagnostico.html, elegir la unidad ⚙ PRUEBA (no cuenta), tomar una foto y enviar. Las series con PRUEBA se guardan aparte, en _pruebas/, y no ensucian el registro.


C · Ciclo normal a partir de aquí

# contenido nuevo desde el repo Drogheda (lista curada dentro del script)
./scripts/sync-docs.sh
git add -A && git commit -m "…" && git push
./scripts/deploy.sh
# y SOLO si tocaste backend/app.py:
ssh leo@git.helgen.online 'cd /srv/projects/drogheda/hbox-docs && git pull && sudo systemctl restart actas-hbox'

D · Respaldo

Todo lo que los técnicos generan son dos carpetas planas — cópialas y ya:

rsync -az leo@git.helgen.online:/srv/projects/drogheda/actas/    ~/respaldo-actas/
rsync -az leo@git.helgen.online:/srv/projects/drogheda/adjuntos/ ~/respaldo-fotos/

E · Problemas frecuentes

Síntoma Causa Arreglo
"La foto pesa demasiado" con fotos normales falta client_max_body_size paso 4
El nombre del técnico no se precarga falta X-Remote-User paso 4
"Ya existe un acta para esta serie" en diagnóstico backend viejo paso 2 (git pull + restart)
Las fotos se ven rotas en el tablero falta la carpeta adjuntos o su permiso paso 3
mkdocs build --strict falla un enlace del nav apunta a un archivo que no existe revisa mkdocs.yml
El técnico no puede entrar usuario no creado, o se usó htpasswd -c y borró a los demás paso 5
«El servicio no tiene permiso de escribir el archivo de usuarios» falta el chown/chmod del htpasswd paso 7
«Tu contraseña está guardada en un formato que no puedo verificar» esa entrada es bcrypt, no $apr1$ restablecerla desde /cuenta.html como administrador