Backup and Restore

Backing up the DataMind Installer means backing up the Installer's own state: its database, its secrets volume and its configuration files. The DataMind OS data the Installer deploys is a separate concern, owned by the DataMind OS stack.

Know what the Installer owns

ItemWhere it livesWhat it holds
DatabaseDocker volume declared as pgdata, mounted at /var/lib/postgresql/data in delamain-postgresUsers and refresh tokens, configuration rows (some encrypted), system secrets such as the Azure client secret, the audit trail deployment_actions, the job-event history deployment_job_events
SecretsDocker volume declared as delamain_secrets — at /run/secrets in delamain-postgres, /usr/src/app/secrets in delamain-backendjwt.secret, encr.key, pg.pass, curato.token
Deployment filesHost bind mount ./deployment → /usr/src/app/deploymentThe downloaded DataMind OS docker-compose.yml, .env.unified.template, the generated .env, and an optional docker-compose.override.yml
Installer .envThe host file beside the Installer's docker-compose.ymlVERSION, DOCKER_SOCK, NEST_PORT, POSTGRES_*, JWT_*, CORS
Important

The DataMind OS data is not in this set. The DataMind OS stack is a different compose project (label com.docker.compose.project=unistream) with its own volumes. Back it up through the DataMind OS stack, not with the Installer's backup.

Note the real volume names

The compose file declares the volumes as pgdata and delamain_secrets without an explicit name: field, so Docker creates them prefixed with the compose project name — for example delamain_pgdata. Confirm the exact names on the host before copying:

bash
docker volume ls | grep -E 'pgdata|delamain_secrets'

Back up the database

A logical dump is the portable option and needs no downtime beyond the dump itself:

bash
docker exec delamain-postgres pg_dumpall -U "${POSTGRES_USER:-postgres}" \
  > delamain-db-$(date +%F).sql

POSTGRES_USER defaults to postgres and the database name to delamain.

Back up the secrets volume and the files

Stop the Installer's containers first, so the volumes and the files are captured consistently. docker compose down removes containers but keeps the declared volumes:

bash
docker compose down

Copy the secrets volume with a short-lived helper container (a standard Docker volume copy):

bash
docker run --rm \
  -v delamain_secrets:/data:ro \
  -v "$PWD":/backup \
  alpine tar czf /backup/delamain_secrets.tgz -C /data .

The same pattern works if you prefer a raw copy of the database volume instead of, or in addition to, the logical dump:

bash
docker run --rm -v <project>_pgdata:/data:ro -v "$PWD":/backup \
  alpine tar czf /backup/pgdata.tgz -C /data .

Then copy the files that are not in a volume:

bash
tar czf delamain-files-$(date +%F).tgz deployment .env docker-compose.yml

Keep the database dump, the secrets archive, the deployment directory, the Installer .env and the compose file together. Restart the Installer:

bash
docker compose up -d

Understand what is not covered

Not coveredWhy
DataMind OS data volumesOwned by the DataMind OS compose project, not the Installer
/var/tmp/delamainTransient staging for docker compose and the self-update helper
/var/lib/jenkins mountA read-only bind mount of the host's Jenkins home, kept for migrations
/opt/delamain mountHost side of the bare-metal retirement script
The unistream Docker networkExternal and owned by neither project; recreate it with docker network create unistream
The host Docker daemon configuration and the Docker socketHost infrastructure

Restore

  1. Recreate the external network if the host is new:
    bash
    docker network create unistream
  2. Restore the files: put the Installer's docker-compose.yml, .env and deployment/ directory back in place.
  3. Restore the secrets volume from delamain_secrets.tgz, into a volume named as the compose project expects (<project>_delamain_secrets).
  4. Start the database only and load the dump:
    bash
    docker compose up -d postgres
    docker exec -i delamain-postgres psql -U "${POSTGRES_USER:-postgres}" -d postgres \
      < delamain-db-<date>.sql
    The dump from pg_dumpall includes CREATE DATABASE and role statements, so it restores into the maintenance database.
  5. Start the rest: docker compose up -d. The delamain-backend-init one-shot runs typeorm migration:run to bring the restored schema up to the running build, then delamain-backend starts.
  6. Verify: curl -s http://localhost:${NEST_PORT:-8000}/api/health returns {"status":"ok","db":"up"}, and GET /api/version returns a digest.
Warning

The database and the secrets volume are a matched set, and restoring one without the other breaks the install:

  • encr.key (loaded as NEST_ENCR_KEY) decrypts the secrets stored in the database — the Azure client secret and any encrypted configuration values. Restore the database with a different encr.key and those values cannot be decrypted.
  • jwt.secret signs the access and refresh tokens; a different value invalidates every existing session.
  • pg.pass is the password the database was created with. It must match the restored database, or delamain-postgres will not be reachable and /api/health will fail.