Upgrades, backups and scaling
View as MarkdownAll commands on this page run from the installation directory (/opt/infraward in the installation guide).
Upgrade
Section titled “Upgrade”-
Read the release notes of the new version and back up first.
-
Update the deployment files from the new release (
compose.yml,compose.openbao.yml,init.sh,openbao/config.hcl). Keep your.env,data/andsecrets/. Compare.env.examplewith your.envand add any new variables. -
Set the new version in
.env:.env INFRAWARD_VERSION=v0.6.0 -
Run
init.shagain. It creates any key, secret, AppRole or directory that the new version needs and leaves everything else as it is. With OpenBao it needssecrets/openbao/init.json: if you moved it off the server, put it back for this step and remove it afterwards.Terminal window ./init.sh -
Pull the images and recreate the containers:
Terminal window docker compose pulldocker compose up -dThe API applies database migrations when it starts. The worker and the gateway wait until the API is healthy.
-
Check
docker compose psand sign in.
Rolling back to an earlier version after its migrations have run is not supported. Restore the backup taken before the upgrade instead.
Back up
Section titled “Back up”| What | Where | How often | Notes |
|---|---|---|---|
| Database | data/postgres |
Daily | Use a logical dump (below) rather than copying files of a running database. |
| OpenBao storage | data/openbao |
Daily | Secrets, SSH CA and AppRoles. Stop OpenBao or take a filesystem snapshot for a consistent copy. |
| Keys and secrets | secrets/ |
After init.sh and after each rotation |
Separately from the database backup. |
| Configuration | .env, compose*.yml, openbao/config.hcl |
After each change | |
| Redis | data/redis |
Optional | Only queues and locks. Pending jobs are rescheduled. |
| Trivy cache | data/worker |
Never | Downloaded again on start. |
Dump the database:
docker compose exec -T postgres sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > infraward-$(date +%F).dumpRestore
Section titled “Restore”-
Install the same InfraWard version on the new host following the installation guide, but do not run
init.shor start the stack yet. -
Copy
.env,secrets/anddata/openbaofrom the backup. -
Run
./init.sh. It createsdata/postgres,data/redisanddata/workerand fixes ownership of everything. -
Start PostgreSQL alone and load the dump:
Terminal window docker compose up -d postgresdocker compose exec -T postgres sh -c 'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists' < infraward-2026-10-27.dump -
Start everything with
docker compose up -d.
Scale the worker
Section titled “Scale the worker”Run several worker replicas to scan more images in parallel:
docker compose up -d --scale worker=3Or set WORKER_REPLICAS=3 in .env so the number survives the next up. Replicas:
- share the queues without duplicating jobs;
- respect per-server limits across all replicas:
HOST_MAX_JOBS(2) jobs at a time against one server, of whichHOST_MAX_SCAN_JOBS(1) scans; a CT counts against its Proxmox node; - share
data/worker, so the Trivy database is downloaded once; - elect one leader through Redis to run scheduled tasks. Actividad shows the connected replicas and which one runs each job.
When a replica stops, it waits up to 90 seconds (WORKER_SHUTDOWN_GRACE) for running jobs and returns the rest to the queue. Another replica picks them up.
Per-replica concurrency is set with WORKER_CONCURRENCY, COLLECT_CONCURRENCY, DISCOVERY_CONCURRENCY, IMAGE_SCAN_CONCURRENCY and the other variables in Configuration variables. Scanning is memory-hungry: add memory before raising IMAGE_SCAN_CONCURRENCY.
Rotate credentials
Section titled “Rotate credentials”| Credential | How to rotate |
|---|---|
OpenBao AppRole secret_id (app, vault and terminal) |
./init.sh --rotate-secret-id, then docker compose restart api worker gateway. |
| Administrator password | Ajustes → Perfil → Seguridad. Closes your other sessions. |
| SSH CA keys | After changing the CA issuer in OpenBao (infraward-ssh/), InfraWard flags every server whose installed CA keys are out of date. Use Regenerar el comando on each one and run the new command. |
| Cloudflare token | Ajustes → Conectores → Reemplazar token. |
| API tokens | Revoke and create new ones in Ajustes → Tokens de API. |
Harden OpenBao
Section titled “Harden OpenBao”The example deployment unseals OpenBao automatically with secrets/openbao/unseal.key, which lives on the same host as the data. Anyone who can read the disk can read the secrets. For stronger guarantees, edit openbao/config.hcl:
- Manual unseal: remove the
seal "static"block. After every restart, rundocker compose exec openbao bao operator unsealwith the unseal key. - External auto-unseal: replace the block with a cloud KMS or the
transitengine of another OpenBao or Vault.
OpenBao listens without TLS on the internal network only. To use an external OpenBao instead, remove compose.openbao.yml from COMPOSE_FILE, configure the AppRoles and the SSH engine as init.sh does, and set OPENBAO_ADDR and the AppRole variables for api and worker in an override file.
Migrate from named volumes
Section titled “Migrate from named volumes”Early deployments stored data in named volumes (postgres-data, redis-data, worker-data, openbao-data). To move to data/:
docker compose down./init.shfor 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.shdocker compose up -dThe second init.sh fixes ownership after the copy. Check that everything works before deleting the old volumes with docker volume rm. The Trivy cache does not need copying.