The DataMind Installer writes almost everything to standard output, so container logs are the primary source. A structured audit trail and a persisted job-event history add the rest.
Container names are fixed in the Installer's compose file, so docker logs by name is the reliable
way to reach them, whatever the compose project is called.
| Component | Container name | Where it writes | Command |
|---|---|---|---|
| Installer backend | delamain-backend | stdout (NestJS logger) | docker logs delamain-backend |
| Installer database | delamain-postgres | stdout | docker logs delamain-postgres |
| Migrations (one-shot) | delamain-backend-init | stdout | docker logs delamain-backend-init |
| Update helper | delamain-self-updater | stdout, plus <work-dir>/.self-update-status | docker logs delamain-self-updater |
| DataMind OS services | compose project unistream | container stdout | via the Installer API, or docker compose -p unistream logs |
The one-shot delamain-backend-init service runs typeorm migration:run and exits; its log is the
record of the schema migrations that ran on the last deploy or boot.
By container name:
docker logs --tail 200 -f delamain-backend docker logs --tail 200 delamain-postgres docker logs --tail 200 delamain-backend-init docker logs --tail 200 delamain-self-updater
By compose service, from the directory that holds the Installer's docker-compose.yml. The backend
compose service is named backend:
docker compose logs -f backend docker compose logs -f postgres
The DataMind OS stack is its own compose project. Its containers carry the label
com.docker.compose.project=unistream:
docker ps --filter label=com.docker.compose.project=unistream docker compose -p unistream logs --tail 200
The Installer's .env sets TZ=UTC, and container log timestamps come from Docker in UTC.
The Installer's interface shows live output while a job runs: the raw docker compose output for
the job, and each service's container log on its own panel. Under the hood these are server-sent
event (SSE) endpoints:
| Endpoint | Method | What it streams |
|---|---|---|
/api/deployment/jobs/{jobId}/logs | SSE | The job's events: phases, pull progress, compose output, warnings, the final finished event |
/api/deployment/logs | SSE | Aggregated container logs for all DataMind OS services; optional ?tail=<lines> |
/api/deployment/logs/{service} | SSE | One compose service's container logs; optional ?tail=<lines> |
The job stream replays from the beginning, or from ?after=<seq> or a Last-Event-ID header, so a
reconnecting client does not lose output. It emits a heartbeat every 15 seconds.
curl -N "http://localhost:${NEST_PORT:-8000}/api/deployment/jobs/<jobId>/logs?after=0" \
-H "Authorization: Bearer <token>"
curl -N "http://localhost:${NEST_PORT:-8000}/api/deployment/logs/clickhouse-server?tail=200" \
-H "Authorization: Bearer <token>"An update replaces the backend, so the API stops answering mid-way. Follow it on the host instead:
docker logs -f delamain-self-updater
The helper's log is the step-by-step record โ pre-flight result, compose backup, install of the new
compose file, the switch, and either ok, rolled-back or failed. See
Update the DataMind Installer.
The Installer also mirrors every docker compose job line into its own stdout, so deployment
output survives a backend restart and is picked up by the DataMind OS log pipeline
(Fluent Bit โ VictoriaLogs).
For a plain, aggregated view of the DataMind OS containers over a time window, the Installer exposes a dedicated log controller. Both endpoints require the admin role.
| Endpoint | Method | Arguments |
|---|---|---|
/api/deployment-log | SSE | since, until (ISO 8601), containerName |
/api/deployment-log/download | GET | since (required, ISO 8601), until, containerName |
The download returns text/plain as logs-<ISO timestamp>.txt, with every line prefixed by the
container name it came from:
curl -s -OJ "http://localhost:${NEST_PORT:-8000}/api/deployment-log/download?since=2026-09-01T00:00:00Z" \
-H "Authorization: Bearer <token>"Every action the Installer takes is recorded in the database table deployment_actions, with its
status, exit code, acting user and a free-text detail.
| Recorded action | Meaning |
|---|---|
restart | In-place restart of a service |
stop / kill | docker compose stop / kill |
pull | Image pull |
compose-up | Start of already-pulled images |
deploy | Download templates, pull, then compose up |
apply-config | Recreate services so they pick up edited configuration |
migrate-host | Retire the bare-metal platform |
cancel-job | A job cancelled by an operator |
self-update | The Installer updating itself |
Statuses are started, completed and failed. Read the newest first:
curl -s "http://localhost:${NEST_PORT:-8000}/api/deployment/actions?limit=50" \
-H "Authorization: Bearer <token>"The acting user is resolved from the request; a call from the DataMind OS control plane is
attributed to the user id it forwards, and falls back to curato.
| Log or record | Retention |
|---|---|
Job events (deployment_job_events table) | Pruned after 30 days, on startup |
| In-memory job and its recent events | Dropped 60 minutes after the job ends; older jobs are served from the database |
Audit rows (deployment_actions table) | Not pruned by the Installer |
| Container stdout | The Installer's compose files set no logging driver or rotation limits, so retention follows the host Docker daemon's own configuration |
| Hung-job guard | A job with no output for 15 minutes is aborted as hung, with the message No output for N minutes โ aborted as hung |
Because the compose files define no log rotation, unbounded container logs are the host daemon's
policy to set. Check the daemon's log-driver/log-opts before assuming growth is bounded.
docker ps -a and, from the Installer directory, docker compose ps.for c in delamain-backend delamain-postgres delamain-backend-init delamain-self-updater; do echo "===== $c ====="; docker logs --tail 500 "$c" 2>&1 done
GET /api/version and GET /api/system/self-update-check.GET /api/deployment/status.GET /api/deployment/actions?limit=50.GET /api/deployment-log/download?since=<ISO>.<work-dir>/.self-update-status.Do not paste .env, anything from the secrets volume, or a bearer token. The Installer's
.env and its secrets volume carry the JWT signing secret, the encryption key, the PostgreSQL
password and the service token.