---
title: "External DID Web Hosting"
description: "This guide explains how to make DIDs available at a custom domain (e.g., dids.waltid.org) instead of the default enterprise domain."
stack: "Enterprise Stack (commercial) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/services/did-registry/external-did-web-hosting
generated: 2026-07-20
---
# External DID Web Hosting

This guide explains how to make DIDs available at a custom domain (e.g., dids.waltid.org) instead of the default enterprise domain.

## Overview

By default, DIDs in the walt.id Enterprise Stack are hosted at the enterprise domain (e.g., `waltid.enterprise.cloud`). However, you may want to make these DIDs available at your own custom domain (e.g., `dids.waltid.org`). This guide explains how to set up external DID web hosting to achieve this.

## Prerequisites

- Access to a walt.id Enterprise Stack organization
- A tenant with DID registry service
- A custom domain that you control (e.g., `dids.waltid.org`)
- Access to configure DNS settings for your custom domain

## Step 1: Configure Organization-Level Root DID Registry

Before configuring the tenant-level DID registry, you need to set up an organization-level root DID registry:

1. **Create Organization-Level DID Registry Service**:

**Option: CURL**

Endpoint: `/v1/{target}/resource-api/services/create` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%2F%20Resource/post_v1__target__resource_api_services_create)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise.cloud/v1/{target}/resource-api/services/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "did-registry"
}'
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `waltid`, your default Base URL will
  be `waltid.enterprise.cloud`.
- `target`: _resourceIdentifier_ - The target indicates the organization in which to create the new organization level
  DID Registry service, e.g. `waltid.tenant.didregistry`

**Body Parameters**

- `type`: _serviceType_ - Specifies the type of service to create. In our case `did-registry`

2. **Set Up Root DID Registry**:

**Option: CURL**

Endpoint: `/v1/organization/update-config` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Organization/post_v1_organization_update_config)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise.cloud/v1/organization/update-config' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "rootDidRegistry": "waltid.tenant.didregistry"
}'
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `waltid`, your default Base URL will
  be `waltid.enterprise.cloud`.

**Body Parameters**

- `rootDidRegistry`: _resourceIdentifier_ - The ID of the DID Registry Service to be used for organization-level DIDs,
  e.g. `waltid.tenant.didregistry`

## Step 2: Configure Tenant-Level DID Registry

First, ensure that your tenant has the DID registry service properly configured:

**Option: CURL**

Endpoint:`/v1/{target}/tenant-api/tenants/config/update` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/TenantManagement/post_v1__target__tenant_api_tenants_config_update)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise.cloud/v1/{target}/tenant-api/tenants/config/update' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "didRegistry": "waltid.tenant.didregistry"
}'
```

**Body**

```json
{
  "didRegistry": "waltid.tenant.didregistry"
}
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `waltid`, your default Base URL will
  be `waltid.enterprise.cloud`.
- `target`: _resourceIdentifier_ - The target indicates the tenant for which to update the configuration
  (`{organizationID}.{tenantID}`), e.g. `waltid.tenant`

**Body Parameters**

- `didRegistry`: _String_ - The ID of the DID Registry service to be associated with the tenant. This should be the fully qualified ID of your DID registry service.

## Step 3: Create Host Alias for Tenant

Create a host alias for your tenant that points to your custom domain:

**Option: CURL**

Endpoint:`/v1/{target}/host-alias-api/host-aliases/create` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%2F%20Resource/post_v1__target__resource_api_host_aliases_create)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise.cloud/v1/{target}/host-alias-api/host-aliases/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "domain": "dids.waltid.org"
}'
```

**Body**

```json
{
  "domain": "dids.waltid.org"
}
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `waltid`, your default Base URL will
  be `waltid.enterprise.cloud`.
