Licensing and activation
Turn the built-in 30-day trial into your purchased package, online or across an air gap, and know what the appliance does when a licence lapses.
- Version: 0.4
- Role: admin_user
- Type: task
A CID222 licence is a small signed file bound to one appliance. You export an activation request,
send it to your CID222 contact, and upload the .lic file they return. The appliance never
contacts a licence server, so the whole procedure works with no internet on either side.
What do I need?
- Licence
- Any
- Role
admin_user
Prerequisites
- The appliance has completed the first-boot setup wizard.
- You can sign in to the dashboard with a tenant that has the admin_user role.
- Settings → License shows a non-empty installation id. A licence cannot be issued against an empty one.
- The appliance host clock is correct and disciplined by NTP — licence validity is bounded by dates.
- For the air-gapped path, removable media or an email path between the appliance's operator and a machine that can reach your CID222 contact.
What the appliance enforces
A fresh appliance runs a built-in 30-day trial at the Starter capability set, stamped from first boot rather than from the day the image was built. The trial is fully usable, but it does not unlock Professional or Enterprise features — ask your CID222 contact for a time-limited licence at that tier if you need to evaluate them.
The licence carries a tier, and the tier decides the capabilities. The appliance grants the union of the capabilities named in the file and the capabilities of its tier, so a feature added to the product after your licence was signed still works without a re-issue. Which capability belongs to which tier is generated from the code on the licence tiers reference.
| State | What it means | What the product does |
|---|---|---|
trial | No licence installed yet, inside the trial window | Runs at the trial tier, with a countdown banner |
valid | A licence verified and is inside its term | Normal operation |
expiring | Inside the warning window before expiry | Normal operation, with a banner |
grace | Past expiry, inside the grace period the licence itself names | Normal operation, with a banner |
expired / trial_expired | Past expiry and past grace, or the trial elapsed | Product routes answer 402 LICENSE_EXPIRED |
invalid | Nothing verifiable — no trust anchor, or the host clock rolled back | Product routes answer 402 LICENSE_EXPIRED |
A 402 is deliberately narrow. It blocks the product paths — chat, detection, inspection, image
and document analysis, and the key-validation endpoint the extension and the proxy call — and
leaves everything else working, including sign-in, the dashboard, the licence page and
Settings → System Updates, so the appliance can always be re-licensed without a rescue
procedure. Release images ship with
licence enforcement switched on (CID_REQUIRE_LICENSE), which means an appliance that cannot
verify a licence fails closed rather than running unlicensed.
Note
Each state change is written to the event log as LICENSE_EXPIRING, LICENSE_GRACE,
LICENSE_EXPIRED or LICENSE_TRIAL_EXPIRED, so a lapse can be alerted on in your SIEM instead
of waiting for someone to open a page.
Activate the licence
Open the licence page
Select Settings → License.
The page shows the current License state, Tier, Expires and Installation — the id your licence is bound to. On a trial it also shows how many days remain.
/assets/screenshots/license-page@0.4.pngExport the activation request
Select Export activation request.
A file named cid-activation-<installation-id>.json downloads. It carries the installation
id, the appliance's fingerprint, how strongly the identity is bound, whether the appliance
generated that identity itself, and the time it was exported — no customer data of any kind.
Send the request to your CID222 contact
Send the downloaded file to your CID222 contact from the machine you are working on.
Your contact issues a signed .lic file for your purchased package, bound to that installation
id.
Upload the licence file
Back on Settings → License, drop the .lic file on Drop your .lic file here, or select
Upload license (.lic) and pick it.
The appliance verifies the signature and the installation binding, installs the file, and the page switches to the licensed tier within a few seconds.
/assets/screenshots/license-page-activated@0.4.pngWarning
Transfer the .lic file as a binary attachment or over a checksum-verified copy, and do not open
it in an editor. A mail client that re-wraps the lines changes the bytes the signature covers,
and the appliance then rejects a genuine licence.
Renew, or move to a different package
Request the new file before the current one lapses
Send your CID222 contact the same activation request. The installation id has not changed, so the renewal binds to the same appliance.
A renewal and a package upgrade are the same operation: Starter to Professional to Enterprise is a licence re-issue, not a reinstall.
Upload it the same way
Select Settings → License, then upload the new .lic.
Capabilities expand immediately and the expiry date on the page moves out. The appliance keeps every setting and every record; nothing restarts.
Danger
Changing the appliance's installation identity invalidates the licence bound to the old one, and there is no self-service recovery — it takes a re-issued licence. Do not regenerate the identity on an appliance that already holds a licence.
Verify
- Settings → License shows License state as valid, the Tier tile naming your package, and an Expires date in the future.
- The Warnings tile is absent, or names only the soft-binding notice. A warning that the identity was generated by the appliance rather than derived from the machine is expected on a deployment where the host tooling never ran; it does not affect enforcement.
- Make one chat request. It succeeds rather than returning
402. - Open a page that belongs to your tier — the MCP servers page on Professional, SIEM export on Enterprise. It opens instead of reporting that the capability is not licensed.
If it fails
The upload is refused with a 400 naming the signature:
License upload fails with 400 "rejected: signature"
You might see: 400 rejected: signature · 400 rejected: ENOENT · License upload → 400 · licence file will not upload
Before you start
Checks
- 1
Verify the licence trust anchor exists on the host
diagnostics · appliance.license.trustAnchorPresent = true
- 2
Verify the appliance reports an installation id
diagnostics · appliance.license.installationId
- 3
Verify the host clock is disciplined by NTP
diagnostics · host.timeSynced = true
- 4
Read the licence state the gateway reports
GET /admin/license/status → {"state":"active|trial"}
Causes and fixes
| Reached when | Cause | Explanation, fix and verification |
|---|---|---|
| check 1 fails | missing-anchor (critical) | The licence-signing public key (/etc/cid/license-pubkey.pem) was never baked into this image, or was removed. Verification has nothing to check the signature against, so every licence — including a perfectly valid one — is rejected as forged. The API surfaces this as a 400 with a signature or ENOENT message rather than as a missing-key error, which is why the licence file gets blamed. Fix: Restore the trust anchor on the host and restart the gateway container, then upload the licence again. On an appliance the anchor is part of the image: an image that lacks it was built wrong and the fix is to re-run the host repair, not to hand-place a key of unknown provenance. Follow Licensing and activation; if the appliance was built from an image that shipped without the anchor, collect the support bundle and escalate rather than sourcing a key yourself. Verify: diagnostics · appliance.license.trustAnchorPresent = true If that does not apply: Attach the support bundle. The image build, not the appliance, is at fault. |
| check 2 fails | null-installation-id (critical) | The appliance reports no installation id, so no licence can have been issued for it and no licence can bind to it. This normally means the identity was never generated during first boot, or the file holding it is not readable by the gateway container. Fix: Re-run the first-boot identity step and confirm the id appears on Settings → License. Request a licence only once a stable id is shown; a licence issued against a null id is unusable. See Licensing and activation. Verify: diagnostics · appliance.license.installationId |
| check 3 fails | clock-skew (warning) | Licence validity is bounded by dates. A host clock that is wrong by more than the licence's grace window makes a valid licence appear not-yet-valid or expired, and the error surfaces at the same place as a signature failure. Fix: Correct the host clock and enable NTP or chrony, then restart the gateway container and upload the licence again. See Network prerequisites for the NTP egress the appliance needs. Verify: diagnostics · host.timeSynced = true |
| check 4 fails | wrong-licence-for-this-box (critical) | The trust anchor, installation id and clock are all correct, so the signature check is meaningful — and it fails. The licence was issued for a different installation id, was modified in transit (a mail client re-wrapping lines is the usual culprit), or was truncated. Fix: Re-download the licence file from the issuing portal, transfer it as a binary attachment or over a checksum-verified copy, and upload it again without opening it in an editor. If the installation id in the licence does not match this appliance, request a re-issue. Verify: GET /admin/license/status → {"state":"active|trial"} If that does not apply: Attach the support bundle and the installation id shown on Settings → License. |
Everything answers 402 although the wizard completed:
Every request returns 402 LICENSE_EXPIRED after the wizard completes
You might see: 402 LICENSE_EXPIRED · chat returns 402 after finishing setup · the dashboard loads but every action fails with payment required · product blocked immediately after setup
Before you start
Checks
- 1
Read whether licence enforcement is switched on for this deployment
diagnostics · appliance.license.requireLicense = true
- 2
Read the licence state the gateway resolved at boot
diagnostics · appliance.license.state = "active|trial"
- 3
Verify the licence trust anchor exists, since without it no licence can ever resolve as active
diagnostics · appliance.license.trustAnchorPresent = true
- 4
Check how long the installed licence has left
diagnostics · appliance.license.expiresAt
Causes and fixes
| Reached when | Cause | Explanation, fix and verification |
|---|---|---|
| check 3 fails | enforcement-on-without-anchor (critical) | CID_REQUIRE_LICENSE is true and the licence-signing public key is absent. The guard demands a valid licence, and verification cannot succeed without the anchor, so every licensed route answers 402 no matter what is uploaded. The appliance is enforcing a check it cannot pass. Fix: Restore the trust anchor and upload the licence, following License upload fails with 400 signature. Turning enforcement off is a deliberate, temporary measure for a lab only — never the fix on a customer appliance, because it disables the entitlement checks the tier relies on. Verify: diagnostics · appliance.license.trustAnchorPresent = true |
| check 2 fails | no-valid-license (critical) | Enforcement is on and the licence resolved to a state other than active or trial — missing, invalid or expired. The setup wizard does not install a licence, so a freshly completed appliance with enforcement on reaches exactly this state until one is uploaded. Fix: Upload the licence issued for this appliance under Settings → License. If no licence has been issued yet, request one against the installation id shown on that page. See Licensing and activation. Verify: GET /admin/license/status → {"state":"active|trial"} |
| check 4 fails | license-genuinely-expired (critical) | A licence is installed and verifies, but its validity period has ended. Enforcement then blocks the product routes while leaving administration reachable, so the appliance can be re-licensed without a rescue procedure. Fix: Upload a renewed licence. If the expiry looks wrong, check the host clock first — a skewed clock ages a valid licence out early and produces exactly this state. Verify: diagnostics · appliance.license.state = "active|trial" |
| check 1 fails | unexpected-402-without-enforcement (warning) | Enforcement is off, so the licence guard should not be blocking anything. A 402 in this state means the value the gateway read at boot differs from the value now configured — usually the container was started before the setting changed and has not been restarted. Fix: Restart the gateway container so it re-reads its configuration, then retry. If 402 persists with enforcement off, collect the support bundle: the effective configuration and the configured one disagree. Verify: diagnostics · appliance.license.requireLicense = false If that does not apply: Attach the support bundle, including the effective posture section. |
Two more symptoms have a shorter answer:
- A page or endpoint answers not licensed (
FEATURE_NOT_LICENSED) → the capability is not in your package. Check the licence tiers reference and ask your CID222 contact for a re-issue at the tier that includes it. - Creating a user is refused with
LIMIT_EXCEEDED→ the licence carries a seat cap and this appliance has reached it. Deactivating a leaver frees a seat; existing users are never blocked from signing in.
Next steps
- Licence tiers — the generated table of which capability each package entitles.
- Naming, DNS and TLS — the names and certificate your clients need before they will talk to the appliance.
- Update the appliance — updates never change your package; the licence file is what defines capabilities.
Last updated on