Panel administrativo: operación en producción
July 16, 2026 · View on GitHub
Para una actualización habitual desde una versión anterior, empieza por la guía paso a paso para instalaciones Docker existentes. Este documento conserva la referencia operativa completa y el procedimiento de rollback.
La equivalencia entre el panel, .env y los comandos disponibles está en Administración desde el servidor.
Modelo de activación
- Una instalación nueva, sin
data/incidencias.sqlite, creadata/.admin-enabledantes de inicializar la base y activa el panel por defecto. - Una instalación existente que actualiza desde una versión anterior mantiene
/admindesactivado aunque las migraciones sean compatibles. La API y la web pública siguen funcionando y no se exigeSESSION_SECRETmientras el panel permanezca desactivado. ADMIN_ENABLED=true|falsepermite una sobrescritura explícita para entornos gestionados, pero el mecanismo recomendado en Docker es el marcador persistente.
Instalación Docker nueva
Después de copiar .env.sample a .env y revisar BASE_URL y TRUST_PROXY, ejecuta:
./scripts/install.sh
El asistente genera SESSION_SECRET y una contraseña temporal, ejecuta el bootstrap en un contenedor efímero, limpia la credencial de .env y arranca el servicio definitivo sin ella. La contraseña se muestra una sola vez en la terminal y debe cambiarse al entrar en /admin; no hace falta editar de nuevo .env ni recrear el servicio.
scripts/install.sh guarda data/.installation-complete al terminar y rechaza una segunda ejecución cuando encuentra ese marcador. Un intento interrumpido antes de completarse puede ejecutarse de nuevo. Para versiones posteriores usa:
./scripts/upgrade.sh
El upgrade solo acepta avances rápidos sobre main, rechaza cambios locales versionados, crea un backup antes de modificar el servicio y verifica su salud al terminar. Una ejecución interrumpida deja un marcador de reintento para que el mismo comando vuelva a desplegar la revisión actual.
El canal estable, recomendado y predeterminado, compara la versión incluida en la imagen con la última GitHub Release publicada. Solo admite etiquetas vMAJOR.MINOR.PATCH; upgrade.sh instala esa etiqueta exacta, evitando commits posteriores. El título y la descripción de la Release se muestran en el aviso, así que no publiques la Release hasta que la entrega esté lista para producción.
El canal beta es opt-in desde /admin/updates. Compara el SHA incluido al construir la imagen con la punta de la rama y avisa ante cualquier cambio; el upgrade instala esa rama mediante avance rápido. La selección se guarda en SQLite y se refleja en data/update-channel para que el script de servidor respete la misma preferencia.
La sección Actualizaciones aparece como entrada independiente del menú, debajo de Auditoría. El administrador puede usar Comprobar ahora para invalidar la caché y consultar inmediatamente el canal guardado. La acción está autenticada y protegida mediante CSRF; no ejecuta el upgrade.
Activar una instalación Docker existente
Desde la raíz del repositorio actualizado ejecuta:
./scripts/enable_admin.sh
El servidor anfitrión solo necesita Docker y Docker Compose v2. Las tareas auxiliares
de Node se ejecutan en un contenedor temporal node:22-slim; no es necesario instalar
Node ni npm en el servidor.
El asistente:
- Detiene el servicio para obtener una copia coherente.
- Guarda SQLite,
uploads/y.envenbackups/admin-enable-FECHA/. - Genera y guarda un
SESSION_SECRETrobusto si falta. - Crea el marcador persistente
data/.admin-enabled. - Construye la imagen y ejecuta migraciones más bootstrap en un contenedor efímero.
- Arranca el contenedor definitivo sin la contraseña bootstrap en su entorno.
- Muestra una sola vez en la terminal la URL, usuario y contraseña temporal si creó el primer administrador.
La contraseña nunca se presenta en /admin sin autenticación: hacerlo permitiría que el primer visitante de una instancia pública reclamase el panel.
Configuración pública administrable
La pantalla /admin/configuracion persiste identidad, imágenes de marca, paleta, textos y enlaces públicos, área geográfica, búsqueda, proximidad, umbrales de resolución, CAPTCHA, analítica y reporte por WhatsApp en la tabla app_settings. Estos valores prevalecen sobre sus equivalentes de .env y se sirven en runtime, por lo que basta recargar la web pública después de guardar.
Las rutas de logo y favicon deben apuntar a recursos públicos existentes, por ejemplo /img/custom/logo.png o /uploads/branding/logo.png. No se aceptan rutas relativas ni segmentos ...
No se muestran ni modifican desde el panel SESSION_SECRET, credenciales bootstrap, proxy, CORS, SQLite ni rutas internas. Esos valores requieren acceso al entorno de despliegue. La clave secreta de Friendly Captcha puede actualizarse desde el panel, pero nunca se vuelve a mostrar ni se incluye en /api/config o en la auditoría.
Preparacion
- Deten las escrituras o activa una ventana de mantenimiento.
- Copia
data/incidencias.sqlite,uploads/y el.envvigente a un destino fuera del servidor. - Verifica la copia con
sqlite3 backup.sqlite "PRAGMA integrity_check;"; debe responderok. - Restringe
.env, SQLite y los backups al usuario del servicio (chmod 600 .env data/incidencias.sqlitey directorios de backup con modo700). El asistente de activación aplica unaumaskrestrictiva. - En una instalación nueva,
scripts/install.shgeneraSESSION_SECRET;enable_admin.shhace lo mismo al activar una instalación existente. En despliegues gestionados, genera un valor distinto por entorno con al menos 32 caracteres. No reutilices secretos entre entornos. - Los asistentes generan una contraseña bootstrap segura y la pasan únicamente al contenedor efímero. En un despliegue manual,
ADMIN_BOOTSTRAP_PASSWORDdebe tener al menos 12 caracteres y un máximo de 72 bytes, y no debe permanecer en el entorno del servicio definitivo. - Configura
BASE_URLcon el origen HTTPS publico. ManténTRUST_PROXY=falsesi Node recibe trafico directo; usaTRUST_PROXY=1solo detras de un unico proxy de confianza.
Proxy inverso y cookies seguras
Cuando Nginx termina HTTPS, todas las rutas que llegan a Node deben conservar Host, X-Forwarded-For y X-Forwarded-Proto. Esto incluye ubicaciones con nombre como location @app: si el fallback pierde X-Forwarded-Proto, Express considera que la petición es HTTP y no entrega la cookie administrativa Secure.
Usa el patrón genérico de examples/nginx.conf.example, valida siempre con nginx -t y guarda backups fuera de sites-enabled. No sobrescribas Origin ni publiques un Access-Control-Allow-Origin "*" global; la aplicación gestiona su propia política de orígenes.
Migracion y despliegue
Prueba primero sobre una copia de la base:
SQLITE_DB_PATH=/ruta/a/copia.sqlite NODE_ENV=test npm run migrate
sqlite3 /ruta/a/copia.sqlite "PRAGMA integrity_check; PRAGMA foreign_key_check;"
El runner registra cada fichero en schema_migrations; repetir npm run migrate es seguro. El arranque de producción ejecuta las migraciones antes de abrir el servidor. Ejecutar migraciones no activa el panel en una instalación existente: la activación depende del marcador.
Checklist de despliegue:
npm ci,npm audit,npm run lint,npm test -- --runInBandynpm run buildterminan correctamente.- La copia de seguridad está fechada, accesible y verificada.
SESSION_SECRET,BASE_URLy la politica de proxy son correctos.docker compose configno muestra errores de variables.docker compose up -d --buildcrea un contenedor nuevo ydocker compose pslo marca como saludable./api/incidencias/ultima-actualizacion, la web publica y/admin/loginresponden.- En HTTPS,
/admin/loginentrega una cookie conHttpOnly,SecureySameSite=Strict. - Se validan login, cambio de clave, logout, filtros, ficha, acciones masivas, categorias, administradores, mantenimiento y auditoria.
- Se confirma que la contraseña bootstrap no aparece en logs.
- La imagen no contiene
.envni.npmrc; ambos se excluyen del contexto y la configuración llega en runtime mediante Compose.
Verificacion posterior
docker compose ps
docker compose logs --tail=200 basuracero-app
curl -fsS https://TU_DOMINIO/api/incidencias/ultima-actualizacion
Comprueba también PRAGMA integrity_check, el recuento de incidencias/categorias y una imagen ya existente. Conserva el backup hasta cerrar la ventana de observacion.
Rollback
- Deten el contenedor para evitar nuevas escrituras.
- Conserva una copia de la base fallida y de los logs para diagnostico.
- Restaura la imagen o revision anterior de la aplicacion.
- Restaura conjuntamente la copia de
incidencias.sqliteyuploads/; no mezcles una base restaurada con un directorio de imagenes posterior. - Recupera el
.envanterior, manteniendo secretos fuera del repositorio. - Arranca la version anterior y repite salud, integridad, recuentos, web publica y login.
No intentes revertir migraciones con SQL manual sobre la base real. El rollback soportado es restaurar el backup coherente de base, imagenes y configuracion.