- `target`: _resourceIdentifier_ - The target indicates the tenant for which to create the host alias
  (`{organizationID}.{tenantID}.{host_alias_id}), e.g. `waltid.tenant.my_alias`

**Body Parameters**

- `domain`: _String_ - The custom domain that you want to use for your tenant. This is the domain where your DIDs will be available.

## Step 4: Configure DNS and Reverse Proxy (Customer Side)

On the customer side, you need to configure your DNS and set up a reverse proxy to point your custom domain to the enterprise stack server:

1. **DNS Configuration**: 
   - Create a DNS record for your custom domain (e.g., `dids.waltid.org`) pointing to your reverse proxy server.

2. **Reverse Proxy Setup**:
   - Set up a reverse proxy (e.g., Nginx, Apache, Traefik) on your server.
   - Configure SSL/TLS for your custom domain.
   - Configure the reverse proxy to forward requests from your custom domain to the enterprise stack server.

**Example Nginx Configuration**:

```nginx
server {
    listen 443 ssl;
    server_name dids.waltid.org;

    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/private.key;

    location / {
        proxy_pass https://waltid.enterprise.cloud;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

**Example Kubernetes Ingress Configuration**:

If you're using Kubernetes, you can set up an Ingress resource to route traffic to your enterprise API service:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dids-waltid-org-enterprise-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: "nginx"
  tls:
    - hosts:
        - dids.waltid.org
      secretName: did-waltid-org-tls
  rules:
    - host: dids.waltid.org
      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: ImplementationSpecific
            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: ImplementationSpecific
            backend:
              service:
                name: waltid-enterprise-api
                port:
                  name: http
          - path: /.*/did\.json$
            pathType: ImplementationSpecific
            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
```

This Ingress configuration:
- Sets up TLS for the dids.waltid.org domain using cert-manager
- Routes various API paths to the waltid-enterprise-api service
- Includes a regex path for DID documents (/.*/did\.json$)

## Step 5: Create DID in DID Store

Create a DID in the DID Store, making sure to use your custom domain in the domain parameter:

**Option: CURL**

Endpoint: `/v1/{target}/did-service-api/dids/create/web` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/DID%20Service/post_v1__target__did_service_api_dids_create_web)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise.cloud/v1/{target}/did-service-api/dids/create/web' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -d '{
  "type": "single_key_id",
  "keyId": "waltid.tenant.kms1.secp256r1",
  "domain": "dids.waltid.org",
  "path" : "user1"
}'
```

**Body**

```json
{
  "type": "single_key_id",
  "keyId": "waltid.tenant.kms1.secp256r1",
  "domain": "dids.waltid.org",
  "path" : "user1"
}
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `waltid`, your default Base URL will
  be `waltid.enterprise.cloud`.
- `target`: _resourceIdentifier_ - The target indicates the organization + tenant + DID service in which to execute the
  DID creation (`{organizationID}.{tenantID}.{subtenantID}.{didServiceID}`), e.g. `waltid.tenant.did1`

**Body Parameters**

- `keyId`: _resourceIdentifier_ - Specifies the key for which to generate a DID + DID Document. Please make sure that
  the key is stored in a KMS service under the same tenant as the DID service.
- `domain`: _string_ - The domain name to be used for the DID:web. This should be your custom domain (e.g., `dids.waltid.org`).
- `path`: _string_ - The path to be used for the DID:web (e.g., `user1`).

**Response**

- `201` - DID created successfully.

```json
{
  "did": "did:web:dids.waltid.org:user1",
  "document": {
    "context": [
      "https://www.w3.org/ns/did/v1",
      "https://w3id.org/security/suites/jws-2020/v1"
    ],
    "id": "did:web:dids.waltid.org:user1",
    "verificationMethod": [
      {
        "id": "did:web:dids.waltid.org:user1#key1",
        "type": "JsonWebKey2020",
        "controller": "did:web:dids.waltid.org:user1",
        "publicKeyJwk": {
          "kty": "EC",
          "crv": "P-256",
          "kid": "key1",
          "x": "...",
          "y": "..."
        }
      }
    ],
    "assertionMethod": [
      "did:web:dids.waltid.org:user1#key1"
    ],
    "authentication": [
      "did:web:dids.waltid.org:user1#key1"
    ],
    "capabilityDelegation": [
      "did:web:dids.waltid.org:user1#key1"
    ],
    "capabilityInvocation": [
      "did:web:dids.waltid.org:user1#key1"
    ],
    "keyAgreement": [
      "did:web:dids.waltid.org:user1#key1"
    ]
  }
}
```

## Step 6: Verify DID Resolution

Once you've completed the above steps, your DID should be available to resolve at your custom domain:

```
did:web:dids.waltid.org:user1
```

You can verify this by accessing the DID document directly at:

```
https://dids.waltid.org/user1/did.json
```

## Troubleshooting

If you're having issues with external DID web hosting, check the following:

1. **Organization-Level DID Registry**: Ensure that your organization has the correct root DID registry configured.
2. **Tenant Configuration**: Ensure that your tenant has the correct DID registry configured.
3. **Host Alias**: Verify that the host alias has been created correctly with your custom domain.
4. **DNS Configuration**: Check that your DNS records are pointing to the correct server.
5. **Reverse Proxy**: Ensure that your reverse proxy is correctly configured to forward requests to the enterprise stack server.
6. **DID Creation**: Make sure you used your custom domain when creating the DID.
