Renew the license key
When you finish this page, your deployment renews its own non-production license key, by hand or on your own schedule.
A license key runs until its date (When a key expires). How you get the next one depends on where the key came from:
- A production key is renewed with your contract: write to contact@kindgi.com.
- A non-production key from access.kindgi.com
can be renewed by the deployment itself. You enroll the deployment once.
Then you run
kindgi license renewwhenever you like, by hand or from your own scheduler. Nothing calls Kindgi unless you run it. You can also sign in at access.kindgi.com for a new key.
Before you start
Section titled “Before you start”- A non-production key from access.kindgi.com, and the GitHub login you sign in there with.
- The
kindgiCLI, 0.1.7 or later, on a machine that can read and write where your keys are kept. It runs from any folder asnpx --yes @kindgi/cli@0.1(Install). Inside a pack project,pnpm exec kindgiruns the project's pinned CLI instead. - A place for each key, from Where the keys are kept.
Where the keys are kept
Section titled “Where the keys are kept”kindgi license reads and writes these, each named by a reference:
- the license key (
--key), where the runtime reads it; - the renewer's private key (
--renewer), whichenrollmakes. It never leaves where you keep it, and it's never printed; - the runtime's own token (
--runtime-token), read only, when a renewal carries counts (--runtime).
Give each flag where the value is kept, never the value itself. A flag that isn't a reference is refused without repeating it, in case it's the secret.
| Reference | Where |
|---|---|
file:<path> |
A whole file, such as a mounted secret. |
env-file:<path>#<NAME> |
One line of an env file, such as kindgi.env. The other lines are kept as they are. |
gcp:projects/<project>/secrets/<name> |
Google Secret Manager: reads the latest version, writes a new one. |
azure:https://<vault>.vault.azure.net/secrets/<name> |
Azure Key Vault: reads the current version, writes a new one. |
aws:<region>:<name>, or aws:<the secret's ARN> |
AWS Secrets Manager: reads AWSCURRENT, writes a new version. |
A new version leaves the old ones, so a runtime that reads the latest
version gets the new key at its next start. A file is replaced in one step,
and keeps its mode. A new file is created with the mode 0600.
The cloud stores sign in as the platform's own identity:
- Google: the metadata server on Cloud Run and Compute Engine, else
gcloud auth print-access-token. - Azure: the managed identity, else
az account get-access-token.KINDGI_AZURE_CLIENT_IDnames a user-assigned identity. - AWS: the first of these that answers:
- the environment:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEYandAWS_SESSION_TOKEN; - a web identity:
AWS_ROLE_ARNwithAWS_WEB_IDENTITY_TOKEN_FILE; - the container's credentials;
- the instance's role, through IMDSv2;
- the AWS CLI's, from
aws configure export-credentials.
- the environment:
Whatever runs renew needs to read these, and to write the license key's.
1. Enroll the deployment, once
Section titled “1. Enroll the deployment, once”enroll makes the deployment's renewer: a key pair whose public half
access.kindgi.com trusts.
npx --yes @kindgi/cli@0.1 license enroll --for <your GitHub login> --renewer gcp:projects/acme-prod/secrets/kindgi-license-renewer--foris the GitHub login you sign in to access.kindgi.com with. The renewer works for it alone.--reneweris where to keep the renewer's private key, as a reference from Where the keys are kept.
enroll keeps the private key at --renewer. It prints the renewer's id
(lr_…), a line to add at access.kindgi.com (kgi_lrp_…), and the renew
command to run next:
Renewer lr_c1DXmGBUpkAT6wd10BARbp: its private key is in ….
Add this deployment on https://access.kindgi.com, signed in as …, under "Renew the key from your deployment":
kgi_lrp_…
Then renew the key whenever you like, by hand or on your own schedule:
kindgi license renew --key <where the license key is> --renewer …Run enroll again with the same --renewer, and it reuses the key it finds
there. --replace makes a new one instead. The old one stops working once
you add the new line.
2. Add the renewer at access.kindgi.com
Section titled “2. Add the renewer at access.kindgi.com”Sign in at access.kindgi.com as the login you gave --for. Under Renew the
key from your deployment, add the kgi_lrp_… line that enroll printed.
access.kindgi.com keeps only the renewer's public key.
3. Renew
Section titled “3. Renew”renew asks access.kindgi.com for the key's next version, and writes it
where the runtime reads the key:
npx --yes @kindgi/cli@0.1 license renew --key gcp:projects/acme-prod/secrets/kindgi-license-key \ --renewer gcp:projects/acme-prod/secrets/kindgi-license-renewer--keyis where the license key is kept, and where the new one goes.--reneweris whereenrollkept the renewer's private key.- With a
kindgi.env,--env-file kindgi.envstands for--key env-file:kindgi.env#KINDGI_LICENSE_KEY. --runtime <url>with--runtime-token <ref>: this deployment's runtime, and where its own token (KINDGI_API_TOKEN) is kept, as a reference from Where the keys are kept. The renewal then carries counts of the deployment's use since the current key was issued (What renewing sends).<url>is the runtime's URL asKINDGI_API_URLgives it, path included, over http or https, with no credentials in it.- Counts are for a non-production key: a production key's renewal carries none, and the runtime isn't asked.
- They need the CLI and the runtime at 0.1.8 or later. Without them, the key still renews.
renew checks the answer offline before it writes anything: Kindgi's
signature, the same licensee and use, and no earlier end date. It writes
only a key that's new, and prints one line:
renewed: <name>'s <use> key, until <date> (renewer lr_…), and that the runtime uses the new key from its next start. Until then, the runtime runs on the key it started with.unchanged: …when there's no newer key. A non-production key gets its next one in its last 30 days.
With --runtime, a line says what the renewal carried:
counts: sent (<runs> runs, <people> people, <n> in production since <date>, runtime <version>). The, <n> in productionpart comes only from a runtime that can put projects in production.counts: not sent (<why>); this renewal goes without them.when there are none to send: a production key's renewal, a token that can't be read or sent, or a runtime that couldn't say (no answer, a 404 from a runtime that doesn't report its use, a refusal, an error, or an answer that isn't counts, as access.kindgi.com reads them). The key still renews.
On a refusal, the line goes to stderr, before refused (…).
In the key's last 30 days, renew adds a line that starts
⚠ It expires in <N> days. It says how to get a key if renew keeps
answering unchanged.
A refusal or a failure goes to stderr and exits 1, so your scheduler's
alerting sees it. The key is left as it was. A failure says what's wrong.
Here, a scheduled run on Azure for a deployment that wasn't enrolled:
There's no renewer key in the Key Vault secret license-renewer (vault …). Enroll this deployment first: kindgi license enroll --for <your GitHub login> --renewer <where to keep its key>.A refusal from access.kindgi.com names its code, refused (<code>): …:
| Code | What to do |
|---|---|
unauthorized |
Enroll the deployment, and add its line at access.kindgi.com. |
stale-request |
Check the machine's clock: it's more than 5 minutes off. |
replayed |
Run renew again: each request is used once. |
rate-limited |
Wait an hour, then run renew again: too many renewals came for this key this hour. |
renewer-stopped |
Its renewal was stopped at access.kindgi.com. Enroll it again, or sign in there for a key. |
not-entitled |
A production key is renewed with your contract: write to contact@kindgi.com. |
term-ended |
The contract's term has ended, and the key you have runs until its own date. Write to contact@kindgi.com to extend the term. |
key-revoked, denied |
Write to contact@kindgi.com. |
held-for-review |
This renewal's counts are above what a non-production key covers, so it got no new key: write to contact@kindgi.com about a production license. Kindgi can release the deployment after a review, and its renewals then aren't held until a date. The key you have runs until its own date. A renewal before the key is due gets the same key back. |
On a schedule
Section titled “On a schedule”Any scheduler that can run the CLI will do: cron, a CI schedule, or a scheduled job. Once a day is plenty.
On Azure, the Terraform module runs it for you
(Azure Container Apps). Enroll first. Then set
license_renewal_schedule, a cron in UTC, and apply:
- The module adds a Container Apps job that runs
kindgi license renewon the runtime image, as an identity of its own. That identity reads the license key and the renewer's key, and can only set the license key. - Two alerts come with it: a run that failed, and a key within 7 days of its end.
license_renewer_secretnames the renewer's secret,license-renewerby default. The outputslicense_enroll_commandandlicense_renew_commandprint the two commands for this deployment.
The module's README has the details.
What renewing sends
Section titled “What renewing sends”The renewal request: the renewer's id, the time and a one-time value, signed
with the renewer's private key. No license key, run or data leaves the
deployment. Nothing is sent between runs of renew.
With --runtime, the request also carries counts of the deployment's use
since its current key was issued, signed with the rest. renew reads them
from the runtime (GET /v1/license/usage, which only the deployment's own
token, or a system key holding system:license, can read):
- runs: the runs started, not counting dry runs, replays, evals or the runs another run starts;
- people: the distinct people who started runs or decided approvals, counted in each tenant and summed, so a person in two tenants counts twice;
- projects in production, from a runtime that can put projects in production;
- the runtime's version, and the period they cover.
A tenant the runtime can't count is left out, and its log names it (a
warning under license), so the counts can be lower than the use. When it
can't count any of its tenants, it answers an error instead, and the renewal
goes without counts.
They're counts only: no content, names or ids. Until the date on Kindgi's
privacy page, access.kindgi.com
keeps only whether a renewal carried counts. From that date, it keeps them
with the renewal's record, kept 400 days, and the latest ones with the
deployment's renewer, kept until the account is deleted. Kindgi reads them to
see production-like use of non-production keys. Above levels Kindgi sets, a
non-production key's renewal is held for review once a new key is due
(held-for-review).
The runtime's warnings
Section titled “The runtime's warnings”From 30 days before the key's date, the runtime's banner warns, and ends with how to renew:
- For a non-production key from access.kindgi.com, that's the
renewcommand, or signing in at access.kindgi.com. The command has this deployment's--keyand--renewerwhen it setsKINDGI_LICENSE_KEY_REFandKINDGI_LICENSE_RENEWER_REF, as the Azure module does. - For a production key, it's contact@kindgi.com.
A tenant admin sees a line on every console page too.
- Licensing: which key a deployment needs, and what happens when one expires.
- Azure Container Apps: the module that renews on a schedule.
- Operate a self-hosted runtime: health, backups, upgrades and rotating keys.