Quickstart: Run a Node
By the end of this guide, anyone on the internet will be able to resolve addresses at your domain and get back signed routing contracts.
Two paths
The reference implementation runs on Cloudflare Workers with automated DNS setup. If your domain’s DNS is on Cloudflare, follow the steps below — the CLI handles everything.
If your DNS is on another provider (Route 53, GoDaddy, Namecheap, etc.), you create two DNS records manually and can host the DRS anywhere. See DNS Records — Creating Records by Provider for exact instructions per provider.
What you need (Cloudflare path)
- A domain with DNS on Cloudflare
- A Cloudflare API token (Zone:DNS:Edit, Workers:Edit, Account:Workers KV:Edit)
- Node.js 20+ and pnpm
1. Clone and install
git clone https://github.com/drs-xyz/drs.gitcd drspnpm install2. Initialize your node
drs init --domain yourcompany.com --cf-token <your-cloudflare-token>This single command:
- Generates an Ed25519 keypair (your signing key)
- Creates two KV namespaces (addresses and config)
- Creates DNS records:
_drs._tcp.yourcompany.comSRV and_drskey.yourcompany.comTXT - Enables DNSSEC on the zone (protects DNS records from cache poisoning)
- Writes initial config to KV
Save the output — you’ll need the private key and KV namespace IDs.
3. Store the signing key
cd packages/drs-workerwrangler secret put DRS_SIGNING_KEY --env yourcompany# Paste the base64 private key when prompted4. Configure wrangler.toml
Add your domain as an environment in packages/drs-worker/wrangler.toml:
[env.yourcompany]vars = { DOMAIN = "yourcompany.com", NODE_TYPE = "standard" }routes = [{ pattern = "yourcompany.com/*", zone_name = "yourcompany.com" }]
[[env.yourcompany.kv_namespaces]]binding = "ADDRESSES"id = "<addresses-kv-id-from-step-2>"
[[env.yourcompany.kv_namespaces]]binding = "CONFIG"id = "<config-kv-id-from-step-2>"5. Tell the world what you accept
drs update-config --accepts '[ {"value_type":"USDC","transfer_type":"ethereum", "reference":"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "sponsor":"circle.com"}, {"value_type":"ETH","transfer_type":"ethereum"}]' --cf-token <token> --account-id <id> --kv-namespace <config-kv-id>6. Add your first address
drs add-address alice --routes '[ {"value_type":"USDC","transfer_type":"ethereum","destination":"0xABC..."}, {"value_type":"ETH","transfer_type":"ethereum","destination":"0xABC..."}]' --cf-token <token> --account-id <id> --kv-namespace <addresses-kv-id>7. Deploy
cd packages/drs-workerwrangler deploy --env yourcompany8. Test it
# Is DNS correct?drs check-dns yourcompany.com
# What does your node accept?curl https://yourcompany.com/.well-known/directory.json | jq
# Resolve alice — get a real signed routing contractcurl -s -X POST https://yourcompany.com/resolve \ -H 'Content-Type: application/json' \ -d '{"address":"alice@yourcompany.com"}' | jq
# Full end-to-end: resolve + verify signature against DNS keydrs test-resolve alice@yourcompany.comThat’s it. alice@yourcompany.com is now a live Directory address. Anyone with the SDK can resolve it, verify the signature, and know exactly where to send value.
Try it locally first
If you want to test before deploying to Cloudflare:
pnpm dev# Starts a local DRS node at http://localhost:8787# Pre-seeded with test addresses, real Ed25519 signingcurl -s -X POST http://localhost:8787/resolve \ -H 'Content-Type: application/json' \ -d '{"address":"alice@localhost.directory.dev"}' | jqNon-Cloudflare path
If you’re not using Cloudflare DNS or Workers, here’s what you need:
1. Generate your keypair
node -e " import('@directory/crypto').then(async (c) => { const keys = await c.generateKeyPairBase64(); console.log('Public key:', keys.publicKey); console.log('Private key:', keys.privateKey); });"2. Create DNS records
Add two records in your DNS provider’s dashboard:
| Type | Name | Value |
|---|---|---|
| SRV | _drs._tcp | 10 5 443 yourcompany.com |
| TXT | _drskey | v=drs1; k=ed25519; p=YOUR_BASE64_PUBLIC_KEY |
See DNS Records for provider-specific examples (Route 53, GoDaddy, etc.).
Enable DNSSEC on your DNS provider if available. DNSSEC protects your SRV and TXT records from cache poisoning — without it, an attacker can substitute a fake public key and sign contracts that verify. See Security Model — DNSSEC.
3. Run the DRS
The DRS is a stateless HTTPS API. The reference implementation uses Hono and can run on any Node.js host:
pnpm dev# Runs the full DRS at http://localhost:8787For production, wrap it in any HTTPS server — behind nginx/caddy on a VPS, in a Docker container, or on Vercel/Fly.io/Railway. The only requirement is HTTPS on the domain your SRV record points to.
The storage layer is a simple KVStore interface — just get(key) and put(key, value). Cloudflare KV implements it natively. For other hosts, implement it against Redis, Postgres, SQLite, or anything else. A MemoryKV adapter ships with the project for local dev:
import { MemoryKV } from "@directory/worker/adapters/memory";
// Or implement your own:class RedisKV implements KVStore { async get(key: string) { /* redis.get(key) */ } async put(key: string, value: string) { /* redis.set(key, value) */ }}4. Verify
dig _drs._tcp.yourcompany.com SRVdig _drskey.yourcompany.com TXTdrs check-dns yourcompany.comWhat’s next
- Add more addresses:
drs add-address - Manage addresses as YAML files:
drs sync --dir ./addresses - Rotate keys:
drs rotate-key - See all commands: CLI Reference
- Understand the protocol: How It Works