Skip to content

Hosting DIDs on Your Domain

By default, Layr8 hosts your DID on our infrastructure at <node-id>.node.layr8.io. However, for organizations that want greater control and sovereignty over their identity, you can host your DID on your own domain using the Layr8 DID Webserver. This guide walks through the setup process.

Why Host Your Own DID?

Hosting your DID on your domain provides several benefits:

  • Brand consistency - Your DID matches your domain (e.g., did:web:acme.com)
  • Full control - You manage the domain and DID routing
  • Trust - Partners recognize and trust your domain
  • Portability - Change DID providers without changing your identifier

How It Works

The Layr8 DID Webserver acts as a proxy that:

  1. Receives DID resolution requests at your domain
  2. Fetches the DID document from your Layr8 node
  3. Serves the document from your domain with proper caching
  4. Maintains high availability with multiple origin nodes
did:web:example.com → https://example.com/.well-known/did.json
DID Webserver
Fetches from Layr8 Node
Returns DID Document

Prerequisites

Before you begin, ensure you have:

  1. Domain ownership - Administrative access to your domain’s DNS
  2. Server infrastructure - A server to run the DID Webserver
  3. Layr8 Node - Active node with your DID document(s)

Installation Options

Option 1: Docker Deployment

The easiest way to deploy is using Docker:

Terminal window
# Pull the DID Webserver image
docker pull ghcr.io/layr-8/did-webserver:latest
# Create node configuration
echo "your-node-id.node.layr8.io" > node_list.txt
# Run the container
docker run -d \
--name did-webserver \
-p 4000:4000 \
-e PORT=4000 \
-e CACHE_TTL=3600 \
-e FILE_PATH=/app/config/node_list.txt \
-v $(pwd)/node_list.txt:/app/config/node_list.txt \
ghcr.io/layr-8/did-webserver:latest

Option 2: Direct Installation

For more control, install directly on your server:

Terminal window
# Prerequisites: Elixir 1.14+ and Erlang/OTP 25+
# Clone the repository
git clone https://github.com/layr-8/did-webserver.git
cd did-webserver
# Install dependencies
mix deps.get
# Configure your node
echo "your-node-id.node.layr8.io" > priv/static/node_list.txt
# Run in production
MIX_ENV=prod mix run --no-halt

Option 3: Kubernetes Deployment

For production deployments, use Kubernetes:

apiVersion: apps/v1
kind: Deployment
metadata:
name: did-webserver
spec:
replicas: 3
selector:
matchLabels:
app: did-webserver
template:
metadata:
labels:
app: did-webserver
spec:
containers:
- name: did-webserver
image: ghcr.io/layr-8/did-webserver:latest
ports:
- containerPort: 4000
env:
- name: PORT
value: "4000"
- name: CACHE_TTL
value: "3600"
volumeMounts:
- name: node-config
mountPath: /app/config
volumes:
- name: node-config
configMap:
name: did-webserver-nodes
---
apiVersion: v1
kind: ConfigMap
metadata:
name: did-webserver-nodes
data:
node_list.txt: |
your-node-id.node.layr8.io
backup-node.node.layr8.io

Configuration

Environment Variables

Configure the DID Webserver with these environment variables:

VariableDescriptionDefault
PORTHTTP server port4000
FILE_PATHPath to node list filepriv/static/node_list.txt
CACHE_TTLCache time-to-live (seconds)3600 (1 hour)
DEPLOYMENT_ENVEnvironment (dev/staging/prod)dev

Node List Configuration

The node_list.txt file specifies origin nodes to fetch DID documents from:

# Primary node
mercury.node.layr8.io
# Backup nodes (optional)
venus.node.layr8.io
earth.node.layr8.io

Features:

  • One node per line
  • Comments supported with #
  • Monitored for changes (updates every 5 seconds)
  • Multiple nodes provide redundancy

Web Server Configuration

Configure your web server (Nginx/Apache) to proxy to the DID Webserver:

Nginx Configuration:

