Kubernetes Deployment

This document provides instructions for deploying the walt.id Enterprise API in a Kubernetes environment. It includes configuration details and deployment steps using deployment.yaml.

Prerequisites

  • Access to a Kubernetes cluster
  • kubectl configured to interact with your cluster
  • Familiarity with Kubernetes concepts such as Deployments, Services, and Ingress

Configuration Overview

The deployment.yaml file is structured into several key sections:

  • ConfigMap: Defines configuration settings for the enterprise API.
  • Secret: Holds the license seed, and holds LICENSE_STATE_ENCRYPTION_KEY when you supply your own secret. See Licensing.
  • Deployment: Specifies the deployment settings, including the container image and volume mounts.
  • Service: Exposes the API to the network.
  • Ingress: Manages external access to the services

The Config Map

The ConfigMap defines configurations of the walt.id Enterprise API. Modify the values as needed for your environment. You can learn more about each configuration file in the configurations section here

apiVersion: v1
kind: ConfigMap
metadata:
  name: waltid-enterprise-api-config
data:
  _features.conf: |
    enabledFeatures = [
      admin
      dev-mode
    ]
  auth.conf: |
    requireHttps = false
  database.conf: |
    databaseType = mongodb
    mongodb = {
      connectionString = "mongodb://root:password@localhost:27017/"
      database = "waltid-enterprise"
      profile = MONGODB_8
    }
  enterprise.conf: |
    baseDomain = "enterprise-demo.waltid.dev"
  license.conf: |
    seedCredential = ${?LICENSE_SEED_CREDENTIAL}
    seedCredentialFile = ${?LICENSE_SEED_CREDENTIAL_FILE}
    installationKeyFile = ${?LICENSE_INSTALLATION_KEY_FILE}
    licenseServerUrl = "https://license.walt.id"
  web.conf: |
    webHost = "0.0.0.0"
    webPort = 3000

Create a Secret for the online offer, or omit seed-credential and mount offline files instead. Include state-encryption-key and the LICENSE_STATE_ENCRYPTION_KEY env entry only when you supply your own secret. Omit both to have one generated. See Licensing.

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

API Deployment

kind: Deployment
apiVersion: apps/v1
metadata:
  name: waltid-enterprise-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: waltid-enterprise-api
  template:
    metadata:
      labels:
        app: waltid-enterprise-api
      annotations:
        deployment/id: "_DEFAULT_DEPLOYMENT_"
    spec:
      imagePullSecrets:
        - name: waltid-regcred
      containers:
        - name: waltid-enterprise-api
          image: waltid/waltid-enterprise-api
          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
            - name: LICENSE_SEED_CREDENTIAL_FILE
              valueFrom:
                secretKeyRef:
                  name: waltid-enterprise-license
                  key: seed-credential-file
                  optional: true
            - name: LICENSE_INSTALLATION_KEY_FILE
              valueFrom:
                secretKeyRef:
                  name: waltid-enterprise-license
                  key: installation-key-file
                  optional: true
          ports:
            - containerPort: 3000
              name: http-api
          volumeMounts:
              - name: waltid-enterprise-api-config
                mountPath: /config/_features.conf
                readOnly: true
                subPath: _features.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/auth.conf
                readOnly: true
                subPath: auth.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/database.conf
                readOnly: true
                subPath: database.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/enterprise.conf
                readOnly: true
                subPath: enterprise.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/license.conf
                readOnly: true
                subPath: license.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/web.conf
                readOnly: true
                subPath: web.conf
      volumes:
        - name: waltid-enterprise-api-config
          configMap:
            name: waltid-enterprise-api-config

API Service

kind: Service
apiVersion: v1
metadata:
  name: waltid-enterprise-api
spec:
  ports:
    - name: http
      port: 80
      targetPort: http-api
      protocol: TCP
  selector:
    app: waltid-enterprise-api

UI Deployment

kind: Deployment
apiVersion: apps/v1
metadata:
  name: waltid-enterprise-ui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: waltid-enterprise-ui
  template:
    metadata:
      labels:
        app: waltid-enterprise-ui
      annotations:
        deployment/id: "_DEFAULT_DEPLOYMENT_"
    spec:
      imagePullSecrets:
        - name: waltid-regcred
      containers:
        - name: waltid-enterprise-ui
          image: waltid/waltid-enterprise-ui
          env:
            - name: NUXT_PUBLIC_BASE_DOMAIN
              value: "enterprise-demo.waltid.dev"
          ports:
            - containerPort: 3000
              name: http-api

UI Service

kind: Service
apiVersion: v1
metadata:
  name: waltid-enterprise-ui
spec:
  ports:
    - name: http
      port: 80
      targetPort: http-api
      protocol: TCP
  selector:
    app: waltid-enterprise-ui

Ingress

