License

Your license is a signed token, verified locally. There is no license server, no activation call, and nothing to reach on the internet.

Your installation ID

A production license is bound to your installation's logical ID — never to a machine, a MAC address or a hostname, because pods and hosts are replaceable and your license should not care. The ID is generated on first start and stored in your database. An evaluation license is usually not bound, and can be issued before you install.

You see the ID when you create the first administrator — bootstrap-superadmin prints Installation ID: <uuid> — and in the backend log at every start:

docker compose logs backend | grep -i installation                            # Compose
kubectl -n <namespace> logs deploy/<release>-backend | grep -i installation   # Helm

Send it to Lutra Labs with your order reference, and tell us the release version you run. You receive the license token back.

Install it

The file is the simplest way:

PackageHow
ComposePut the token in secrets/lutraid_license, then docker compose restart backend
HelmCreate a Secret holding the token and set license.existingSecret, then kubectl rollout restart deploy/<release>-backend

Or install it through the API, with no restart. Sign in as an administrator first; the session is kept in cookies.txt:

BASE=https://id.example.gov.si            # your PUBLIC_BASE_URL
printf 'Admin email: '; read -r EMAIL
printf 'Password: '; stty -echo; read -r PASSWORD; stty echo; echo

printf '{"email":"%s","password":"%s"}' "$EMAIL" "$PASSWORD" \
  | curl -fsS -c cookies.txt -H "Origin: $BASE" -H 'content-type: application/json' \
      --data @- "$BASE/api/auth/sign-in/email" >/dev/null

printf '{"token":"%s"}' "$(tr -d '[:space:]' < license.lic)" \
  | curl -sS -b cookies.txt -H "Origin: $BASE" -H 'content-type: application/json' \
      --data @- "$BASE/v1/admin/license"

A token that cannot be installed is refused with 422 and the exact reason, and nothing is stored:

ReasonMeaning
malformedNot a LutraID license token — usually a truncated copy or paste
bad-signatureThe token was altered after it was signed
unknown-kidSigned with a key this release does not know. See Version compatibility
wrong-audienceNot a self-hosted license
not-yet-validIts validity starts in the future. Check the host clock
binding-mismatchBound to a different installation ID

An expired token is not refused: it installs, and the installation follows the expiry ladder below.

Check the state any time — this works before any license is installed too:

curl -sS -b cookies.txt -H "Origin: $BASE" "$BASE/v1/admin/license"

Renewal is the same operation. Nothing is deleted; licenses are append-only and the newest valid one wins.

What expiry does

Warn, then degrade. Never stop. An identity platform that stops issuing credentials at midnight because a purchase order took three weeks is not something we are willing to ship.

StateBehaviour
ValidEverything normal
Warning — approaching expiryBanner and a response header. Nothing degrades
Grace — past expiry, within the grace periodNon-dismissible banner. Nothing degrades
ExpiredConfiguration changes refused. No new issuers, verifiers, organisations, API keys or profiles. Enterprise feature configuration stops
MissingRuns normally for a 30-day onboarding window from first start, then behaves as expired. A missing or bad license file never stops a deployment from booting

These never stop, in any state

Credential issuance. Credential verification. Status-list publication. .well-known metadata. Key operations. Revocation. Existing-user login. Existing SSO login — an expired license will never lock an administrator out of their own identity provider. Data export.

Version compatibility

A license only verifies on releases that ship its signing key. If you are pinned to an older release and receive a license signed with a newer key, it is refused with unknown-kid.

Tell us your deployed version when you request a license or a renewal and this never comes up.

Was this page helpful?