# Actualizaciones, copias y escalado

> Actualiza InfraWard, haz copias y restáuralas, escala el worker, rota credenciales y refuerza OpenBao.

Todos los comandos de esta página se ejecutan desde el directorio de instalación (`/opt/infraward` en la [guía de instalación](/es/docs/installation.md)).

## Actualizar

1. Lee las notas de la nueva versión y [haz una copia](#hacer-copias-de-seguridad) antes de nada.

2. Actualiza los ficheros de despliegue con los de la nueva versión (`compose.yml`, `compose.openbao.yml`, `init.sh`, `openbao/config.hcl`). Conserva tu `.env`, `data/` y `secrets/`. Compara `.env.example` con tu `.env` y añade las variables nuevas.

3. Pon la nueva versión en `.env`:

   ```ini title=".env"
   INFRAWARD_VERSION=v0.6.0
   ```

4. Vuelve a ejecutar `init.sh`. Crea las claves, secretos, AppRoles o directorios que necesite la nueva versión y deja el resto como está. Con OpenBao necesita `secrets/openbao/init.json`: si lo sacaste del servidor, devuélvelo para este paso y bórralo después.

   ```bash
   ./init.sh
   ```

5. Descarga las imágenes y recrea los contenedores:

   ```bash
   docker compose pull
   docker compose up -d
   ```

   La API aplica las migraciones de la base de datos al arrancar. El worker y el gateway esperan a que la API esté sana.

6. Comprueba `docker compose ps` y entra en la interfaz.

> **Atención**
>
> Saltarse el paso 4 es el fallo más habitual al actualizar. Las versiones que añaden un secreto de Compose (por ejemplo, la contraseña de Redis o la AppRole de la terminal) fallan con un error como `TERMINAL_OPENBAO_ROLE_ID es obligatoria (la escribe init.sh)` hasta que se ejecuta `init.sh`.

No se puede volver a una versión anterior después de que se hayan aplicado sus migraciones. En su lugar, restaura la copia que hiciste antes de actualizar.

## Hacer copias de seguridad

| Qué | Dónde | Frecuencia | Notas |
|---|---|---|---|
| Base de datos | `data/postgres` | Diaria | Usa un volcado lógico (abajo) en lugar de copiar los ficheros de una base de datos en marcha. |
| Almacenamiento de OpenBao | `data/openbao` | Diaria | Secretos, CA SSH y AppRoles. Para OpenBao o usa una instantánea del sistema de ficheros para tener una copia coherente. |
| Claves y secretos | `secrets/` | Tras `init.sh` y tras cada rotación | **Aparte de la copia de la base de datos.** |
| Configuración | `.env`, `compose*.yml`, `openbao/config.hcl` | Tras cada cambio | |
| Redis | `data/redis` | Opcional | Solo colas y locks. Los trabajos pendientes se vuelven a programar. |
| Caché de Trivy | `data/worker` | Nunca | Se descarga de nuevo al arrancar. |

Volcado de la base de datos:

```bash
docker compose exec -T postgres sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > infraward-$(date +%F).dump
```

> **Claves y datos, por separado**
>
> `secrets/master.key` y `secrets/vault.master.key` descifran los secretos del proveedor local y de la caja fuerte local. Una copia que contenga la base de datos y estas claves entrega todos los secretos guardados. Una copia de la base de datos sin las claves no se puede descifrar. Guárdalas en sitios distintos y con accesos distintos.

## Restaurar

1. Instala la misma versión de InfraWard en el host nuevo siguiendo la [guía de instalación](/es/docs/installation.md), pero **sin** ejecutar todavía `init.sh` ni arrancar el stack.
2. Copia `.env`, `secrets/` y `data/openbao` desde la copia.
3. Ejecuta `./init.sh`. Crea `data/postgres`, `data/redis` y `data/worker` y corrige los propietarios de todo.
4. Arranca solo PostgreSQL y carga el volcado:

   ```bash
   docker compose up -d postgres
   docker compose exec -T postgres sh -c 'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists' < infraward-2026-10-27.dump
   ```

5. Arranca todo con `docker compose up -d`.

## Escalar el worker

Varias réplicas del worker escanean más imágenes en paralelo:

```bash
docker compose up -d --scale worker=3
```

O pon `WORKER_REPLICAS=3` en `.env` para que el número se mantenga en el siguiente `up`. Las réplicas:

- comparten las colas sin duplicar trabajos;
- respetan los límites por servidor sumando todas: `HOST_MAX_JOBS` (2) trabajos a la vez contra un servidor, de los que `HOST_MAX_SCAN_JOBS` (1) son escaneos; un CT cuenta contra su nodo de Proxmox;
- comparten `data/worker`, así que la base de datos de Trivy se descarga una sola vez;
- eligen un líder mediante Redis, que ejecuta las tareas programadas. **Actividad** muestra las réplicas conectadas y cuál ejecuta cada trabajo.

Cuando una réplica se para, espera hasta 90 segundos (`WORKER_SHUTDOWN_GRACE`) a los trabajos en curso y devuelve el resto a la cola. Otra réplica los recoge.

La concurrencia de cada réplica se ajusta con `WORKER_CONCURRENCY`, `COLLECT_CONCURRENCY`, `DISCOVERY_CONCURRENCY`, `IMAGE_SCAN_CONCURRENCY` y las demás variables de [Variables de configuración](/es/docs/configuration.md#worker). El escaneo consume mucha memoria: añade memoria antes de subir `IMAGE_SCAN_CONCURRENCY`.

## Rotar credenciales

| Credencial | Cómo rotarla |
|---|---|
| `secret_id` de las AppRoles de OpenBao (app, caja fuerte y terminal) | `./init.sh --rotate-secret-id` y después `docker compose restart api worker gateway`. |
| Contraseña del administrador | **Ajustes → Perfil → Seguridad**. Cierra tus otras sesiones. |
| Claves de la CA SSH | Después de cambiar el emisor de la CA en OpenBao (`infraward-ssh/`), InfraWard marca los servidores cuyas claves de la CA instaladas están desactualizadas. Usa **Regenerar el comando** en cada uno y ejecuta el comando nuevo. |
| Token de Cloudflare | **Ajustes → Conectores → Reemplazar token**. |
| Tokens de API | Revócalos y crea otros en **Ajustes → Tokens de API**. |

## Reforzar OpenBao

El despliegue de ejemplo desella OpenBao automáticamente con `secrets/openbao/unseal.key`, que está en el mismo host que los datos. Quien pueda leer el disco puede leer los secretos. Para más garantías, edita `openbao/config.hcl`:

- **Desellado manual**: quita el bloque `seal "static"`. Tras cada reinicio, ejecuta `docker compose exec openbao bao operator unseal` con la clave de desellado.
- **Desellado automático externo**: sustituye el bloque por un KMS de un proveedor cloud o por el motor `transit` de otro OpenBao o Vault.

OpenBao escucha sin TLS y solo en la red interna. Para usar un OpenBao externo, quita `compose.openbao.yml` de `COMPOSE_FILE`, configura las AppRoles y el motor SSH como hace `init.sh` y define `OPENBAO_ADDR` y las variables de las AppRoles para `api` y `worker` en un fichero de override.

## Migrar desde volúmenes con nombre

Los primeros despliegues guardaban los datos en volúmenes con nombre (`postgres-data`, `redis-data`, `worker-data`, `openbao-data`). Para pasar a `data/`:

```bash
docker compose down
./init.sh
for v in postgres redis openbao; do
  docker run --rm -v infraward-stack_$v-data:/from:ro -v "$PWD/data/$v:/to" \
    docker.io/library/alpine sh -c 'cp -a /from/. /to/'
done
./init.sh
docker compose up -d
```

El segundo `init.sh` corrige los propietarios tras la copia. Comprueba que todo funciona antes de borrar los volúmenes antiguos con `docker volume rm`. La caché de Trivy no hace falta copiarla.

---

Página HTML: https://infraward.net/es/docs/operations/
