---
title: "License"
description: "Configure license.conf and LICENSE_STATE_ENCRYPTION_KEY to activate and persist an Enterprise Stack license."
stack: "Enterprise Stack (commercial) — version 1.1.1"
stack_version: "1.1.1"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/setup/configurations/config-files/license
generated: 2026-10-01
---
# 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.

**Note:**

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.

**Error:**

First startup needs **exactly one** seed option: `seedCredential` **or** `seedCredentialFile`. Configuring both fails startup.

For the full activation flow, see [Licensing](https://docs.walt.id/enterprise-stack/setup/licensing.md).

## Example File

```hocon[license.conf]
# 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 `.waltlicense` is 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** `issuedAt` is 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 |

**Error:**

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

```bash
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):

```yaml
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`:

```hocon
seedCredential = ${?LICENSE_SEED_CREDENTIAL}
seedCredentialFile = ${?LICENSE_SEED_CREDENTIAL_FILE}
installationKeyFile = ${?LICENSE_INSTALLATION_KEY_FILE}
licenseServerUrl = "https://license.walt.id"
```

```yaml
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://..."
```

```yaml
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-mode` in `_features.conf`** — A **development** license requires `dev-mode` to be enabled. A **production** license refuses to start when `dev-mode` is enabled.
- **Feature allow-list** — `_features.conf` still applies, but a feature must also be allowed by the active license.

See [Features](https://docs.walt.id/enterprise-stack/setup/configurations/config-files/features.md) and [Licensing](https://docs.walt.id/enterprise-stack/setup/licensing.md).
