Skip to content

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

Terminal window
git clone https://github.com/drs-xyz/drs.git
cd drs
pnpm install

2. Initialize your node

Terminal window
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.com SRV and _drskey.yourcompany.com TXT
  • 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

Terminal window
cd packages/drs-worker
wrangler secret put DRS_SIGNING_KEY --env yourcompany
# Paste the base64 private key when prompted

4. 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

Terminal window
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

Terminal window
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

Terminal window
cd packages/drs-worker
wrangler deploy --env yourcompany

8. Test it

Terminal window
# 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 contract
curl -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 key
drs test-resolve alice@yourcompany.com

That’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:

Terminal window
pnpm dev
# Starts a local DRS node at http://localhost:8787
# Pre-seeded with test addresses, real Ed25519 signing
Terminal window
curl -s -X POST http://localhost:8787/resolve \
-H 'Content-Type: application/json' \
-d '{"address":"alice@localhost.directory.dev"}' | jq

Non-Cloudflare path

If you’re not using Cloudflare DNS or Workers, here’s what you need:

1. Generate your keypair

Terminal window
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:

TypeNameValue
SRV_drs._tcp10 5 443 yourcompany.com
TXT_drskeyv=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:

Terminal window
pnpm dev
# Runs the full DRS at http://localhost:8787

For 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

Terminal window
dig _drs._tcp.yourcompany.com SRV
dig _drskey.yourcompany.com TXT
drs check-dns yourcompany.com

What’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