# DOC-OPS-006 · Runbook de Instalación y Operación — face-match-node

**Producto:** Microservicio face-match-node · Fidelitas S.A.  
**Versión:** 1.2  
**Fecha:** 2026-11-10  
**Audiencia:** Developer Junior  
**Clasificación:** CONFIDENCIAL — USO INTERNO

---

## Índice

1. Qué es este servicio y qué hace
2. Prerequisitos en la estación de desarrollo
3. Clonar el repositorio y preparar el código local
4. Compilar el proyecto en la estación de desarrollo
5. Empaquetar y transferir al servidor
6. Prerequisitos en el servidor Ubuntu 24.04
7. Desplegar el servicio en el servidor
8. Configurar Apache como reverse proxy
9. Verificar que todo funciona (health check + test de autenticación)
10. Medir performance y consultar métricas
11. Recuperar la base de datos SQLite ante un fallo
12. Comandos de operación diaria (referencia rápida)

---

## 1. Qué es este servicio y qué hace

El servicio `face-match-node` es un **microservicio Node.js** que actúa como proxy seguro entre los consumidores de la API de Fidelitas y la API de reconocimiento facial de RENAPER (Registro Nacional de las Personas de Argentina).

**Flujo completo de un request:**

```
Consumidor (Postman / app cliente)
        │  POST /v3/face-match/
        │  apikey + selfie_image (base64) + nationalid + gender
        ▼
Apache 443 (HTTPS — TLS termina acá)
        │  ProxyPass → localhost:3100
        ▼
face-match-node (puerto 3100 interno)
        │  1. Valida apikey y IP
        │  2. Obtiene token RENAPER (cache o nuevo)
        │  3. Envía imagen → recibe TCN
        │  4. Consulta resultado con TCN (polling)
        │  5. Guarda archivos + SQLite
        ▼
Respuesta JSON unificada al consumidor
```

**Qué persiste por cada operación:**

| Archivo/Registro | Contenido |
|---|---|
| `storage/TCN-xxx.txt` | Imagen selfie en base64 |
| `storage/TCN-xxx_step1.json` | Respuesta RENAPER paso 1 (TCN) |
| `storage/TCN-xxx_step2.json` | Respuesta RENAPER paso 2 (resultado) |
| `data/fide-facematch.db` | SQLite: todos los campos + timings en ms |

---

## 2. Prerequisitos en la estación de desarrollo

Antes de tocar código necesitás tener instalado en tu máquina Fedora 44:

| Herramienta | Versión mínima | Verificación |
|---|---|---|
| Node.js | 26.x LTS | `node --version` → debe mostrar `v26.x.x` |
| npm | 10.x | `npm --version` → debe mostrar `10.x.x` |
| Podman | cualquiera | `podman --version` |
| git | cualquiera | `git --version` |
| ssh | cualquiera | `ssh -V` |
| rsync | cualquiera | `rsync --version` |

### Instalar Node.js 26 en Fedora 44

```bash
# Agregar repositorio oficial de NodeSource
curl -fsSL https://rpm.nodesource.com/setup_26.x | sudo bash -

# Instalar Node.js
sudo dnf install -y nodejs

# Verificar
node --version   # debe mostrar v26.x.x
npm --version    # debe mostrar 10.x.x
```

> Podman ya viene instalado en Fedora 44 Golden ISO. Si falta: `sudo dnf install -y podman`

---

## 3. Clonar el repositorio y preparar el código local

### 3.1 Actualizar el repo

```bash
cd ~/Downloads/fide-workspace
git pull origin master
```

El código del microservicio vive en:

```
fide-workspace/face-match-node/
```

### 3.2 Crear el archivo de variables de entorno

El archivo `.env` **nunca está en git**. Hay que crearlo manualmente:

```bash
cd face-match-node
cp .env.example .env
nano .env
```

**Qué completar:**

```bash
PORT=3100
NODE_ENV=development

APIKEY_MASTER=completar_con_el_valor_provisto_por_el_responsable

# En desarrollo, dejar solo localhost
AUTHORIZED_IPS=["127.0.0.1","::1"]

# Credenciales RENAPER (pedirlas al responsable)
RENAPER_USERNAME=tu_usuario_renaper
RENAPER_PASSWORD=tu_password_renaper
```

> **Importante:** Nunca commitees el `.env`. Si lo hacés por accidente, avisá inmediatamente al responsable de seguridad.

---

## 4. Compilar el proyecto en la estación de desarrollo

