License
license.conf configures how the Enterprise API activates its license, where it contacts walt.id's license service, and which seed material to use on first startup.
Licensing is a base feature. The file is required. After the first successful activation, the stack stores the bound credential and installation key in MongoDB. Later restarts reuse that persisted state, so an online credential offer is never redeemed twice.
First startup needs exactly one seed option: seedCredential or seedCredentialFile. Configuring both fails startup.
For the full activation flow, see Licensing.
Example File
# URL used for online activation, heartbeat renewal, and usage reporting.
licenseServerUrl = "https://license.walt.id"
# Online first activation — uncomment and paste the offer walt.id provides.
# seedCredential = "openid-credential-offer://..."
# Raw credential seed — recovery or migration when a signed SD-JWT VC is already available.
# Do not set this together with seedCredentialFile.
# seedCredential = "eyJ..."
# Offline or air-gapped activation — mount both files, then uncomment both lines.
# Keep installation-key.json inside your environment; never send it to walt.id.
# seedCredentialFile = "/license/offline-license.waltlicense"
# installationKeyFile = "/license/installation-key.json"
Fields
licenseServerUrl
String — Base URL of walt.id's license service. Used for online activation, heartbeat renewal, and usage reporting.
- Default —
"https://license.walt.id" - Use the URL walt.id gives you for your environment. Connected deployments need outbound access to this host.
Heartbeat interval and startup refresh timeouts are walt.id policy. They are not configured in this file.
seedCredential
String — First-start license material when you are not mounting a file.
Use one of:
- OpenID credential offer — e.g.
"openid-credential-offer://...": walt.id returns this when they create an online license. The stack redeems it once on first startup, then stores the issued credential. - Raw SD-JWT VC — e.g.
"eyJ...": a signed license credential you already have. Use this for controlled migrations or recovery, not for a fresh online offer.
Leave the field unset (or commented) after activation if MongoDB already holds the bound credential. A previously redeemed offer cannot be redeemed again — request a fresh offer from walt.id if first activation failed after the offer was consumed.
seedCredentialFile
String (optional) — Path to a raw offline license VC or a checksummed .waltlicense bundle.
- Use with air-gapped / offline licenses.
- A path ending in
.waltlicenseis treated as a bundle. Other files are treated as a raw credential and must be offline licenses. - Do not set this together with
seedCredential. - On later restarts, persisted MongoDB state is used. A mounted bundle with a newer
issuedAtis treated as an explicit renewal.
installationKeyFile
String (optional) — Path to the private installation key that matches an offline license.
- Required for first-start offline activation when walt.id bound the license to a key you generated in your environment.
- The file must contain a private key.
- Keep this file inside your environment. Never send it to the license server.
- After first activation, the fleet key is stored encrypted in MongoDB. All replicas share that stored key. A configured file must match the stored fleet key or startup fails.
Online activations generate the installation key automatically and persist it. You do not set installationKeyFile for a normal online offer.
LICENSE_STATE_ENCRYPTION_KEY
This value is not in license.conf. Supply it as an environment variable or JVM system property on every replica.
The key encrypts the persisted license credential and fleet installation private key in MongoDB.
| Requirement | Detail |
|---|---|
| Name | LICENSE_STATE_ENCRYPTION_KEY |
| Length | At least 32 characters |
| Scope | Same value on every replica of one deployment |
| Backup | Back it up together with MongoDB |
A missing or too-short key fails startup. Changing the key without first re-encrypting the stored rawVc and installationKeyJwk makes existing license state unreadable. Live dual-key rotation is not supported.
Docker
docker run -p 3000:3000 \
-v $(pwd)/config:/config \
-e LICENSE_STATE_ENCRYPTION_KEY="{your-32-plus-character-secret}" \
waltid/waltid-enterprise-api
Docker Compose
Add the variable to the Enterprise API service (or to .env and interpolate it):
waltid-enterprise:
environment:
- LICENSE_STATE_ENCRYPTION_KEY={your-32-plus-character-secret}
volumes:
- ./config:/config
Kubernetes
Store the key in a Secret and reference it from the Deployment. You can also inject the online offer through the same Secret using HOCON optional substitution in license.conf:
seedCredential = ${?LICENSE_SEED_CREDENTIAL}
seedCredentialFile = ${?LICENSE_SEED_CREDENTIAL_FILE}
installationKeyFile = ${?LICENSE_INSTALLATION_KEY_FILE}
licenseServerUrl = "https://license.walt.id"
apiVersion: v1
kind: Secret
metadata:
name: waltid-enterprise-license
type: Opaque
stringData:
state-encryption-key: "{your-32-plus-character-secret}"
seed-credential: "openid-credential-offer://..."
env:
- name: LICENSE_STATE_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: waltid-enterprise-license
key: state-encryption-key
- name: LICENSE_SEED_CREDENTIAL
valueFrom:
secretKeyRef:
name: waltid-enterprise-license
key: seed-credential
optional: true
For offline Kubernetes activation, mount the .waltlicense bundle and installation-key.json (for example at /license/offline-license.waltlicense and /license/installation-key.json) and set the matching *-file secret keys to those paths.
Related Configuration
dev-modein_features.conf— A development license requiresdev-modeto be enabled. A production license refuses to start whendev-modeis enabled.- Feature allow-list —
_features.confstill applies, but a feature must also be allowed by the active license.
