Skip to content

Container image

The Bundled image, registry.tinyfactory.ai/tinyblox/tinyconductor-bundled, is one container that holds the engine and PostgreSQL. One volume holds PostgreSQL’s data and the secrets the engine generates on its first start. For a step-by-step walkthrough, see Quickstart. The images are published to TinyFactory’s registry; the exact address is given with your access.

Terminal window
docker run -d --name tinyconductor -p 127.0.0.1:8080:8080 \
-v tinyconductor-pgdata:/var/lib/postgresql/data \
registry.tinyfactory.ai/tinyblox/tinyconductor-bundled:0.1.0

See Bundled mode.

Every release publishes these images for linux/amd64 and linux/arm64, tagged with the release version, as in registry.tinyfactory.ai/tinyblox/tinyconductor:0.1.0. A release without a pre-release suffix also moves the <major>.<minor> and latest tags.

ImageWhat it runsGuide
registry.tinyfactory.ai/tinyblox/tinyconductor-bundledBundled mode: the engine and PostgreSQL in one containerthis page, Quickstart
registry.tinyfactory.ai/tinyblox/tinyconductorthe engine alone: the Embedded test engine by default, or a Cluster node with --mode clusterEmbedded mode, Cluster mode
registry.tinyfactory.ai/tinyblox/tinyconductor-script-workerthe external Script Task workerScript tasks
registry.tinyfactory.ai/tinyblox/tinyconductor-docsthis documentation, served on port 8080 (docker run -p 127.0.0.1:8080:8080 …) for reading offline or on your own network—

The engine program is also published as a download for Linux, macOS and Windows, for running without containers; see Embedded mode.

The engine requires a credential by default. On first boot it generates a random bearer token and keeps only its digest in PostgreSQL. The token is never written to the log: it is written once to the first-boot secrets file on the data volume, which only the engine’s user can read. The log says where. Read it, store it, then delete the file:

Terminal window
docker exec tinyconductor cat /var/lib/postgresql/data/tinyconductor/first-boot-secrets
docker exec tinyconductor rm /var/lib/postgresql/data/tinyconductor/first-boot-secrets

Every later boot reuses the stored credential and writes nothing. Only the token’s SHA-256 digest is stored, so the token can’t be read back. If you lose it, delete the row and restart to get a new one:

Terminal window
docker exec tinyconductor psql -U postgres -d tinyconductor -c \
'DELETE FROM bpm_runtime.engine_credential'
docker restart tinyconductor