**Regla Fidelitas (§19 CONTEXTO):** Nada se compila en los servidores. El binario nativo de `better-sqlite3` se compila en la estación de desarrollo dentro de un contenedor Podman que replica exactamente el sistema operativo del servidor de producción (Ubuntu 24.04). El resultado se transfiere compilado y listo para correr.

### Por qué es importante compilar en el mismo OS que el servidor

`better-sqlite3` contiene código C++ que se compila en un binario específico para el sistema operativo y la versión de Node.js del destino. Si compilás en Fedora 44 y ejecutás en Ubuntu 24.04, el binario no funciona. La solución es compilar dentro de un contenedor `ubuntu:24.04` que ya tiene las mismas librerías que el servidor.

### 4.1 Crear el script de compilación

```bash
cd ~/Downloads/fide-workspace/face-match-node
```

Crear el archivo `compile.sh` en esa carpeta:

```bash
#!/bin/bash
# compile.sh — compila el proyecto dentro de un contenedor Ubuntu 24.04
# El resultado es un node_modules compatible con el servidor de producción

set -e  # Detener ante cualquier error

PROYECTO_DIR="$(cd "$(dirname "$0")" && pwd)"
IMAGE="docker.io/node:26-bookworm-slim"

echo "==> Compilando face-match-node para Ubuntu 24.04..."
echo "==> Directorio del proyecto: $PROYECTO_DIR"

# Correr npm install dentro de un contenedor Ubuntu 24.04
# -v monta la carpeta del proyecto dentro del contenedor
# --rm borra el contenedor al terminar (efímero)
# -w establece el directorio de trabajo dentro del contenedor
podman run --rm \
  -v "$PROYECTO_DIR":/app:Z \
  -w /app \
  "$IMAGE" \
  sh -c "npm install --omit=dev && echo '==> Compilación exitosa'"

echo "==> node_modules listo para transferir al servidor."
```

> **Nota sobre la imagen:** `node:26-bookworm-slim` es Node 26 sobre Debian Bookworm (base de Ubuntu 24.04). Los binarios nativos son 100% compatibles con Ubuntu 24.04.

```bash
# Dar permisos de ejecución
chmod +x compile.sh
```

### 4.2 Ejecutar la compilación

```bash
./compile.sh
```

La primera vez descarga la imagen (≈ 200 MB). Las siguientes veces usa el cache de Podman y tarda menos de un minuto.

Al terminar verás: `==> Compilación exitosa`

### 4.3 Verificar que el binario nativo compiló correctamente

```bash
# Debe existir este archivo .node (binario nativo de SQLite)
ls node_modules/better-sqlite3/prebuilds/linux-x64.node
```

Si existe, la compilación fue exitosa.

### 4.4 Verificar que el servidor arranca en modo desarrollo

```bash
# Arrancar localmente (en Fedora — solo para verificar la lógica, no los binarios)
# Instalar dependencias nativas para Fedora también:
npm install

# Arrancar
node src/server.js
```

Respuesta esperada:

```json
{"level":"info","time":"...","msg":"Server listening at http://127.0.0.1:3100"}
```

Verificar health check en otra terminal:

```bash
curl http://localhost:3100/health
# {"status":"ok","service":"fide-facematch-api","uptime":5.2}
```

Verificar que rechaza apikey incorrecta:

```bash
curl -X POST http://localhost:3100/v3/face-match/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "apikey=WRONG&selfie_image=abc&nationalid=12345678&gender=M"
# {"Status":"ERROR","Message":"API key inválida o no provista.",...}
```

Detener con `Ctrl+C`.

---

## 5. Empaquetar y transferir al servidor

Una vez que `compile.sh` fue exitoso, tenés en tu máquina el `node_modules` compilado para Ubuntu 24.04. Ahora hay que transferirlo junto con el código fuente.

### 5.1 Variables a conocer antes de ejecutar

Reemplazá estos valores con los reales:

```
SERVIDOR_IP   = IP del servidor Ubuntu (por ejemplo: 10.10.30.50)
USUARIO       = tu usuario FreeIPA en el servidor (por ejemplo: aburgol)
DESTINO       = /var/www/html/apibatch
```

### 5.2 Crear la carpeta destino en el servidor

```bash
# Conectarse al servidor
ssh aburgol@10.10.30.50

# Crear la carpeta del servicio
sudo mkdir -p /var/www/html/apibatch

# Dar permisos a tu usuario para escribir
sudo chown aburgol:aburgol /var/www/html/apibatch

# Salir
exit
```

