Repository navigation
Multi Container
Documentation for the image tag 1.0.0-rc1.1. See Versions for the documentation of a release.
One container per service (identity, API, web, ACME, EST, queue consumer) plus Redis, all from the same image on one host with one shared volume. Choose it when you need EST, or want ACME and EST reachable on a wider network without exposing the API, identity or web UI.
It is not scale-out. Run exactly one of each service.
-
Get the image: Requirements and Getting the Image. You need the
deploy/multi-container/folder from the same release (it holdsdocker-compose.ymland.env.example). -
Create your settings file:
cp deploy/multi-container/.env.example deploy/multi-container/.env
Edit
.env(values below). -
Provide an EST server certificate and key (see EST).
-
Start:
docker compose -f deploy/multi-container/docker-compose.yml \ --env-file deploy/multi-container/.env up -d
Services start in dependency order on health: Redis and identity, then the API, then web, ACME, EST and the queue consumer. Browse to http://<QERTUM_HOST>:8080 and sign in as admin, as described under Single Container.
| Variable | Required | Meaning |
|---|---|---|
QERTUM_IMAGE |
yes | Image reference |
QERTUM_HOST |
yes | Name or IP that browsers, ACME/EST clients and the other containers use. Not localhost: inside a container that is the container itself, and apiservice and webfrontend refuse to start (exit 64). On Docker Desktop, host.docker.internal works for a local trial |
QERTUM_EST_TLS_CERT, QERTUM_EST_TLS_KEY
|
yes | Host paths of the EST server certificate chain and key (PEM) |
QERTUM_DATA |
no | Host path or volume for /data (default: named volume qertum-data) |
QERTUM_SCHEME |
no |
http (default) or https for web, identity and API when a proxy terminates TLS for them. Never for ACME or EST |
WEB_PORT, IDENTITY_PORT, API_PORT, ACME_PORT, EST_PORT
|
no | Advertised and published ports (defaults 8080–8084). Containers always listen on 8080–8084 inside |
ACME_SCHEME |
no |
http (default) or https; the scheme ACME advertises. Use https only when the ACME container terminates TLS itself |
SEED_ADMIN_PASSWORD |
no | First-run admin password. Unset means password, which the first login forces you to change |
- Containers are named
qertum-<service>(qertum-apiservice,qertum-cache, ...). The backup scripts depend on these names; do not rename them. - Every Qertum container mounts the same
/data. The layout is the same as the single container's. - Redis is its own container on the internal network and is never published.
- Published ports: web, identity, API, ACME and EST. The queue consumer has none. To expose only ACME and EST beyond the LAN, bind those two ports to the outward interface and leave the others on the LAN: change the
ports:entries to"<ip>:<port>:<container port>".
EST re-enrollment (/simplereenroll) uses the client certificate as the credential, so the EST container terminates TLS itself. Mount a PEM certificate chain and key through QERTUM_EST_TLS_CERT and QERTUM_EST_TLS_KEY.
- The key must be readable by UID 1654, for example
chown 1654 tls.key && chmod 400 tls.key. - The service refuses to start without both files. It never falls back to plain HTTP.
- Clients must trust the issuer of that server certificate. Qertum does not issue it for you (a bootstrap circle); use your existing PKI, or a self-signed certificate for a lab.
By default Est:RequireHttps is on, so /simpleenroll over plain HTTP answers 401.
ACME clients sign the request URL into every request, and the service compares it with the scheme and host it sees. Behind a TLS-terminating proxy it answers "URL mismatch". This is a requirement, not a setting to work around. By default ACME speaks plain HTTP on ACME_PORT.
To have ACME serve TLS itself, add a Compose override for acmeservice that sets ASPNETCORE_URLS=https://0.0.0.0:8083, Kestrel__Certificates__Default__Path and Kestrel__Certificates__Default__KeyPath, and mounts the PEM files. Then set ACME_SCHEME=https in .env so the directory and order links advertise https.
To seal the key ring to a TPM 2.0 chip, pass the device and its group to every container with the opt-in override:
TPM_DEVICE=/dev/tpmrm0 TPM_GROUP=105 docker compose \
-f deploy/multi-container/docker-compose.yml \
-f deploy/multi-container/docker-compose.tpm.yml \
--env-file deploy/multi-container/.env up -dA TPM-sealed key never leaves that TPM, so a backup restored onto other hardware cannot decrypt the CA key. Read Backup and Restore before enabling it. It has been run on one x86_64 TPM 2.0 (migration to the TPM, restart, issuing before and after, leaving TPM storage again, a sealed backup that cannot be read without the TPM). Other TPMs, firmware TPMs, arm64 and a cleared or replaced TPM are not tested. Try it on a spare machine first.
- Take a backup with the single-container
backup.sh(Backup and Restore), then stop that container. - Point
QERTUM_DATAat the same host path and runup -d. The layout is identical, so nothing migrates. - Keep
QERTUM_HOSTand the ports the same so the issuer and redirect URIs do not change.
Qertum
Deploy
Use
Operate
- Configuration Reference
- Backup and Restore
- Identity Providers
- Issuer Compromise Recovery
- Upgrading
- Troubleshooting
Releases