Qué es NSAdaServer
nsadaserver es el explorador web de ficheros Adabas de Nacarsoft. Se ejecuta como un único binario Go que integra el servidor, la interfaz web y una base SQLite para la seguridad; no hay que desplegar un frontend aparte. Se conecta al núcleo Adabas mediante el cliente nativo (CGO, -tags adalnk).
- Seis vistas por fichero: tabla, formulario, JSON, DDM, ADAREP y API, más un grafo ER de relaciones.
- Datos y metadatos: el catálogo DDM se cachea en disco; la lista de ficheros y su definición se pueden consultar sin una conexión viva, y la conexión aporta el nombre físico y el número de registros.
- Crear y operar: creación de ficheros físicos con ADAFDU desde el navegador, edición y borrado de registros por ISN, vaciado de ficheros y reconciliación del catálogo.
- API REST: los mismos endpoints que usa la web, con especificación OpenAPI 3.0, Swagger y claves API con scopes, caducidad y auditoría de uso.
- Control de acceso: usuarios → grupos → roles → permisos por fichero (
read,write,delete), JWT, bcrypt, protección contra fuerza bruta y auditoría diaria. - Multi-base: varias bases Adabas en la misma instancia, con pool de conexiones y parada automática por inactividad.
- Experiencia: 6 idiomas (ES, EN, FR, DE, IT, PT), tema claro/oscuro y tamaño de fuente ajustable.
Los nombres de bases, ficheros, campos y datos de los ejemplos son ficticios.