### 5.3 Transferir el código compilado con rsync

Desde tu máquina local:

```bash
cd ~/Downloads/fide-workspace/face-match-node

# rsync: transfiere solo lo que cambió
# node_modules SÍ se transfiere — ya está compilado para Ubuntu 24.04
# El punto final (.) indica "transferir el contenido de este directorio"
rsync -avz --progress \
  --exclude='.env' \
  --exclude='storage/' \
  --exclude='data/' \
  --exclude='logs/' \
  . \
  aburgol@10.10.30.50:/var/www/html/apibatch/
```

**Qué hace cada opción de rsync:**
- `-a` → modo archive: preserva permisos, fechas y links simbólicos
- `-v` → verbose: muestra qué archivos se están transfiriendo
- `-z` → comprime durante la transferencia (más rápido en redes lentas)
- `--progress` → muestra el progreso en tiempo real
- `--exclude` → no transfiere esas carpetas (`.env` nunca viaja; `storage/` y `data/` se crean en el servidor)

> **Diferencia clave con el enfoque incorrecto:** `node_modules/` **sí** se transfiere porque ya está compilado para Ubuntu 24.04. El servidor NO necesita compilar nada.

---

## 6. Prerequisitos en el servidor Ubuntu 24.04

El servidor **no necesita compiladores ni toolchains** — el código llega compilado desde la estación de desarrollo. Los prerequisitos son mínimos.

Conectarse al servidor:

```bash
ssh aburgol@10.10.30.50
```

### 6.1 Actualizar el sistema operativo

```bash
# Actualizar la lista de paquetes disponibles
sudo apt-get update

# Aplicar actualizaciones de seguridad
sudo apt-get upgrade -y
```

### 6.2 Instalar Node.js 26 LTS

Node.js es necesario para **ejecutar** el código (no para compilarlo — eso ya se hizo en dev).

```bash
# Repositorio oficial de NodeSource
curl -fsSL https://deb.nodesource.com/setup_26.x | sudo -E bash -

# Instalar Node.js
sudo apt-get install -y nodejs

# Verificar — debe coincidir exactamente con la versión usada para compilar
node --version    # debe mostrar v26.x.x
```

> **Importante:** la versión de Node.js en el servidor debe ser la misma rama ((26.x)) que se usó en el contenedor de compilación. Si son diferentes, los binarios nativos pueden fallar.

### 6.3 Instalar PM2 (gestor de procesos)

PM2 mantiene el servicio corriendo en background, lo reinicia si se cae, y lo arranca automáticamente cuando el servidor se reinicia.

```bash
# Instalar PM2 globalmente
sudo npm install -g pm2

# Verificar
pm2 --version
```

### 6.4 Instalar Apache y módulos de proxy

```bash
# Instalar Apache
sudo apt-get install -y apache2

# Habilitar módulos necesarios para reverse proxy
sudo a2enmod proxy         # permite a Apache reenviar requests a otro servidor
sudo a2enmod proxy_http    # soporte específico para HTTP en el proxy
sudo a2enmod headers       # permite manipular headers HTTP
sudo a2enmod ssl           # soporte para HTTPS

# Reiniciar Apache para cargar los módulos
sudo systemctl restart apache2

# Verificar que está corriendo
sudo systemctl status apache2
# Debe mostrar: Active: active (running)
```

### 6.5 Crear directorios del servicio

```bash
# Crear carpetas que rsync excluyó
mkdir -p /var/www/html/apibatch/storage
mkdir -p /var/www/html/apibatch/data
mkdir -p /var/www/html/apibatch/logs

# Verificar la estructura
ls -la /var/www/html/apibatch/
```

---

## 7. Desplegar el servicio en el servidor

### 7.1 Crear el archivo .env en el servidor

```bash
cp /var/www/html/apibatch/.env.example /var/www/html/apibatch/.env
nano /var/www/html/apibatch/.env
```

**Valores para producción:**

