Skip to content
archmax.ai

Installation

archmax automation ships as one image, ghcr.io/archmax-ai/automation. A container of it runs the whole platform: nginx serves the web app on the public port and passes /api/ to the API, and the dispatcher runs beside them. The image carries no deployment’s settings, so the same image serves every deployment: you hand it an env file and a config when it starts.

To work on the code instead, see the development setup; to try the product on your machine first, follow the quickstart.

Service What for
MongoDB Agents, environments, sessions, turns and every other record.
Redis The dispatcher’s queues and the per-agent locks around git operations. Optional for one container: without REDIS_URL the container runs its own (see the image).
An S3-compatible store The only durable store: repository bundles, every draft and version, every session’s files. The bucket must exist.
An identity provider Sign-in: an OIDC provider the web app signs in at (Auth0, Cognito, Okta, Keycloak), or an AWS load balancer that signs people in (AWS). The image runs with NODE_ENV=production, which refuses to boot until ARCHMAX_SIGN_IN names a sign-in mode.
A model endpoint and key for the design agent The config’s designAgent section, which production also requires.

Local disk is only git scratch (/data/scratch) and the skill registry clones (/data/skill-registries), both disposable, so the container needs no volume. nginx sends Strict-Transport-Security, which tells browsers to use https only, so serve the container behind TLS termination: a load balancer or a proxy with a certificate.

Each release is pushed for linux/amd64 and linux/arm64 under three tags. Every commit on main that passes CI, and every pull request from a branch of the repository, gets an image of its own:

Tag Names
X.Y.Z One release, such as 1.5.0. Pin this in production.
X.Y The newest release of that minor line.
latest The newest release.
unstable The newest commit on main that passed CI. Not a release.
unstable-<sha> One commit on main that passed CI, by its first seven characters. The newest ten are kept.
pr-<number> A pull request (its merge commit), rebuilt on every push to it and deleted when it closes.

The package is private until an owner makes it public, so sign in to the registry first with a GitHub token that can read packages:

Terminal window
echo "$GITHUB_TOKEN" | docker login ghcr.io -u USERNAME --password-stdin
docker pull ghcr.io/archmax-ai/automation:1.5.0

The examples on this page use 1.5.0; put the release you run in its place.

