Installation and setup

Which host does the DataMind Installer need?

A Linux host running Docker with the Compose v2 plugin. The Installer is a container that drives docker compose on the host through the Docker socket, so it needs a working Docker Engine and the docker compose subcommand — not the legacy docker-compose binary.

It does not need Node.js, PostgreSQL or any build tooling on the host: the runtime image bundles the Docker CLI, the Compose plugin and util-linux (for nsenter, used only by the host migration feature).

Note

The Installer's own PostgreSQL runs as a container from the same compose project. You do not provision a database separately.

Do I need to create the shared Docker network first?

Yes — run docker network create unistream once, before the first start. Both the Installer's compose project and the DataMind OS stack it deploys attach to that network, and both declare it external, so neither project creates it.

bash
docker network create unistream

Skipping this step fails immediately and legibly:

text
network unistream declared as external, but could not be found
Important

Do not let either compose project own this network. Both sides are external on purpose: a network that already exists without the project's own labels is rejected by Compose 2.19.1+, and compose down on an owner — including the Installer's own self-update — would delete a network the other stack is still using.

The literal network name unistream is fixed and must keep that spelling.

How do I configure the Installer's own .env?

Copy .env.example to .env in the install directory and edit it. Compose reads this file both for variable interpolation and as the containers' runtime environment.

bash
cp .env.example .env
VariablePurposeDefault
VERSIONImage tag of the Installer to runlatest
DOCKER_SOCKHost path of the Docker socket the Installer drives/var/run/docker.sock
NEST_PORTPort the Installer backend and UI listen on8000
NEST_NODE_ENVprod or devprod
SWAGGER_ENABLEDServe the OpenAPI UI at /api/docsfalse
TZContainer timezoneUTC
NEST_TYPEORM_LOGGINGLog every SQL statement the Installer runsfalse
NEST_ORIGINSCORS allowlist for the Installer APIhttp://localhost:8000
POSTGRES_USEROwner of the Installer's internal databasepostgres
POSTGRES_DATABASE_NAMEName of the Installer's internal databasedelamain
JWT_ACCESS_EXPIRYAccess-token lifetime for Installer sessions30m
JWT_REFRESH_EXPIRYRefresh-token lifetime for Installer sessions7d
Note

The JWT signing secret and the encryption key are not set here. They are generated into the delamain_secrets volume on first boot.

See Configuration variables for the full reference.

Which ports does the Installer publish?

Only ${NEST_PORT}, which defaults to 8000. That single port serves the Installer's API and the web interface, because the backend serves the built front end from the same origin at /api and /.

yaml
ports:
  - '${NEST_PORT:-8000}:${NEST_PORT:-8000}'

The Installer's PostgreSQL is not published in the production compose file — it is reachable only on the internal network. In the development compose file it is published on ${POSTGRES_PORT:-5432} for convenience.

What do I set if Docker runs rootless?

Point DOCKER_SOCK at the rootless socket. Find your UID with id -u, then set the path:

bash
id -u

If it prints 1000, the socket path for that installation is:

text
DOCKER_SOCK=/run/user/1000/docker.sock

The default /var/run/docker.sock is the rootful socket. In the compose file the socket path is mounted host path to container path one-to-one, so whatever you set must be a path that exists on the host.

Where are the Installer's secrets stored?

In the delamain_secrets volume, mounted at /usr/src/app/secrets. On first boot the backend generates what is missing and reuses what is already there:

FileContentsCreated by
jwt.secret64-byte hex signing key for Installer session tokensInstaller backend, first boot
encr.keyAES-256-GCM key (v2:-prefixed ciphertext) for stored secrets and generated valuesInstaller backend, first boot
curato.token48-character alphanumeric service tokenInstaller backend, first boot
pg.passPassword of the Installer's own PostgreSQL rolePostgreSQL container entrypoint, first boot

Files are written with mode 0600. The same volume is mounted into the backend-init one-shot that runs the database migrations.

Warning

Losing encr.key makes every stored secret unreadable — the Installer will report a decryption failure and you must re-enter the Azure client secret. See Data and backups.

What does the Installer do on its very first start?

It runs database migrations, generates its secrets, and comes up with an empty deployment directory. The startup sequence is:

  1. postgres starts and generates pg.pass if the file does not exist yet.
  2. backend-init runs typeorm migration:run against the Installer's database and exits.
  3. backend starts only after backend-init completes successfully, generates any missing secret files, and begins listening on NEST_PORT.

At that point no DataMind OS deployment exists: the deployment directory has no compose file and no .env, and the interface shows the setup screen.

Where do the downloaded deployment files land?

In the deployment/ directory next to the compose file, mounted into the backend at /usr/src/app/deployment. Three files live there:

Path (host)Path (container)Contents
./deployment/docker-compose.yml/usr/src/app/deployment/docker-compose.ymlThe DataMind OS compose file, downloaded from blob storage
./deployment/.env.unified.template/usr/src/app/deployment/.env.unified.templateThe environment schema that seeds the Installer's configuration rows
./deployment/.env/usr/src/app/deployment/.envThe generated environment file that the DataMind OS stack consumes

An optional deployment/docker-compose.override.yml is merged into every docker compose command when it exists. The Installer never writes that file — it is yours.

Note