```bash
PORT=3100
NODE_ENV=production


APIKEY_MASTER=completar_con_el_valor_provisto_por_el_responsable

# IPs autorizadas en producción (las IPs reales de los sistemas que van a consultar)
AUTHORIZED_IPS=["10.10.20.5","10.10.30.10"]

# Credenciales RENAPER de producción
RENAPER_USERNAME=usuario_produccion
RENAPER_PASSWORD=password_produccion

# URLs RENAPER (ya están en .env.example, verificar que sean correctas)
RENAPER_TOKEN_URL=https://apirenaper.idear.gov.ar/CHUTROFINAL/API_ABIS/Autorizacion/token.php
RENAPER_TCN_URL=https://apirenaper.idear.gov.ar/CHUTROFINAL/API_ABIS/apiInline_v3.php
RENAPER_RESULT_URL=https://apirenaper.idear.gov.ar/CHUTROFINAL/API_ABIS/resultadoTCN.php

STORAGE_DIR=/var/www/html/apibatch/storage
DB_PATH=/var/www/html/apibatch/data/fide-facematch.db

TCN_MAX_RETRIES=5
TCN_RETRY_DELAY_MS=500
```

### 7.2 Verificar arranque manual

```bash
node /var/www/html/apibatch/src/server.js
```

Si arranca sin errores, detener con `Ctrl+C`. Los errores de configuración se ven acá antes de usar PM2.

### 7.3 Arrancar con PM2

```bash
cd /var/www/html/apibatch
pm2 start ecosystem.config.js --env production

# Ver el estado
pm2 status

# Ver los logs en tiempo real
pm2 logs fide-facematch
```

Deberías ver una fila por cada CPU core del servidor, todas con status `online`.

### 7.4 Configurar arranque automático

```bash
# Generar el script de startup para systemd
pm2 startup systemd -u $USER --hp $HOME

# El comando anterior va a imprimir un comando con sudo — COPIARLO Y EJECUTARLO
# Ejemplo (el tuyo puede ser diferente):
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u aburgol --hp /home/aburgol

# Guardar la lista de procesos para restaurar al reiniciar
pm2 save
```

### 7.5 Flujo de actualización (para próximos deploys)

Cuando hay cambios en el código:

```bash
# En la estación de desarrollo:
cd ~/Downloads/fide-workspace/face-match-node

# 1. Si cambió package.json, recompilar
./compile.sh

# 2. Transferir (node_modules incluido si cambió, excluido si no)
rsync -avz --progress --exclude='.env' --exclude='storage/' --exclude='data/' --exclude='logs/' \
  . aburgol@10.10.30.50:/var/www/html/apibatch/

# En el servidor:
# 3. Reload sin downtime (no corta conexiones activas)
pm2 reload fide-facematch
```

---

## 8. Configurar Apache como reverse proxy

Apache ya tiene HTTPS configurado con el certificado de Fidelitas. Solo hay que agregar la directiva de proxy para redirigir `/v3/face-match/` al servicio Node.js interno.

### 8.1 Encontrar el VirtualHost correcto

```bash
ls /etc/apache2/sites-enabled/
sudo cat /etc/apache2/sites-enabled/fide-api.conf
```

### 8.2 Editar el VirtualHost 443

```bash
sudo nano /etc/apache2/sites-enabled/NOMBRE.conf
```

Agregar **dentro** del bloque `<VirtualHost *:443>`, antes del `</VirtualHost>` de cierre:

```apache
# ============================================================
# face-match-node — reverse proxy al microservicio Node.js
# El servicio escucha en 127.0.0.1:3100 (solo localhost)
# ============================================================

ProxyPreserveHost On

# Pasar el IP real del cliente al servicio Node.js
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader set X-Real-IP "%{REMOTE_ADDR}s"

# Redirigir /v3/face-match/ al servicio Node.js
ProxyPass        /v3/face-match/ http://127.0.0.1:3100/v3/face-match/
ProxyPassReverse /v3/face-match/ http://127.0.0.1:3100/v3/face-match/

# Health check del microservicio (para monitoreo)
ProxyPass        /face-match-health http://127.0.0.1:3100/health
ProxyPassReverse /face-match-health http://127.0.0.1:3100/health
```

### 8.3 Verificar sintaxis y recargar

```bash
# Verificar que la sintaxis del archivo es correcta
sudo apache2ctl configtest
# Debe mostrar: Syntax OK

# Recargar sin cortar conexiones activas
sudo systemctl reload apache2
```

### 8.4 Verificar que el proxy funciona

```bash
curl -sk https://api.fidelitas.com.ar/face-match-health
# {"status":"ok","service":"fide-facematch-api","uptime":300}
```

---

## 9. Verificar que todo funciona

### Test 1 — apikey incorrecta (debe rechazar con 401)

```bash
curl -X POST https://api.fidelitas.com.ar/v3/face-match/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "apikey=INCORRECTA&selfie_image=abc&nationalid=12345678&gender=M"
```

