Upgrade to Enterprise
Activating the Enterprise edition does not reinstall CentralOps. You swap the Community images for the Enterprise images (the same product, with the paid modules compiled in) and provide your license. Without a valid license, the Enterprise features stay blocked (the image keeps running as Community) — so the upgrade and the downgrade are reversible.
This page is about changing edition (Community → Enterprise). To update from one
version to a newer one (e.g. 1.1.0 → 1.2.0), see
Upgrade to a newer version.
What you will need
The license comes as two files, and both are required:
| File | What it is | Where it goes |
|---|---|---|
segark-pipeline-license-<kid>.jwt | The signed (EdDSA) license token. | CENTRALOPS_LICENSE_TOKEN (or the Settings → License screen). |
key.prod.pem | The public key the product uses to verify the token offline. | A directory pointed to by CENTRALOPS_LICENSE_KEYS_DIR. |
The token alone is not enough: without key.prod.pem in the keyring, the product
can't verify the signature and answers unknown key id: 'key.prod' — staying on
Community by design. Always download both files.
Overview
segark.com portal Registry Run
┌───────────────────┐ ┌────────────────┐ ┌──────────────────────────┐
│ License page: │ ───▶ │ docker login → │ ───▶ │ start the EE images with │
│ token + key.pem │ │ pull EE images │ │ token + mounted keyring │
└───────────────────┘ └────────────────┘ └───────────┬──────────────┘
▼
edition=enterprise ✅
1. Download the license from the portal
- Subscribe to a plan on the portal (segark.com). The license is issued to your account.
- Sign in to the portal and open the License page.
- Download both files:
- Download token (.jwt) — the signed license token.
- Download key (key.prod.pem) — the public keyring key.
The page itself shows the "How to activate" summary with these steps.
2. Authenticate to the registry
The Enterprise images are private on the GitHub Container Registry:
ghcr.io/segark-oficial/centralops-ee (API/workers) and
ghcr.io/segark-oficial/centralops-ee-frontend (frontend). Use the pull credential
provided with your subscription (portal install bundle, or support@segark.com):
echo "<credential password>" | \
docker login ghcr.io -u "<credential username>" --password-stdin
The token goes through stdin so it never lands in your shell history.
The pull credential only controls the image download. The real feature activation is the license, verified offline inside the product.
3. Start with the Enterprise images
EE tags follow the Core version: vX.Y.Z-ee tracks the release (e.g. v1.0.1-ee)
and vX.Y.Z-ee.<sha> is immutable (e.g. v1.0.1-ee.2e8917d — prefer this one in production).
Docker Compose
Put the public key next to the compose files and configure compose/.env:
mkdir -p compose/license-keys
cp ~/Downloads/key.prod.pem compose/license-keys/
In compose/.env, add:
CENTRALOPS_LICENSE_TOKEN=<contents of the .jwt file>
LICENSE_KEYS_DIR=./license-keys
CENTRALOPS_EE_IMAGE=ghcr.io/segark-oficial/centralops-ee:v1.0.1-ee
CENTRALOPS_WEB_EE_IMAGE=ghcr.io/segark-oficial/centralops-ee-frontend:v1.0.1-ee
And start CE + the Enterprise overlay (from the project root):
docker compose -f compose/docker-compose.yml -f compose/docker-compose.ee.yml pull
docker compose -f compose/docker-compose.yml -f compose/docker-compose.ee.yml up -d
Compose only applies docker-compose.ee.yml when it is passed with -f — and that
holds for every future command. A docker compose up -d (or pull, or any
recreation) with only the base file silently downgrades the stack to Community:
the image goes back to CE, the keyring mount disappears and the next activation fails
with unknown key id. To make the overlay permanent, set in compose/.env:
COMPOSE_FILE=docker-compose.yml:docker-compose.ee.yml
With that, a plain docker compose up -d (run from inside compose/, no -f) already
applies the overlay, and day-2 commands won't downgrade the stack.
With key.prod.pem mounted (the LICENSE_KEYS_DIR above), you can leave
CENTRALOPS_LICENSE_TOKEN out and paste the token on the product's
Settings → License screen as an administrator. The license is stored (encrypted) in
the database and survives restarts.
The License screen also exists — and accepts the paste — on a Community stack brought
up without the overlay; in that case the container's keyring is empty and the
activation fails with exactly unknown key id: 'key.prod'. Before pasting, confirm the
key is visible inside the container:
docker compose -f compose/docker-compose.yml -f compose/docker-compose.ee.yml \
exec centralops ls /licensing
# key.prod.pem
Kubernetes (Helm)
Create the image pull secret (the chart uses ghcr-secret by default) and upgrade
pointing at the images, token and keyring:
kubectl -n centralops create secret docker-registry ghcr-secret \
--docker-server=ghcr.io \
--docker-username="<credential username>" \
--docker-password="<credential password>"
helm upgrade centralops kubernetes/helm/centralops -n centralops \
--set image.repository=ghcr.io/segark-oficial/centralops-ee \
--set image.tag=v1.0.1-ee \
--set frontendImage.repository=ghcr.io/segark-oficial/centralops-ee-frontend \
--set frontendImage.tag=v1.0.1-ee \
--set secrets.licenseToken="<contents of the .jwt file>" \
--set-file "secrets.licenseKeyring.key\.prod\.pem=./key.prod.pem" \
-f values.override.yaml
The chart mounts the keyring on every pod and sets CENTRALOPS_LICENSE_KEYS_DIR
automatically. For GitOps/ExternalSecrets, use secrets.existingSecret and
secrets.existingLicenseKeyring instead of the inline values.
4. Verify
At boot, the API logs the resolved edition:
docker compose -f compose/docker-compose.yml -f compose/docker-compose.ee.yml \
logs centralops | grep edition=
# edition=enterprise plan=mssp features=3
You can also check it in the UI, under Settings → License (shows the edition, plan and active features).
If you see edition=community, the license wasn't found or couldn't be verified:
unknown key id: 'key.prod'— the keyring the container sees is empty or does not containkey.prod.pem. Follow the walkthrough below.- Missing/expired token — check
CENTRALOPS_LICENSE_TOKEN(or re-activate through the License screen) and the validity on the portal.
An Enterprise install whose license does not cover a feature (a plan that doesn't
include it, a missing license, or one expired beyond the grace period) refuses the
corresponding action with the license_required state — for example, when syncing
a partner's tenants. In that case the fix is not the keyring: check the plan and the
validity under Settings → License or on the portal.
Fixing unknown key id
The dominant cause is an empty keyring inside the container — usually because the
stack was brought up (or recreated) without the Enterprise overlay. The
key.prod.pem can be perfectly fine on the host and still never reach the container.
Diagnose from the inside out:
1. Image and mount — is the API container running the EE image, with the
/licensing mount?
docker inspect --format '{{.Config.Image}} {{json .Mounts}}' \
$(docker compose -f compose/docker-compose.yml -f compose/docker-compose.ee.yml ps -q centralops)
2. What the process sees — the variable and the directory inside the container:
docker compose -f compose/docker-compose.yml -f compose/docker-compose.ee.yml \
exec centralops sh -c 'echo $CENTRALOPS_LICENSE_KEYS_DIR; ls -la /licensing'
3. Permissions — the API runs as uid 10001: the .pem must be readable by it
(file 0644, directory 0755). A key.prod.pem with 0600 root:root is silently
ignored.
4. Keyring logs — the boot logs what was (or wasn't) loaded:
docker compose -f compose/docker-compose.yml -f compose/docker-compose.ee.yml \
logs centralops | grep -iE 'skipping|license keyring'
If the mount or the variable is missing, recreate the containers with both -f
files (up -d) — docker compose restart does not apply new mounts or environment
variables. With the keyring fixed, paste the token again on the License screen
without restarting anything: the keyring is re-read on every activation (and on
every periodic refresh). On Helm, check secrets.licenseKeyring and the /licensing
mount on the pods.
Downgrade
Go back to the Community images (or remove CENTRALOPS_LICENSE_TOKEN) and start again —
the platform falls back to Community by design, without losing data.
Need help?
Talk to support@segark.com.