The deployment directory is on the host, not in a volume, so the downloaded files survive a container replacement and are easy to inspect over SSH.

How does the Installer authenticate to the image registry?

With an Azure client secret, exchanged for an Azure Container Registry token. The Installer requests an Azure AD token using AZURE_TENANT_ID and AZURE_CLIENT_ID (set in the compose file) plus the client secret you store in the interface, then exchanges it for an ACR refresh token and pulls from unistream.azurecr.io.

Docker Hub images are pulled through the same registry as a cache, under the docker-hub/ repository prefix. Public Docker Hub images get an anonymous token instead.

Do I need a public DNS name to install?

No. The install works on a bare IP address or localhost. PLATFORM_URL is the root of every derived URL in the generated .env, and it is normalized: an explicitly typed scheme is kept, otherwise localhost, *.localhost, *.local and any IP literal get http://, while a real domain name gets https://.

text
localhost
192.168.10.20
portal.example.com
https://portal.example.com
Warning

If you type a real domain name, the Installer assumes https://. Make sure the deployment actually terminates TLS for that name before users open it. See Certificates and TLS.

What is the Azure client secret for, and where do I put it?

It authorizes Azure access for image pulls and artifact downloads. Store it in the interface — the setup wizard asks for it, and it can be replaced later from the Advanced configuration view.

Under the hood it is written to the Installer's system_secrets table, encrypted with encr.key, through PUT /api/system-secrets/azure. The Installer can validate it on demand by attempting a real token acquisition, so you find out immediately if a secret is wrong or expired.

Note

The installation step downloads the compose file and the environment template from Azure Blob Storage, and that download uses this same secret. There is no way to install without it.

What does the setup wizard actually do?

It stores your essentials, downloads the deployment artifacts, and starts the deploy job. In order:

  1. Saves the Azure client secret (PUT /api/system-secrets/azure) — required first, because the next step authenticates with it.
  2. Downloads docker-compose.yml and .env.unified.template from blob storage and seeds the configuration rows from the template.
  3. Saves and normalizes PLATFORM_URL.
  4. For a migration, also saves the legacy VM user and optional SSL_CERT_PATH / SSL_KEY_PATH.
  5. Starts the deploy job (POST /api/deployment/deploy): download → pull → compose up.

How do I start DataMind OS for the first time?

Use Start in the interface, or POST /api/deployment/deploy. A deploy job runs three phases: it downloads the compose file and environment template, pulls every service image, then runs docker compose up -d --pull never for all service targets.

bash
curl -X POST http://localhost:8000/api/deployment/deploy \
  -H "Authorization: Bearer <access-token>" \
  -H "Content-Type: application/json" \
  -d '{}'

The response carries a jobId. Follow progress with GET /api/deployment/jobs/<jobId>/logs, which is a server-sent event stream.

Important

Start refuses to run if a required configuration value is still missing, and it refuses if any image is not present locally — the error message names the missing configuration codes or images. Pull first if you see that.

How do I confirm the installation worked?

Check the Installer's health endpoint, then the deployment status. The health endpoint is public and verifies both the process and its database connection:

bash
curl -s http://localhost:8000/api/health

The response is:

json
{"status":"ok","db":"up"}

Then read the deployment status, which reports the prerequisites and every container:

bash
curl -s http://localhost:8000/api/deployment/status \
  -H "Authorization: Bearer <access-token>"

prerequisites.allReady is true when both the compose file and the .env exist; containers.items[] gives each service's condition, state, restart count and uptime.

What is the first administrator account, and how is it created?

The first account you create becomes an administrator, and it can only be created once. POST /api/user/register/initial is public and is refused with 403 as soon as any user exists. The login screen uses GET /api/user/exists to decide whether to show the create-admin form or the normal sign-in form.

Once an administrator exists, further accounts are created by an administrator from the Register User view. See Access and security.

Can I install DataMind OS without the Installer?

Not as a supported procedure. The DataMind OS stack is a compose project plus a generated .env, and the Installer is the component that produces both: it downloads the compose file and the environment schema from blob storage and renders the .env from configuration rows that carry dependencies, required-if rules, generated values and host-computed memory limits.

You could in principle run the compose file by hand with a hand-written .env, but nothing in the product verifies that file, and every value the deployment derives from the host — memory limits in particular — would be missing or wrong.

Note

The Installer does ship one standalone script for the opposite direction: migrate-host.sh retires a legacy bare-metal platform. That is a migration step, not an installation path. See Migrating from bare metal.

What goes wrong most often on the first install?

SymptomCauseFix
network unistream declared as external, but could not be foundThe shared network was never createddocker network create unistream
Install fails immediately on the artifact downloadAzure client secret missing, wrong or expiredStore it in Advanced configuration; use the validate action
Missing required configurations: …Required values still emptyFill the named configuration codes
Missing local images: …Start was pressed before a pullRun Update, then Start
Missing deployment files: …Compose file or .env absent and the restore failedCheck outbound access to blob storage, then re-run the download
Login screen shows only sign-inAn account already existsSign in, or reset the password from an admin account

For diagnosis in depth see Installation fails.

Prerequisites, the full install walkthrough and the first sign-in are covered in Requirements, Install and First login, and the post-install checklist is the fastest way to confirm a new deployment is healthy.