Respuesta esperada:

```json
{"Status":"ERROR","Message":"API key inválida o no provista.","Response":[],"Transaction_id":null}
```

### Test 2 — campos faltantes (debe rechazar con 400)

```bash
curl -X POST https://api.fidelitas.com.ar/v3/face-match/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "apikey=TU_APIKEY_REAL&nationalid=12345678&gender=M"
```

### Test 3 — request completo con imagen real

```bash
# Convertir imagen a base64 (en tu máquina local)
base64 -w 0 foto_dni.jpg > foto_b64.txt

# Enviar el request
SELFIE=$(cat foto_b64.txt)
curl -X POST https://api.fidelitas.com.ar/v3/face-match/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "apikey=TU_APIKEY_REAL" \
  --data-urlencode "selfie_image=$SELFIE" \
  --data-urlencode "nationalid=22222222" \
  --data-urlencode "gender=M"
```

### Test 4 — verificar que los archivos se guardaron

```bash
# En el servidor, listar archivos generados
ls -la /var/www/html/apibatch/storage/
# Debe aparecer: TCN-xxx.txt · TCN-xxx_step1.json · TCN-xxx_step2.json

# Verificar registro en SQLite
sqlite3 /var/www/html/apibatch/data/fide-facematch.db \
  "SELECT tcn_id, status, score, time_total_ms, created_at FROM face_match_results ORDER BY id DESC LIMIT 5;"
```

---

## 10. Medir performance y consultar métricas

### 10.1 Instalar Apache Bench

```bash
sudo apt-get install -y apache2-utils
ab -V
```

### 10.2 Benchmark básico — health check (throughput máximo teórico)

```bash
# -n 10000: total de requests
# -c 100: 100 requests concurrentes simultáneos
# -k: keep-alive (reutilizar conexiones TCP)
ab -n 10000 -c 100 -k https://api.fidelitas.com.ar/face-match-health
```

**Qué mirar en la salida:**

| Métrica | Qué significa | Valor objetivo |
|---|---|---|
| Requests per second | Throughput — cuántos req/seg puede manejar | > 500 |
| Time per request (mean) | Latencia promedio por request en ms | < 200 ms |
| Percentil 50% | La mitad de los usuarios ve este tiempo | < 100 ms |
| Percentil 99% | El 1% más lento de los requests | < 500 ms |
| Failed requests | Requests que fallaron | 0 |

### 10.3 Monitorear recursos durante la carga

Abrir una segunda terminal mientras corre el benchmark:

```bash
# Monitor interactivo de PM2 — CPU y memoria de cada worker
pm2 monit

# Estadísticas del sistema en tiempo real
htop

# Conexiones de red activas hacia el servicio
ss -tnp | grep :3100
```

### 10.4 Consultar timings reales desde SQLite

Estos son los tiempos reales de cada llamada a RENAPER, almacenados por el servicio:

```bash
sqlite3 /var/www/html/apibatch/data/fide-facematch.db << 'EOF'
SELECT
  COUNT(*)                          AS total_operaciones,
  ROUND(AVG(time_token_ms), 0)      AS avg_token_ms,
  ROUND(AVG(time_step1_ms), 0)      AS avg_step1_renaper_ms,
  ROUND(AVG(time_step2_ms), 0)      AS avg_step2_resultado_ms,
  ROUND(AVG(time_total_ms), 0)      AS avg_total_ms,
  MAX(time_total_ms)                AS peor_caso_ms,
  MIN(time_total_ms)                AS mejor_caso_ms
FROM face_match_results
WHERE created_at >= datetime('now', '-1 hour', 'localtime');
EOF
```

---

## 11. Recuperar la base de datos SQLite ante un fallo

La base de datos está en `/var/www/html/apibatch/data/fide-facematch.db`. SQLite en modo WAL es muy robusto — rara vez se corrompe. Si el proceso se cayó a la mitad de una escritura, SQLite recupera automáticamente al próximo inicio.

### 11.1 Detectar si la DB está corrupta

```bash
sqlite3 /var/www/html/apibatch/data/fide-facematch.db "PRAGMA integrity_check;"
# Respuesta normal: ok
# Cualquier otra respuesta indica corrupción
```

### 11.2 Recuperar desde el WAL journal (crash reciente)