server {
listen 443 ssl http2;
server_name example.com;
# SSL configuration
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# DID document endpoint
location /.well-known/did.json {
proxy_pass http://localhost:4000;
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;
# Caching headers
add_header Cache-Control "public, max-age=3600";
add_header Content-Type "application/json";
# CORS headers
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
}
# Health check endpoint
location /health {
proxy_pass http://localhost:4000;
}
# Path-based DIDs (optional)
location ~ ^/(.+)/did\.json$ {
proxy_pass http://localhost:4000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

Apache Configuration:

<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# Enable proxy modules
ProxyRequests Off
ProxyPreserveHost On
# DID document endpoint
<Location "/.well-known/did.json">
ProxyPass http://localhost:4000/.well-known/did.json
ProxyPassReverse http://localhost:4000/.well-known/did.json
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, OPTIONS"
Header set Cache-Control "public, max-age=3600"
</Location>
# Health check
<Location "/health">
ProxyPass http://localhost:4000/health
ProxyPassReverse http://localhost:4000/health
</Location>
</VirtualHost>

URL Patterns Supported

The DID Webserver supports two URL patterns:

1. Domain-level DIDs

DID: did:web:example.com
URL: https://example.com/.well-known/did.json

2. Path-based DIDs

DID: did:web:example.com:users:alice
URL: https://example.com/users/alice/did.json
DID: did:web:example.com:departments:finance
URL: https://example.com/departments/finance/did.json

High Availability Setup

For production environments, implement high availability:

1. Multiple DID Webserver Instances

Run multiple instances behind a load balancer:

upstream did_webservers {
server did-webserver-1:4000 max_fails=3 fail_timeout=30s;
server did-webserver-2:4000 max_fails=3 fail_timeout=30s;
server did-webserver-3:4000 max_fails=3 fail_timeout=30s;
}
location /.well-known/did.json {
proxy_pass http://did_webservers;
proxy_next_upstream error timeout http_500 http_502 http_503;
}

2. Multiple Origin Nodes

Configure multiple Layr8 nodes for redundancy:

node_list.txt
primary.node.layr8.io
secondary.node.layr8.io
tertiary.node.layr8.io

The webserver tries nodes concurrently and uses the first successful response.

3. CDN Integration

Use a CDN for global distribution:

// CloudFlare Page Rule Example
{
"url": "example.com/.well-known/did.json",
"actions": {
"cache_level": "cache_everything",
"edge_cache_ttl": 3600,
"browser_cache_ttl": 3600
}
}

Monitoring and Operations

Health Checks

Monitor your DID Webserver health:

Terminal window
# Basic health check
curl https://example.com/health
# DID resolution check
curl https://example.com/.well-known/did.json
# Automated monitoring script
#!/bin/bash
while true; do
if ! curl -sf https://example.com/.well-known/did.json > /dev/null; then
echo "DID resolution failed at $(date)"
# Send alert
fi
sleep 60
done

Metrics and Logging

The DID Webserver provides detailed logging:

# Log examples:
[info] GET /.well-known/did.json
[info] Fetching DID document from origin nodes
[info] Cache hit for did:web:example.com
[info] Successfully fetched from mercury.node.layr8.io in 45ms
[error] All origin nodes failed for did:web:example.com

Enable debug logging for troubleshooting:

Terminal window
DEPLOYMENT_ENV=dev PORT=4000 ./did-webserver

Cache Management

The webserver includes intelligent caching:

  • Default TTL: 1 hour (configurable)
  • Cache key: Based on DID identifier
  • Automatic invalidation: On origin node changes
  • Memory-based: Fast retrieval

Adjust cache TTL based on your needs:

Terminal window
# Shorter TTL for frequently changing DIDs
CACHE_TTL=300 ./did-webserver # 5 minutes
# Longer TTL for stable DIDs
CACHE_TTL=86400 ./did-webserver # 24 hours

Migration Guide

Step 1: Preparation

  1. Set up DID Webserver on your infrastructure
  2. Configure it to fetch from your Layr8 node
  3. Test thoroughly with direct IP access
  4. Verify DID document is correct

Step 2: DNS Configuration

Add DNS records pointing to your DID Webserver:

; A record for IPv4
example.com. A 203.0.113.10
; AAAA record for IPv6
example.com. AAAA 2001:db8::10
; Or CNAME if using a load balancer
example.com. CNAME lb.example.com.

Step 3: SSL/TLS Setup

Ensure HTTPS is properly configured:

Terminal window
# Using Let's Encrypt
certbot certonly --webroot -w /var/www/html -d example.com
# Test SSL configuration
openssl s_client -connect example.com:443 -servername example.com

Step 4: Update Partner Connections

  1. Notify partners of your new DID
  2. Update documentation and integrations
  3. Maintain old DID during transition period
  4. Monitor both DIDs for activity

Step 5: Verification

Terminal window
# Resolve your new DID
curl https://example.com/.well-known/did.json
# Test with Layr8 tools
layr8 did resolve did:web:example.com
# Verify messaging works
layr8 message send --to did:web:example.com --type test

Troubleshooting

Common Issues and Solutions

DID Resolution Returns 404

  • Check node_list.txt contains valid nodes
  • Verify origin node has your DID document
  • Check webserver logs for fetch errors

SSL Certificate Errors

  • Ensure certificate covers your domain
  • Check certificate chain is complete
  • Verify port 443 is accessible

Slow Response Times

  • Check network connectivity to origin nodes
  • Increase cache TTL if appropriate
  • Add more origin nodes for redundancy

“All origin nodes failed” Error

  • Verify node names in node_list.txt
  • Check network connectivity
  • Ensure origin nodes are operational

Debug Mode

Enable detailed debugging:

Terminal window
# Run with debug logging
DEPLOYMENT_ENV=dev ./did-webserver
# Check specific resolution
curl -v https://example.com/.well-known/did.json
# Monitor cache behavior
curl -H "Cache-Control: no-cache" https://example.com/.well-known/did.json

Security Best Practices

  1. Use HTTPS Only - did:web requires HTTPS
  2. Implement Rate Limiting - Prevent DoS attacks
  3. Monitor Access Logs - Detect unusual patterns
  4. Keep Software Updated - Regular security patches
  5. Restrict Management Access - Secure node_list.txt updates

Advanced Configurations

Multi-Domain Hosting

Host multiple domains on one webserver:

server {
server_name example.com example.org example.net;
location /.well-known/did.json {
proxy_pass http://localhost:4000;
proxy_set_header Host $host;
}
}

Geographic Distribution

Deploy regionally for better performance:

# US Region
us-east-1:
nodes:
- us-east.node.layr8.io
- us-central.node.layr8.io
# EU Region
eu-west-1:
nodes:
- eu-west.node.layr8.io
- eu-central.node.layr8.io
# APAC Region
ap-southeast-1:
nodes:
- ap-south.node.layr8.io
- ap-northeast.node.layr8.io

Further Reading

Next Steps