Where the platform runs is set in environment variables; startup fails with a message naming the variable when a required one is missing. A production env file looks like this (replace every <…>; Docker’s --env-file reads a # only at the start of a line):

MONGODB_URI=mongodb://<mongo host>:27017/archmax
REDIS_URL=redis://<redis host>:6379
S3_BUCKET=<bucket>
S3_REGION=<region>
# Leave both keys out to sign with the host's AWS credentials (a task or pod role)
S3_ACCESS_KEY_ID=<access key id>
S3_SECRET_ACCESS_KEY=<secret access key>
# For MinIO or another S3-compatible store, also:
# S3_ENDPOINT=http://<minio host>:9000
# S3_FORCE_PATH_STYLE=true
# OIDC sign-in: the issuer, the SPA application's client id, and (for Auth0) the API
# identifier its access tokens are issued for. With Auth0, the issuer is
# https://<your-auth0-domain>/ with the trailing slash.
ARCHMAX_SIGN_IN=oidc
ARCHMAX_OIDC_ISSUER=<https://auth.example.com/>
ARCHMAX_OIDC_CLIENT_ID=<client id>
ARCHMAX_OIDC_AUDIENCE=<https://api.example.com>
# Seals every stored credential in the database store, the default: openssl rand -base64 32
MASTER_KEY=<base64 key>
# The public origin: invitation links, and the callback addresses the dispatcher registers
APP_BASE_URL=https://<app.example.com>
OAUTH2_REDIRECT_URL=https://<app.example.com>/api/oauth2/callback
# Referenced by the config as a placeholder
ARCHMAX_DESIGN_AGENT_API_KEY=<key>
# An organization's email domain needs a DNS TXT record before it can onboard new users
# (on by default). A single-tenant deployment whose Organization Owners are all trusted, or that cannot
# reach public DNS, can verify domains without it:
# ARCHMAX_DNS_VERIFICATION=off

ARCHMAX_SIGN_IN=oidc requires ARCHMAX_OIDC_ISSUER and ARCHMAX_OIDC_CLIENT_ID, and MASTER_KEY is required in production, unless the deployment keeps its credentials’ secrets in AWS Secrets Manager instead (ARCHMAX_SECRET_STORE=aws-secrets-manager, with no MASTER_KEY; see where credentials are kept). Behind an AWS load balancer that signs people in, set ARCHMAX_SIGN_IN=aws-alb with ARCHMAX_AWS_ALB_ARN and ARCHMAX_AWS_ALB_SIGN_OUT_URL instead of the OIDC group (see AWS): a variable of the mode not named refuses the boot. Without APP_BASE_URL the platform falls back to the first CORS_ALLOWED_ORIGINS entry, which defaults to http://localhost:5173.

Every variable, with its default, is on the environment variables page.

What the platform offers (the design agent, the services, the Activepieces collections, the skill registries and the OAuth apps) is one document, the config. Start from config.yaml.example in the repository; in production it needs at least the design agent:

designAgent:
apiBaseUrl: https://api.openai.com/v1
apiKey: "${{ARCHMAX_DESIGN_AGENT_API_KEY}}"
model: gpt-6.1-sol
prices:
input: 2.00
output: 10.00

The config holds no secret: each is a ${{VAR}} placeholder resolved from the environment at boot. Hand it to the container in one of two ways:

  • Mounted at /app/config.yaml (-v "$PWD/config.yaml:/app/config.yaml:ro"), or anywhere else with ARCHMAX_CONFIG_FILE naming the path.
  • As one variable, ARCHMAX_CONFIG, for a host with nothing to mount. pnpm config:env prints config.yaml as the one line of JSON it holds, and pnpm config:env --base64 the base64 form, for a host such as Railway that reads ${{NAME}} inside a variable’s value itself.

ARCHMAX_CONFIG wins when both are present, with one warning naming the ignored file. The config reference lists every section, among them branding, which gives the deployment its own title, logo and colours.

Terminal window
docker run -d --name archmax -p 8080:8080 --cap-drop ALL \
--env-file archmax.env \
-v "$PWD/config.yaml:/app/config.yaml:ro" \
ghcr.io/archmax-ai/automation:1.5.0
docker logs -f archmax

The container needs nothing --cap-drop ALL removes, and with it no process the container starts can read another’s environment, the variables you pass included (see the image).

The entrypoint says what it started:

[entrypoint] nginx :8080 -> api 127.0.0.1:3001 (+ dispatcher), access log: errors

The API’s lines follow tagged [api], the dispatcher’s [dispatcher]. A missing or invalid variable, or an invalid config, stops that process with a message naming the variable or the config path. The entrypoint restarts it every two seconds, so the container stays up while that process cannot start: fix the setting and restart the container. A config entry whose placeholder names an unset variable is left out instead, with a [config] line naming the entry and the variable.

Before the API listens and the dispatcher takes a job, each brings the database up to date. On a fresh database that means creating every collection’s schemaVersion index and nothing else: there is no stored document for a data update to rewrite, and the boot logs nothing about it. A later release that changes what a collection stores rewrites the stored documents the same way when it first starts (see data updates at boot).

When the API is up, GET /api/health answers with the release it runs:

Terminal window
curl -s http://localhost:8080/api/health
# {"status":"ok","version":"1.5.0"}

The image’s own health check probes the same route on the internal API port every 30 seconds. Open the public origin in a browser to sign in: the web app reads its sign-in settings from the API, and in OIDC sign-in the identity provider’s SPA application has to list that origin (see sign-in).

Building needs only Docker, from the repository root:

Terminal window
docker build -t archmax .
docker build --build-arg APP_VERSION=1.5.0 -t archmax:1.5.0 .

Without APP_VERSION the image reports dev. It runs the same way as the published image, and the image reference describes what it contains. To keep it running, see operating a deployment.