```bash
# Detener el servicio primero
pm2 stop fide-facematch

# Forzar checkpoint: aplica el WAL pendiente a la base principal
sqlite3 /var/www/html/apibatch/data/fide-facematch.db "PRAGMA wal_checkpoint(TRUNCATE);"

# Verificar integridad
sqlite3 /var/www/html/apibatch/data/fide-facematch.db "PRAGMA integrity_check;"

# Reiniciar el servicio
pm2 start fide-facematch
```

### 11.3 Recuperar desde backup

```bash
# Detener el servicio
pm2 stop fide-facematch

# Guardar el estado corrupto para análisis forense
cp /var/www/html/apibatch/data/fide-facematch.db \
   /var/www/html/apibatch/data/fide-facematch.db.corrupto.$(date +%Y%m%d_%H%M%S)

# Restaurar el backup (reemplazar FECHA con la fecha del backup más reciente)
cp /media/BACKUP_DISK/fide-facematch-db-FECHA.db \
   /var/www/html/apibatch/data/fide-facematch.db

# Verificar integridad del backup restaurado
sqlite3 /var/www/html/apibatch/data/fide-facematch.db "PRAGMA integrity_check;"

# Reiniciar
pm2 start fide-facematch
```

### 11.4 Exportar datos rescatables de una DB parcialmente corrupta

```bash
sqlite3 /var/www/html/apibatch/data/fide-facematch.db \
  ".mode csv" \
  ".output /tmp/rescue_export.csv" \
  "SELECT * FROM face_match_results;" \
  ".quit"

wc -l /tmp/rescue_export.csv
```

### 11.5 Script de backup diario automático

```bash
sudo nano /usr/local/bin/backup-facematch-db.sh
```

Contenido:

```bash
#!/bin/bash
FECHA=$(date +%Y%m%d_%H%M%S)
DB_ORIGEN="/var/www/html/apibatch/data/fide-facematch.db"
BACKUP_DIR="/backup/fide-facematch"

mkdir -p "$BACKUP_DIR"

# .backup es el método correcto para SQLite — checkpoint + copia consistente
sqlite3 "$DB_ORIGEN" ".backup $BACKUP_DIR/fide-facematch-db-$FECHA.db"

# Eliminar backups de más de 30 días
find "$BACKUP_DIR" -name "*.db" -mtime +30 -delete

echo "Backup completado: $BACKUP_DIR/fide-facematch-db-$FECHA.db"
```

```bash
sudo chmod +x /usr/local/bin/backup-facematch-db.sh

# Programar backup diario a las 03:00 AM
(crontab -l 2>/dev/null; echo "0 3 * * * /usr/local/bin/backup-facematch-db.sh") | crontab -

# Verificar
crontab -l
```

---

## 12. Comandos de operación diaria — referencia rápida

```bash
# ── Estado del servicio ─────────────────────────────────────────
pm2 status                             # Estado de todos los workers
pm2 show fide-facematch                # Detalles de un proceso específico
pm2 monit                              # Monitor interactivo CPU/RAM

# ── Logs ────────────────────────────────────────────────────────
pm2 logs fide-facematch                # Logs en tiempo real
pm2 logs fide-facematch --lines 500    # Últimas 500 líneas
pm2 flush fide-facematch               # Limpiar logs acumulados

# ── Reinicio ────────────────────────────────────────────────────
pm2 reload fide-facematch    # Zero-downtime (para actualizaciones)
pm2 restart fide-facematch   # Reinicio completo
pm2 stop fide-facematch
pm2 start ecosystem.config.js --env production

# ── Health check rápido ──────────────────────────────────────────
curl -s http://localhost:3100/health | python3 -m json.tool

# ── Ver la base de datos ─────────────────────────────────────────
sqlite3 /var/www/html/apibatch/data/fide-facematch.db \
  "SELECT tcn_id, status, score, time_total_ms, created_at FROM face_match_results ORDER BY id DESC LIMIT 10;"

# ── Contar operaciones del día ───────────────────────────────────
sqlite3 /var/www/html/apibatch/data/fide-facematch.db \
  "SELECT COUNT(*) FROM face_match_results WHERE DATE(created_at) = DATE('now','localtime');"

# ── Apache: estado y recarga ─────────────────────────────────────
sudo systemctl status apache2
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo tail -50 /var/log/apache2/error.log

# ── Backup manual de la DB ───────────────────────────────────────
/usr/local/bin/backup-facematch-db.sh
```

---

*DOC-OPS-006 · v1.1 · 2026-11-05 · CONFIDENCIAL — USO INTERNO · Fidelitas S.A.*