Send it as Authorization: Bearer <token>. It is a bootstrap credential: use it to set the engine up, and give each job worker and script an API client of its own (Access → Clients in the console, or POST /v2/clients; see Identity and access). GET /healthz, GET /readyz, the console’s own page files and /auth/* are public. Everything that reads or changes engine state needs a credential. A call without one answers 401 with urn:bpm:error:unauthorized.

People sign in to the console instead of pasting tokens. On first boot the image also creates a bootstrap administrator (the first admin account). Its password is the CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD line of the same first-boot secrets file; only an argon2id hash of it is stored.

Open http://127.0.0.1:8080/console/ and sign in as admin. The session cookie is Secure and __Host- prefixed. Browsers accept that over plain HTTP only for localhost/127.0.0.1, and Safari not even then. For such a local-only setup, set CONDUCTOR_SESSION_INSECURE_COOKIE=1 (the cookie is then hb_session, without Secure). Never set it otherwise.

To sign in with your organisation’s identity provider instead, configure OIDC (this turns local users off unless CONDUCTOR_LOCAL_USERS_ENABLED=1):

Terminal window
docker run -d --name tinyconductor -p 127.0.0.1:8080:8080 \
-v tinyconductor-pgdata:/var/lib/postgresql/data \
-e CONDUCTOR_OIDC_ISSUER=https://sso.example.com/realms/tinyconductor \
-e CONDUCTOR_OIDC_CLIENT_ID=tinyconductor \
-e CONDUCTOR_OIDC_CLIENT_SECRET=… \
-e CONDUCTOR_OIDC_REDIRECT_URI=https://bpm.example.com/auth/callback \
-e 'CONDUCTOR_AUTH_MAPPING_RULES_JSON=[{"claim":"groups","equals":"bpm-operators","roles":["operator"]}]' \
registry.tinyfactory.ai/tinyblox/tinyconductor-bundled:0.1.0

A worked Keycloak setup, the mapping rules, the roles and every variable are in Identity and access.

VariableMeaning
CONDUCTOR_AUTH_CREDENTIALS_JSONStatic tokens, for bootstrap and tests (programs normally use API clients created in the console or with POST /v2/clients), in the same document Cluster mode takes, optionally with "expiresAt":"<RFC 3339>". Overrides the generated one. A subject may hold two tokens only when the credentials are identical except for the token — that is how a token is rotated; anything else sharing a subject refuses startup
CONDUCTOR_OIDC_*, CONDUCTOR_AUTH_MAPPING_RULES_JSON, CONDUCTOR_AUTH_ROLES_JSONSign-in through your identity provider. See Identity and access
CONDUCTOR_LOCAL_USERS_ENABLED, CONDUCTOR_LOCAL_USERS_JSON, CONDUCTOR_BOOTSTRAP_ADMIN_USERNAMELocal users; on by default without OIDC. Hash passwords with printf '%s' 'pw' | docker exec -i tinyconductor tinyconductor hash-password
CONDUCTOR_IDENTITY_DEFAULT_PROVIDERWith more than one identity provider (local users count as one): local or an OIDC alias (CONDUCTOR_OIDC_ALIAS, default sso), the provider whose people a plain username such as alice names; others are written alice@<alias>
CONDUCTOR_SESSION_IDLE_TIMEOUT_S, CONDUCTOR_SESSION_ABSOLUTE_TIMEOUT_S, CONDUCTOR_SESSION_INSECURE_COOKIEBrowser session policy: 1800 s idle, 43200 s absolute, Secure cookie
CONDUCTOR_ALLOW_ANONYMOUSTurns authentication off. Warns at every startup, shows a banner in the console, and cannot be combined with a non-loopback bind, with credentials, or with OIDC or local users. Only 1 and true turn it off; 0, false, empty and unset keep authentication on; any other value is refused at startup

To rotate a token, list the old and the new token for one subject, move the callers to the new one, then remove the old entry. The subject never changes, so the audit log keeps naming the same caller:

[{"token":"OLD","subject":"ops","tenantId":"default","kind":"service","actions":["*"]},
{"token":"NEW","subject":"ops","tenantId":"default","kind":"service","actions":["*"]}]

CONDUCTOR_SERVER_LISTEN_HOST is 0.0.0.0 and should stay that way. Inside a container that is the correct address. Docker’s published port targets the container’s own interface, so a loopback bind would make the published port unreachable. You control who can reach the engine with the publish address instead.

  • -p 127.0.0.1:8080:8080 — this host only. What the quickstart uses.
  • -p 0.0.0.0:8080:8080 — routable. A deliberate step; keep the credential and put TLS in front of it.
  • Remote access is an SSH tunnel or a reverse proxy to the loopback-published port, not a wider bind.

The engine refuses to start when CONDUCTOR_ALLOW_ANONYMOUS is combined with a non-loopback bind. The generated token means credentials exist by default, so the container’s own 0.0.0.0 bind starts normally.

PostgreSQL runs with listen_addresses='', so it has no TCP listener at all. The only way in is the Unix domain socket inside the container, and publishing a port cannot expose the database. To attach a streaming standby, set CONDUCTOR_POSTGRES_LISTEN_ADDRESSES (plus CONDUCTOR_POSTGRES_OPTIONS if you need more server settings) and add the matching pg_hba.conf rules in the volume.

On the first start the image creates two PostgreSQL logins:

  • postgres, the superuser, for your own administration over the socket. It logs in only with its password, which the image generates and keeps on the volume; docker exec -it tinyconductor psql uses it for you;
  • tinyconductor, which the engine uses. It owns the tinyconductor database, is not a superuser and cannot bypass row-level security.

The image sets CONDUCTOR_DATABASE_URL for the engine; don’t set it yourself.

The container runs as its own user, tinyconductor (uid and gid 65532), never as root, with no capabilities and no way to gain privileges. It writes only to its volume, so it runs with --read-only, --cap-drop ALL and --security-opt no-new-privileges, and in a Kubernetes pod with a read-only root file system. The engine runs in a sandbox of the Linux kernel (Landlock) that keeps it away from PostgreSQL’s files and the superuser’s password, so code running in the engine cannot act as the database superuser. See Bundled mode for what it needs and what it does not cover. On the volume, PostgreSQL’s data is in pgdata, its socket in run, the superuser’s password in admin and the engine’s own files in tinyconductor.

Data written by preview builds before 0.1.0 is not carried over. On such a volume the container stops with a message that says what to do: stop the container, remove its data volume (docker volume rm tinyconductor-pgdata, or whichever volume you mounted at /var/lib/postgresql/data), and start the 0.1.0 image with a fresh volume. Then deploy your process models again.

From 0.1.0 on, the database is upgraded forward automatically: when a newer version starts on the same volume, it updates the database layout before it serves requests. Back up the volume first, stop the old container, and start the new image on the same volume. An older version cannot be started again on a database that a newer version has upgraded; restore the backup instead.

Third-party notices for everything bundled here ship inside the image at /usr/share/tinyconductor/THIRD_PARTY_NOTICES.md and in THIRD_PARTY_NOTICES.md. No connector runtime is bundled.