Casos de uso
1. Consulta rápida de un registro sin herramientas de escritorio
Localizar un registro concreto (p. ej. la póliza ficticia POL-2024-00123) desde el navegador, sin instalar el cliente Adabas en el puesto.
./build/nsadaserver init /tmp/nsadaserver-demo
# → imprime la contraseña aleatoria del usuario admin; guárdala
./build/nsadaserver start /tmp/nsadaserver-demo
./build/nsadaserver status /tmp/nsadaserver-demo
# → nsadaserver is RUNNING (PID 12345) Listening: http://0.0.0.0:11010
Flujo web (http://localhost:11010): entre con admin y la contraseña que imprimió init; elija la base DEV en el panel lateral, abra el fichero en el árbol, busque por campo o por ISN y lea el registro en vista tabla, formulario o JSON.
2. Explorar la estructura DDM/FDT/ADAREP antes de programar
Revisar campos, formatos, descriptores e índices de un fichero (p. ej. el FNR ficticio 100) antes de escribir una integración o un programa Natural.
./build/nsadaserver status /tmp/nsadaserver-demo # confirmar RUNNING
Flujo web: seleccione base y fichero en el árbol; abra la vista DDM para ver la definición y sus pestañas de campos e índices; abra ADAREP para la salida real del servidor; use la vista API para obtener la llamada REST equivalente.
3. Dar al soporte acceso de solo lectura a una base
Permitir que el equipo de soporte consulte los ficheros de TEST sin tocar DEV ni poder modificar registros.
curl -s http://localhost:11010/api/health
# → {"service":"nsadaserver","status":"healthy"}
Flujo web (como admin): Administración → Grupos, Roles y Permisos; cree un rol con can_read sobre los ficheros de TEST (o * para todos) y asígnelo al grupo del usuario. El usuario inicia sesión y solo ve los ficheros permitidos; el resto de operaciones recibe 403.
4. Paginar un fichero grande con límites controlados
Recorrer un histórico ficticio de miles de registros sin saturar el servidor ni la conexión Adabas.
./build/nsadaserver stop /tmp/nsadaserver-demo
# (ajuste pagination.page_size y pagination.read_limit en /tmp/nsadaserver-demo/config.yaml)
./build/nsadaserver start /tmp/nsadaserver-demo
Flujo web: abra el fichero en vista tabla y avance por páginas; la barra de estado muestra el recuento y el uso ASO/DATA. En bases con pool, la conexión se detiene sola tras idle_timeout_minutes sin accesos.
5. Crear un fichero físico nuevo con ADAFDU
Crear un fichero para una carga nueva sin salir del navegador ni usar herramientas del núcleo.
Flujo web: pulse + en el árbol de la base; indique FNR y nombre del fichero, descripción y valores por defecto; añada los campos con nivel, tipo, longitud, descripción y marcas NU, DE, UQ, PE, GR, MU; añada superdescriptores si hacen falta. NSAdaServer genera el fichero con ADAFDU, actualiza el DDM local y lo deja visible con los permisos del rol.
6. Probar la API desde el propio panel
Consumir y depurar la API sin salir de la aplicación.
Flujo web: abra la vista API; busque el endpoint (p. ej. GET /api/db/150/files/100), rellene parámetros y cuerpo, pulse Execute Request y consulte las pestañas Response, URL y cURL. La especificación OpenAPI 3.0 está en /api/openapi.json y la interfaz Swagger en /swagger/.
7. Integrar un ERP con una clave API
Dar a una integración un acceso acotado, sin compartir la contraseña de un usuario.
Flujo web: Administración → Claves API → crear; indique nombre, caducidad en días (0 = nunca) y scopes. La clave completa solo se muestra una vez, al crearla. El ERP la envía en X-API-Key o como Authorization: Bearer <clave>; cada uso queda registrado y la clave se puede revocar o reactivar.
8. Auditar quién ha consultado o modificado un dato
Revisar operaciones y cambios de configuración para un ticket o una auditoría interna.
Flujo web: Administración → Usuarios/Grupos/Roles/Permisos y Claves API; el editor de Configuración permite revisar el config.yaml y avisa del reinicio necesario. La actividad queda en audit/ con rotación diaria y los accesos fallidos pasan por la protección contra fuerza bruta.
Interfaz



| Área | Qué hace |
|---|---|
| Login y recuperación | Autenticación por usuario y contraseña; sesión JWT; recuperación por correo con código de 6 dígitos si SMTP está configurado |
| Panel lateral / árbol | Lista las bases configuradas y sus ficheros con sus números; selector de base activa, búsqueda de ficheros y botón de creación |
| Vista tabla | Rejilla paginada con descriptor e ISN de cada registro |
| Vista formulario | Un registro por ficha, con los campos del DDM y sus grupos PE/GR/MU |
| Vista JSON | La misma información en JSON, lista para copiar o integrar |
| Vista DDM | Definición completa: nivel, tipo, longitud, descripción, campos relacionados e índices |
| Vista ADAREP | Salida real del comando ADAREP del servidor |
| Vista API | Llamada REST equivalente, con respuesta, URL y cURL |
| Grafo ER | Relaciones entre ficheros a partir de los campos del DDM, con filtro y exportación a PNG |
| Búsqueda | Por campo (con operadores) o por ISN, con orden por descriptor y paginación |
| Administración | Usuarios, grupos, roles, permisos por fichero y claves API |
| Configuración | Editor de config.yaml con las bases declaradas y aviso de reinicio |
| Perfil | Idioma, tema y cambio de contraseña |
| Barra de estado | Recuento de registros, uso ASO/DATA y estado de la base o del pool |
Las seis vistas de un fichero
| Vista | Qué muestra |
|---|---|
| Tabla | El fichero como rejilla, con el descriptor y el ISN de cada registro |
| Formulario | Un registro por ficha, con los campos del DDM y sus grupos PE/GR/MU |
| JSON | La misma información en JSON, lista para copiar o integrar |
| DDM | Definición completa: nivel, tipo, longitud, descripción, campos relacionados e índices |
| ADAREP | La salida real del comando ADAREP del servidor |
| API | La llamada REST equivalente, con su respuesta, su URL y su cURL |
Referencia
Requisitos
| Requisito | Detalle |
|---|---|
| Sistema | Linux (probado en RHEL 8/9 y Debian) |
| Cliente Adabas | Librerías nativas de Adabas para la conectividad (CGO, -tags adalnk) |
| Puerto | 11010 por defecto, configurable |
| Proxy inverso | Recomendado en producción, con HTTPS |
| Navegador | Navegador moderno; no requiere instalar nada en el puesto |
Comandos CLI
| Comando | Descripción |
|---|---|
init <dir> | Crea un entorno nuevo: config.yaml, db/security.db, logs/, audit/ y certs/. No sobrescribe un directorio existente. Genera el secreto JWT y la clave de Swagger, e imprime la contraseña aleatoria de admin |
start [dir] | Arranca el servidor como daemon (por defecto, el directorio actual). Guarda .nsadaserver.pid junto al config.yaml |
stop [dir] | Detiene el daemon; intenta un apagado ordenado y fuerza la salida si no termina |
restart [dir] | Reinicia el daemon: lo para si está arrancado y lo vuelve a arrancar |
status [dir] | Muestra PID, fichero de configuración, URL de escucha, uptime y memoria; sale con 0 si está arrancado y 1 si no |
license [dir] | Muestra el estado de la licencia y el fingerprint de la máquina; sale con 1 si la licencia no es válida |
version (--version, -v, -version) | Muestra versión, build, fecha, commit y estado de la licencia |
run | Servidor en primer plano para depuración (interno; no aparece en --help) |
--config <dir> | Subflag de los comandos: indica el directorio del entorno. También se acepta como argumento posicional |
-server / -stop | Alias obsoletos de start y stop; avisan y siguen funcionando |
--configno funciona como primer argumento:nsadaserver --config xrespondeUnknown command. Usensadaserver start <dir>onsadaserver start --config <dir>.La contraseña de
adminno es fija:initgenera una aleatoria y la muestra una sola vez. Cópiela antes de cerrar la terminal y cámbiela en el primer acceso.
Configuración principal (config.yaml)
| Clave | Descripción |
|---|---|
server.host / server.port | Interfaz y puerto web (por defecto 0.0.0.0:11010) |
server.tls_cert_file / tls_key_file | TLS opcional en el propio binario; vacíos si el TLS lo termina el proxy |
server.base_path | Prefijo externo cuando se publica detrás de un proxy (p. ej. /api/proxy/ABROWSE). Admite varios separados por comas; vacío = raíz |
database.path | SQLite de seguridad (./db/security.db): usuarios, grupos, roles, permisos y claves API |
security.jwt_secret | Clave JWT (mínimo 32 caracteres) — cámbiela en producción |
security.token_expiry_hours | Caducidad del token (24) |
security.password_reset_code_ttl_minutes | Validez del código de reseteo (10) |
adabas.dbid / config_file / files | Configuración de una base única (modo legacy); connect solo se admite dentro de adabas.databases.<nombre> |
adabas.databases.<nombre> | Bases declaradas: dbid, config_file, connect y files (filtro de FNR, p. ej. "(100-120)") |
adabas.databases.<nombre>.pool | Pool de conexiones: size_acc, size_upd, etid o etid_prefix, idle_timeout_minutes |
smtp.* | Correo para reseteo de contraseña (host, port, username, password, from, use_tls) |
pagination.page_size / read_limit | Tamaño de página y tope de lectura. El ejemplo usa 80 y 10000; si se omiten, los valores por defecto son 20 y 1000 |
config.separator_decimal / daemon / logdir / logdays | Separador decimal, modo daemon, directorio de logs y retención (7 días por defecto) |
audit_dir | Directorio de auditoría (./audit) |
swagger.enabled / api_key / title / version / description | Documentación REST: activación, clave del explorador y metadatos OpenAPI |
Notas:
- Si
adabas.databasesestá vacío, se usa la configuración legacy deadabas.dbid/config_file. - Un
poolausente mantiene el modo de conexión compartida tradicional. En modo pool,size_accysize_updno positivos caen a5y2;idle_timeout_minutes: 0significa que nunca se detiene. etidyetid_prefixson excluyentes. El prefijo aleatorio debe tener exactamente 3 caracteres alfanuméricos.fileslimita los FNR visibles de esa base; es independiente de los permisos RBAC por fichero.
Catálogo DDM
Cada base declara su catálogo en config_file: un JSON con la estructura de los ficheros. El formato es:
{
"library": "SYSTEM",
"files": [
{
"metadata": {
"source_file": "DEMO-CLI.NSD",
"ddm_name": "DEMO-CLIENTES",
"db": "000",
"file_number": 100,
"record_type": "ADABAS",
"total_fields": 21,
"total_length": 654,
"description": "Datos de clientes de demostración"
},
"fields": [
{
"level": 1,
"name": "AA",
"field_name": "COD-CLIENTE",
"format": "A",
"length": "8",
"descriptor": "D",
"description": "Código de cliente"
}
]
}
]
}
El catálogo se cachea en disco: la lista de ficheros y su definición se muestran aunque la conexión Adabas esté caída; la conexión solo aporta la información física. POST /api/db/{dbid}/reconcile vuelve a sincronizar el catálogo con el núcleo.
Permisos y claves API
usuarios → grupos → roles → permisos por fichero (can_read / can_write / can_delete)
| Aspecto | Detalle |
|---|---|
| Unidad de permiso | El fichero, por nombre DDM o * para todos |
| Operaciones | can_read, can_write, can_delete |
| Efecto | Las listas de ficheros y los registros se filtran por permisos; una operación sin permiso devuelve 403 |
| Comodín | * concede el permiso a todos los ficheros del rol |
| Claves API | Nombre, caducidad opcional, scopes, revocación/reactivación y auditoría de uso. La clave completa solo se muestra una vez |
| Sesión de usuario | JWT HS256; contraseñas con bcrypt; bloqueo tras intentos fallidos |
API REST
La especificación OpenAPI 3.0 se sirve en /api/openapi.json y la interfaz Swagger en /swagger/. El API Explorer de la web usa la misma especificación y añade el token de la sesión.
Autenticación:
- JWT:
Authorization: Bearer <token>trasPOST /api/auth/login. - Clave API:
X-API-Key: <clave>oAuthorization: Bearer <clave>. - El token también se acepta como
?token=en URLs compartibles del explorador.
| Método y ruta | Descripción |
|---|---|
GET /api/health | Estado del servicio |
GET /api/version / GET /api/license | Versión/build y estado de la licencia |
GET /api/settings / GET /api/languages | Configuración de paginación/idiomas |
POST /api/auth/login / logout | Inicio y cierre de sesión |
POST /api/auth/forgot-password / reset-password | Recuperación con código de 6 dígitos |
GET /api/databases | Bases con sus ficheros, estado y pool |
GET /api/databases/{database}/ping | Estado de una base |
POST /api/databases/{database}/reconnect / stop | Reconectar o detener una base |
GET /api/db/{dbid}/files / files-tree | Ficheros y árbol de una base |
GET /api/db/{dbid}/files/{file} | Registros paginados (page, page_size, last_isn) |
POST /api/db/{dbid}/files/{file}/search | Búsqueda con expresiones Adabas |
GET /api/db/{dbid}/files/{file}/fdt / fdt-full / definition | FDT del catálogo y definición viva |
GET /api/db/{dbid}/files/{file}/adarep | Salida de ADAREP |
GET /api/db/{dbid}/files/{file}/fields / count / stats | Campos, total y estadísticas |
POST /api/db/{dbid}/files | Crear un fichero físico (ADAFDU) |
POST /api/db/{dbid}/reconcile | Reconciliar el catálogo DDM |
POST /api/db/{dbid}/files/{file}/empty | Vaciar los registros de un fichero |
PUT/PATCH /api/db/{dbid}/files/{file} | Actualizar un registro por ISN |
DELETE /api/db/{dbid}/files/{file} | Borrar un registro por ISN |
DELETE /api/db/{dbid}/files/{file}/physical | Dar de baja el fichero físico |
GET/POST/PUT/DELETE /api/admin/users|groups|roles|permissions | Administración RBAC |
GET/POST /api/apikeys y subrutas /:id/{revoke,reactivate,scopes,name,audit} | Claves API, scopes y auditoría |
# Autenticación (use la contraseña que imprimió init)
TOKEN=$(curl -s -X POST http://localhost:11010/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"<contraseña-de-init>"}' \
| sed 's/.*"token":"\([^"]*\)".*/\1/')
# Registros de un fichero (DBID 150, FNR 100)
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:11010/api/db/150/files/100?page=1&page_size=40"
# Búsqueda por expresión Adabas
curl -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-X POST http://localhost:11010/api/db/150/files/100/search \
-d '{"query":"COD-CLIENTE=DEMO*","limit":20}'
Seguridad y auditoría
- Contraseñas de usuario con bcrypt y sesión JWT HS256.
- Recuperación por correo con enlace y código de 6 dígitos, con caducidad configurable.
- Protección contra fuerza bruta y registro de intentos de acceso.
- Auditoría por operación (usuario, acción y resultado) con rotación diaria en
audit/. config.yamlse guarda con permisos0600cuando se edita desde la aplicación.- Trial de 30 días; licencia firmada por máquina en
$NS_HOME/licenses/nsadaserver.key.
Ejemplos comentados
# 1. Entorno nuevo y arranque (el directorio no debe existir)
./build/nsadaserver init /tmp/nsadaserver-demo
./build/nsadaserver start /tmp/nsadaserver-demo
./build/nsadaserver status /tmp/nsadaserver-demo
# 2. Dos entornos con el mismo binario
./build/nsadaserver init /tmp/nsadaserver-prod && ./build/nsadaserver start /tmp/nsadaserver-prod
./build/nsadaserver init /tmp/nsadaserver-dev && ./build/nsadaserver start /tmp/nsadaserver-dev
./build/nsadaserver status /tmp/nsadaserver-prod
./build/nsadaserver stop /tmp/nsadaserver-dev
# 3. Reinicio tras cambiar config.yaml
./build/nsadaserver restart /tmp/nsadaserver-demo
# 4. Verificación: salud, SPA, versión y licencia
curl -s http://localhost:11010/api/health
curl -s http://localhost:11010/ -o /dev/null -w '%{http_code}\n'
./build/nsadaserver version
./build/nsadaserver license /tmp/nsadaserver-demo
# 5. Alias obsoleto (funciona con aviso)
./build/nsadaserver -server /tmp/nsadaserver-demo
# API con clave (sin sesión de usuario)
curl -H "X-API-Key: $NSADASERVER_API_KEY" \
"http://localhost:11010/api/db/150/files/100?page=1&page_size=40"
# Estado de una base concreta
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:11010/api/databases/DEV/ping"
Preguntas frecuentes
¿Cuál es la contraseña inicial de admin? No hay una contraseña fija. init genera una aleatoria y la imprime una sola vez; guárdala y cámbiala en el primer acceso. Si se pierde, use la recuperación por correo (si SMTP está configurado) o cree un entorno nuevo: init no sobrescribe directorios existentes.
¿Dónde va la licencia? En $NS_HOME/licenses/nsadaserver.key; si NS_HOME no está definido, en /opt/ns/licenses/nsadaserver.key. Sin licencia hay trial de 30 días y nsadaserver license muestra el fingerprint de la máquina.
¿No conecta con Adabas? Revise adabas.databases en config.yaml (dbid, connect, config_file y files) y el acceso de red al núcleo. GET /api/databases/{database}/ping ayuda a aislar el problema. En el servidor, compruebe ldd build/nsadaserver y LD_LIBRARY_PATH si falta la librería nativa.
¿Por qué no veo ficheros? Puede que el catálogo DDM no esté cargado o que el rol no tenga permiso sobre esos ficheros. Revise el config_file, que el JSON tenga files con su ddm_name, y los permisos can_read del rol (o el comodín *).
¿Puedo consultar sin conexión Adabas? La lista de ficheros y su DDM se leen de la caché local; para ver registros, ADAREP o estadísticas hace falta una conexión viva.
¿Cómo accedo a la API? Desde la vista API de la web, con /api/openapi.json o con /swagger/. Para integraciones, cree una clave API en Administración → Claves API y envíela en X-API-Key.
¿Qué puerto usa? 11010 por defecto. Cámbielo en server.port; si está ocupado, compruebe con lsof -i :11010.
¿Qué idiomas y temas hay? ES, EN, FR, DE, IT y PT; tema claro/oscuro y tamaño de fuente ajustable. Los manuales de esta web están en español e inglés, con fallback al inglés para el resto.
¿Los datos de los ejemplos son reales? No: bases, ficheros, campos, registros y credenciales de los ejemplos son ficticios.