Self-hosted setup
Prepare a licensed DataMaker installation with Docker Compose.
Self-hosted DataMaker requires access to the deployment bundle or repository and the release images. Obtain that access, the intended release version and license configuration from Automators or your administrator before starting. The application repository is not a public anonymous download.
Requirements
The supplied Compose setup targets Linux AMD64, Docker Engine 24 or later and Docker Compose 2.24 or later. Start with at least 4 vCPU, 8 GB RAM and 40 GB disk, then size storage and workers for your workload. These are starting requirements, not a capacity guarantee.
Prepare the app and API hostnames, inbound HTTPS routing, storage and outbound access to your chosen AI providers and connected systems. Private registry images require credentials with package-read access.
Configure the deployment bundle
In the supplied hosting directory:
cp .env.example .env
chmod 600 .env
cp Caddyfile.example CaddyfileFill in the release version, domains, datastore configuration and AI provider settings from the example file. Generate unique secrets for DATAMAKER_TOKEN_SECRET, CHAT_SECRET, CRYPT_SECRET, POSTGRES_PASSWORD and REDIS_PASSWORD when using bundled datastores. Store them securely and retain them across upgrades.
Configure AUTOMATORS_SESSION_PUBLIC_KEYS using the signing public keys supplied by your Automators Auth deployment. These are verification keys; do not place Auth's private signing key in DataMaker. See Authentication.
You do not need a key in hand to deploy. Bring the stack up and sign in, and the licensing surface - the wall, or Settings → License - offers two paths:
- Request a license. The server files a request with the issuer over outbound HTTPS, carrying your contact email, company and this deployment's public origin. Automators reviews it; the server polls for the outcome and activates the issued key itself once approved. A denial appears in the same place with the reviewer's note.
- Paste a key you were sent directly.
Set DATAMAKER_PUBLIC_URL to the real browser-facing origin before requesting: it is this deployment's identity with the issuer as well as the URL the browser uses. DATAMAKER_LICENSE_REQUIRED=1 makes a valid license mandatory, and until one is active the deployment serves only sign-in and the licensing surfaces.
A deployment cannot mint its own license. It carries the public keys it verifies against and no signing key, so a requested key is verified exactly like a pasted one. Do not remove license enforcement to work around a configuration error.
Seats on a server license
A server license allows a number of seats, and every account on the deployment holds one. Signing in again, using the desktop app and joining another workspace never use a new seat.
When every seat is in use, a new person who signs in sees This DataMaker server is full, with how many accounts the license allows, and can try again once you have freed a seat or added more. Inviting an address that has no account yet, at the limit, tells you the server is full. Below the limit the invitation is refused because the address has no account. Accounts are created at first sign-in through your identity provider, so ask the person to sign in once a seat is free, then add them to the workspace.
Settings → License shows how many seats are in use and, when it has happened, how many sign-ups were refused in the last 7 days because the server was full. A person refused several times on the same day is counted once.
AI usage metering
By default chat and agent runs call Anthropic and OpenAI directly with the provider keys in .env, and nothing records what they spent: no AiUsageEvent rows are written, so AI usage reporting reads zero however much traffic goes through. The Plan usage panel is a Cloud surface and a self-hosted deployment does not show it, so read the figure with GET /cloud-licenses/usage?teamId=... instead. To record usage, route model calls through the API's embedded AI gateway by setting both variables in .env:
# Reachable from the opencode container, so the internal service name,
# not DATAMAKER_PUBLIC_API_URL.
AI_GATEWAY_URL=http://datamaker-api:8000/ai
# Shared server-to-server credential the gateway checks.
AI_GATEWAY_SECRET=<openssl rand -hex 32>Set them together. With a URL but no matching secret the gateway answers 401 and chat stops working. Restart with docker compose up -d datamaker-api datamaker-opencode. Verify with a chat turn followed by GET /cloud-licenses/usage?teamId=..., which should move. The provider keys stay where they are: in this mode the API container spends them.
Serve DataMaker under a path
DataMaker can share a hostname with other applications, for example at https://tools.example.com/datamaker. Put the path in the public URLs and nothing else changes:
DATAMAKER_PUBLIC_URL=https://tools.example.com/datamaker
DATAMAKER_PUBLIC_API_URL=https://tools.example.com/datamaker/dm-apiThe web app applies the path when its container starts, so the same release images serve a root or a path. Your reverse proxy or ingress must forward /datamaker/... to the web app with the prefix intact. For the API either form works: it answers with or without the /datamaker/dm-api prefix.
On platforms that run containers with an arbitrary user or a read-only root filesystem, such as OpenShift, keep /tmp writable in the web app container. The app writes a copy of its build there at start, about 60 MB.
Corporate CA certificates
If your network intercepts and re-signs outbound TLS, give the containers your certificate authority in .env. No image rebuild is needed:
CORPORATE_CA_CERT="-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----"Any variable whose name ends in _CERT or _CA_CERT is picked up. You can instead name the variable in CERT_ENV_VAR_NAME, mount a PEM file at /app/certs/ca.crt, or list PEM files in DATAMAKER_CA_FILES, separated by colons. Several sources are combined, and the bundle's own local certificate stays trusted.
Every service, including the scenario runner and the initialization container, trusts the CA at start. Each container logs a docker-ca: line for each source it used. The supplied CA is added to the system certificates rather than replacing them, so public services stay reachable. The working files go to /tmp/datamaker-ca (or $TMPDIR/datamaker-ca where the image sets a TMPDIR), so a read-only root filesystem or an arbitrary user ID, as on OpenShift, is supported. Set DATAMAKER_CA_DIR to use another writable directory, one the service user owns: these files decide what TLS verifies against, so a directory that is a symlink, owned by someone else, or writable by group or other is refused, and the container starts with the CA unconfigured and a docker-ca: line naming the reason. The default path is created by the container, and falls back to a private temporary directory if something else holds it.
Start and verify
Point DNS at the host and confirm the TLS routing configuration, then start the bundled services:
docker compose up -d
docker compose logs -f datamaker-init
docker compose psWait for schema initialization to complete successfully. Verify HTTPS, sign-in, project access, a small generation, scenario execution and a downloadable output before admitting normal traffic. Stop the log-follow command once initialization is complete.
The default bundle includes datastores. If using external Postgres or Redis, follow the overlay instructions supplied with the same release; do not combine files from different versions.
Continue with Operations and upgrades.