Please ensure that all openid/* endpoints of the Enterprise Stack API are publicly accessible. This is necessary for successful credential exchanges with external systems.

The Enterprise API identifies the organization by the request's hostname ({organizationId}.{baseDomain}, or a host alias), so every such hostname needs a DNS record, a TLS certificate, and an ingress rule, and the ingress must pass the original host through (Host or X-Forwarded-Host). The example below has one rule for the base domain and one for the waltid organization. With a single organization, as in most on-prem deployments, that is all you need. For many organizations, use a wildcard record and rule for *.{baseDomain}, as the Helm chart in the quickstart repository does. On platforms with their own routing resources, such as OpenShift, create the equivalent routes for the same hostnames. See Organization Hostnames.


apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: waltid-enterprise-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: "traefik"
  tls:
    - hosts:
        - enterprise-demo.waltid.dev
      secretName: enterprise-demo-tls-secret
    - hosts:
        - waltid.enterprise-demo.waltid.dev
      secretName: waltid-enterprise-demo-tls-secret
  rules:
    - host: enterprise-demo.waltid.dev
      http:
        paths:
          - path: /auth/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /.well-known/vct/v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /swagger
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /api.json
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /livez
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /features/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /debug/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-ui
                port:
                  name: http
    - host: waltid.enterprise-demo.waltid.dev
      http:
        paths:
          - path: /auth/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /.well-known/vct/v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /swagger
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /api.json
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /livez
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /features/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /debug/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-ui
                port:
                  name: http

Complete deployment.yml

The manifest below includes LICENSE_STATE_ENCRYPTION_KEY. Delete that env entry, and state-encryption-key, when the API should generate the secret. See License configuration.

apiVersion: v1
kind: ConfigMap
metadata:
  name: waltid-enterprise-api-config
data:
  _features.conf: |
    enabledFeatures = [
      admin
      dev-mode
    ]
  auth.conf: |
    requireHttps = false
  database.conf: |
    databaseType = mongodb
    mongodb = {
      connectionString = "mongodb://root:password@localhost:27017/"
      database = "waltid-enterprise"
      profile = MONGODB_8
    }
  enterprise.conf: |
    baseDomain = "enterprise-demo.waltid.dev"
  license.conf: |
    seedCredential = ${?LICENSE_SEED_CREDENTIAL}
    seedCredentialFile = ${?LICENSE_SEED_CREDENTIAL_FILE}
    installationKeyFile = ${?LICENSE_INSTALLATION_KEY_FILE}
    licenseServerUrl = "https://license.walt.id"
  web.conf: |
    webHost = "0.0.0.0"
    webPort = 3000
---
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://..."
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: waltid-enterprise-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: waltid-enterprise-api
  template:
    metadata:
      labels:
        app: waltid-enterprise-api
      annotations:
        deployment/id: "_DEFAULT_DEPLOYMENT_"
    spec:
      imagePullSecrets:
        - name: waltid-regcred
      containers:
        - name: waltid-enterprise-api
          image: waltid/waltid-enterprise-api
          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
            - name: LICENSE_SEED_CREDENTIAL_FILE
              valueFrom:
                secretKeyRef:
                  name: waltid-enterprise-license
                  key: seed-credential-file
                  optional: true
            - name: LICENSE_INSTALLATION_KEY_FILE
              valueFrom:
                secretKeyRef:
                  name: waltid-enterprise-license
                  key: installation-key-file
                  optional: true
          ports:
            - containerPort: 3000
              name: http-api
          volumeMounts:
              - name: waltid-enterprise-api-config
                mountPath: /config/_features.conf
                readOnly: true
                subPath: _features.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/auth.conf
                readOnly: true
                subPath: auth.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/database.conf
                readOnly: true
                subPath: database.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/enterprise.conf
                readOnly: true
                subPath: enterprise.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/license.conf
                readOnly: true
                subPath: license.conf
              - name: waltid-enterprise-api-config
                mountPath: /config/web.conf
                readOnly: true
                subPath: web.conf
      volumes:
        - name: waltid-enterprise-api-config
          configMap:
            name: waltid-enterprise-api-config
---
kind: Service
apiVersion: v1
metadata:
  name: waltid-enterprise-api
spec:
  ports:
    - name: http
      port: 80
      targetPort: http-api
      protocol: TCP
  selector:
    app: waltid-enterprise-api
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: waltid-enterprise-ui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: waltid-enterprise-ui
  template:
    metadata:
      labels:
        app: waltid-enterprise-ui
      annotations:
        deployment/id: "_DEFAULT_DEPLOYMENT_"
    spec:
      imagePullSecrets:
        - name: waltid-regcred
      containers:
        - name: waltid-enterprise-ui
          image: waltid/waltid-enterprise-ui
          env:
            - name: NUXT_PUBLIC_BASE_DOMAIN
              value: "enterprise-demo.waltid.dev"
          ports:
            - containerPort: 3000
              name: http-api
---
kind: Service
apiVersion: v1
metadata:
  name: waltid-enterprise-ui
spec:
  ports:
    - name: http
      port: 80
      targetPort: http-api
      protocol: TCP
  selector:
    app: waltid-enterprise-ui
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: waltid-enterprise-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: "traefik"
  tls:
    - hosts:
        - enterprise-demo.waltid.dev
      secretName: enterprise-demo-tls-secret
    - hosts:
        - waltid.enterprise-demo.waltid.dev
      secretName: waltid-enterprise-demo-tls-secret
  rules:
    - host: enterprise-demo.waltid.dev
      http:
        paths:
          - path: /auth/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /.well-known/vct/v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /swagger
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /api.json
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /livez
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /features/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /debug/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-ui
                port:
                  name: http
    - host: waltid.enterprise-demo.waltid.dev
      http:
        paths:
          - path: /auth/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /.well-known/vct/v1/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /swagger
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /api.json
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /livez
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /features/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /debug/
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /
            pathType: Prefix
            backend:
              service:
                name: waltid-enterprise-ui
                port:
                  name: http
Last updated on November 9, 2026