Licensing Overview
How KubeMQ licensing works — key or file, the lease, boot and per-minute checks, the fail-open window, revocation, exit code 3, and each deployment mode.
Every KubeMQ server needs a license to start, in every deployment mode — standalone binary, Docker, Kubernetes with the operator, and Kubernetes without it. There is no unlicensed or "community" mode. This page explains the model; the pages that follow show how to obtain and supply a license for each situation.
Start a 30-day trial
Get a free trial key from kubemq.io/trial — one installation, 30 days, no sales call.
Use a license key
KUBEMQ_LICENSE_KEY for Docker, Compose, Helm and raw manifests; activation, caching, regeneration.
Air-gapped installations
A signed license file verified locally — no network access, ever.
Kubernetes
CRD fields, the operator's role, the lease cache Secret, and the RBAC the server needs.
Troubleshooting
Every licensing log line, its cause, and its fix.
Usage reporting
Exactly what an online server sends, how often, and what is never sent.
Key or file
There are two ways to license a server. They differ only in whether the server talks to the licensing service.
| License key (online) | License file (offline) | |
|---|---|---|
| What you receive | A 43-character key, shown once when it is issued | An armored text file (-----BEGIN KUBEMQ LICENSE-----) |
| How you pass it | KUBEMQ_LICENSE_KEY | KUBEMQ_LICENSE_FILE (a path) or KUBEMQ_LICENSE_DATA (the contents) |
| Network | Activates once per installation, then refreshes hourly against https://license.kubemq.io | None. The file is verified locally with the public key embedded in the server binary |
| Who it is for | Trials, and any installation that can reach the internet | Air-gapped networks, and networks whose egress rules cannot allow the licensing endpoint |
| Usage reporting | Yes — see Usage reporting | No — an offline server makes zero outbound connections |
| Revocation | Possible, by a signed and confirmed revocation (below) | Impossible for a file already issued; files expire and are reissued |
If both a key and a file are set, the file wins and the server logs a warning. If neither is set, the server refuses to start with exit code 3.
The license key and the license id are different things. The id is a public handle that appears in logs, the dashboard and usage reports. The key is a secret used only to activate; it is stored by KubeMQ only as a hash. A key can be regenerated without affecting running servers — they hold a lease, not the key.
The lease
An online server never runs on the key itself. On first boot it activates: it sends
the key plus its installation fingerprint to the licensing service and receives a
lease — a signed token valid for 7 days (24 hours for trials). The lease is
cached on disk under the server's store directory (<store>/license/) and is what the
server verifies from then on.
While the server runs it refreshes the lease every 60 minutes (±10% jitter). Each refresh returns a freshly signed lease, so the 7-day window keeps sliding forward for as long as the server can reach the endpoint. If a refresh fails the server keeps running on the cached lease and retries with backoff (1, 2, 5, 15, then 30 minutes).
The file used by air-gapped installations is the same kind of token with a longer validity — up to one year — and no refresh.
What is checked, and when
- At boot. The server resolves its input (file, data, then key), verifies the signature, the signing key id, the algorithm and the expiry, and checks that the token was issued to this installation's fingerprint. An online server with no cached lease activates first. Any failure here refuses to start.
- Every minute. The server checks the token it verified at boot, locally and with no network call: expiry (plus grace, see below), its own clock against the persisted high-water mark, and the warning conditions (over cap, silent, clock skew, revocation seen). It does not re-verify the signature or the fingerprint every minute — those were settled at boot, and a cache file edited while the server runs is caught at the next boot. This is what catches an expired file, an exhausted grace window, or a clock rolled backwards.
- Every hour (online only). The refresh described above. A changed entitlement — for example a trial converted to a paid plan, or an extended expiry — arrives with the next refresh, within an hour.
- Every 15 minutes (online only). The usage report. See Usage reporting.
Hard stop, and the fail-open window
The rule is simple: no valid license, no running server. A server with no license input, an invalid signature, a wrong fingerprint or an expired file does not start. A running server whose license is revoked, or whose lease and grace are exhausted, drains and exits.
The one thing that never stops a running server is a network problem. If the
licensing service is unreachable — DNS failure, outage, firewall change — the server
keeps running on its cached lease. When the lease's 7 days pass, it enters a grace
period (grace_days, default 7, set per license between 0 and 30; trials have 2
days). During grace it runs normally and logs a warning every minute with the days
left. Only when lease and grace are both exhausted does it drain and exit.
The maximum an online server runs without ever reaching the licensing service is
lease + grace: 7 days + grace_days. For a trial that is 24 hours + 2 days, which is
why a trial server must reach the endpoint at least every 3 days.
Revocation: signed, confirmed, drained
A revocation is the only way a running server is stopped before its lease and grace run out, and it is deliberately hard to trigger:
- Signed. A revocation is a token signed by the licensing service with the same key that signs leases. An HTTP error — a 403, a 401, a 404, a 5xx — never stops a server on its own. The server keys on the presence of a valid signed revocation, not on a status code.
- Confirmed. The server counts a revocation only after seeing three fresh
assertions at least 10 minutes apart — both the assertion's issue time and the
moment the server received it must be 10 minutes after the previously counted one,
so a burst of freshly minted assertions is one confirmation, not three. After the
first one it re-polls every 10 minutes and reports
revocation.seen_countinGET /api/v1/license. A replayed assertion (wrong nonce) is not counted. Counted assertions are persisted (<store>/license/revocation.json): a restart with one or two on record resumes the 10-minute polling with the count intact. - Drained. After the third confirmation the server stops accepting new connections
and subscriptions, waits for the drain window (
KUBEMQ_LICENSE_DRAIN_SECONDS, default 300) plus, in a cluster, a per-node stagger (a hash of the node's host name modulo 600 seconds, so nodes leave one at a time), sends a final usage report withactivity: "stop", and then stops with exit code 3.
Revocations are issued only by an explicit, typed administrative action. Nothing automatic — silence, exceeding an installation cap, rate limiting, an ingest error — produces one. A disabled license simply stops receiving new leases and runs out at lease
- grace.
Commercial expiry versus lease expiry
Every token carries two dates:
| Claim | Meaning | When it passes |
|---|---|---|
exp — lease expiry | How long this particular token is valid: 7 days online (24 h trial), up to 1 year offline | Online: grace starts, and refresh keeps trying. Offline: the server drains and exits (with a 5-minute leeway) |
kmq.license_exp — commercial expiry | The end of your contract or trial | The licensing service stops issuing new leases. The running server keeps going until its current lease + grace runs out, then stops |
Both are shown in GET /api/v1/license (lease_expires_at, license_expires_at) and
by kmq license, together with run_until — the exact moment the server will drain if
nothing changes.
Exit code 3
A licensing refusal at boot, and a licensing-driven stop at runtime, always exit with code 3. Exit 1 remains a durability fault and exit 0 a clean shutdown, so a restart policy or a probe can tell them apart. Every licensing log line that refuses or stops ends with a link into Troubleshooting naming the exact cause.
Enforcement by deployment mode
The server itself enforces the license in every mode. Kubernetes detection changes only
how the installation fingerprint is derived and how source.type is reported in usage;
it never changes whether licensing applies.
Standalone binary
| Input | KUBEMQ_LICENSE_KEY, or KUBEMQ_LICENSE_FILE / KUBEMQ_LICENSE_DATA in the environment |
| Fingerprint | A random id generated on first boot, persisted at <store>/license/instance.id |
| Cache | <store>/license/ — must survive restarts, so keep the store on a persistent path |
| Enforced by | The server |
Docker
| Input | -e KUBEMQ_LICENSE_KEY=…, or a mounted file with -e KUBEMQ_LICENSE_FILE=/path |
| Fingerprint | Persisted at <store>/license/instance.id inside the store volume |
| Cache | <store>/license/ — mount a volume at /kubemq/store; without one every container restart is a first boot and a new installation |
| Enforced by | The server |
Kubernetes with the operator
| Input | spec.licenseKey / spec.licenseFile on the KubemqCluster, or spec.licenseKeySecretRef / spec.licenseFileSecretRef pointing at a Secret; the operator injects KUBEMQ_LICENSE_KEY or KUBEMQ_LICENSE_DATA into the pods |
| Fingerprint | The UID of the kube-system namespace, read by the server through a ClusterRole the chart installs |
| Cache | <store>/license/ on the PersistentVolumeClaim; the operator additionally copies the last good lease into a Secret named <cluster>-license-cache so a pod rescheduled onto a fresh volume does not start from a first boot |
| Enforced by | The server. The operator only refuses to create or update a cluster whose offline file fails signature or revocation checks (a key is never verified by the operator), clamps the replica count to the installation cap on first create when it knows the cap, and blocks growing a live cluster past the cap (condition ReplicasOverLicenseCap) |
Kubernetes without the operator
| Input | KUBEMQ_LICENSE_KEY or KUBEMQ_LICENSE_DATA from a Secret via envFrom / secretKeyRef |
| Fingerprint | The UID of the kube-system namespace — needs a ServiceAccount with get on namespaces for kube-system; without it the server falls back to a persisted id and logs a warning |
| Cache | <store>/license/ on a PersistentVolumeClaim (required) |
| Enforced by | The server |
Details for both Kubernetes modes are in Kubernetes.
What licensing cannot do
- A self-built or patched server binary can bypass any check. The supported artifact
is the signed official image; the server reports its image digest in usage reports
when the deployment injects it as
KUBEMQ_IMAGE_DIGEST(see Usage reporting). - An offline file can be copied to another machine that has the same fingerprint list. Its use is bounded by the file's expiry (at most one year) and by your contract, not by cryptography.
- The signing key is rotated by a server release. A compromised key stays trusted until the release that retires it is adopted.
Was this page helpful?