Skip to content

Run a Registry Node ​

agentdns is the Go binary that implements the Registry Spec. One process, talks Postgres + Redis + the mesh + the HTTP API.

This page is the operator's runbook. For protocol-level details see Architecture: Registry Spec and for binary internals see Architecture: AgentDNS.

Pre-flight ​

NeedDetail
Linux VM2 vCPU, 4 GB RAM minimum for a small mesh node; 8+ GB once you start indexing thousands of entities
Postgres 14+Either local or managed (RDS / Cloud SQL fine)
Redis (optional)Speeds up cards / rate limits / bloom filters; the node runs without it
A domainPublic registries should serve TLS at a real domain, e.g. registry.example.com
Outbound TCP+TLS to port 4001For mesh peering

Install ​

bash
# Download the latest binary (placeholder — adjust to actual release path)
curl -L -o /usr/local/bin/agentdns https://github.com/zyndai/AgentDNS/releases/latest/download/agentdns-linux-amd64
chmod +x /usr/local/bin/agentdns

agentdns version

Or build from source:

bash
git clone https://github.com/zyndai/AgentDNS
cd AgentDNS
go build -o /usr/local/bin/agentdns ./cmd/agentdns

Initialise ​

bash
agentdns init

Creates:

  • ~/.zynd/identity.json — node Ed25519 keypair. Back this up.
  • ~/.zynd/config.toml — default config; safe to edit before start.

Configure ​

~/.zynd/config.toml holds everything. Most operators only edit a handful of sections.

[node] ​

toml
[node]
name = "my-registry"
type = "full"                          # "full" | "light" | "gateway"
data_dir = "~/.zynd/data"
external_ip = "auto"                   # or a fixed IP
https_endpoint = "https://my-registry.example.com"

https_endpoint becomes the prefix of every FQAN your node mints, so set it to a domain you control.

[mesh] ​

toml
[mesh]
listen_port = 4001
max_peers = 15
bootstrap_peers = ["zns-boot.zynd.ai:4001", "zns01.zynd.ai:4001"]
tls_enabled = true

bootstrap_peers is how new nodes find the mesh. Leave the defaults to join the public Zynd mesh; replace with your own seeds for a private mesh.

[registry] ​

toml
[registry]
postgres_url = "postgres://agentdns:agentdns@localhost:5432/agentdns?sslmode=require"
max_local_agents = 100000

In production: sslmode=require. The connection pool is 2–20 connections.

toml
[search]
embedding_backend = "onnx"
embedding_model   = "bge-small-en-v1.5"
embedding_dimensions = 384

use_improved_keyword = true

max_federated_peers   = 10
federated_timeout_ms  = 1500
default_max_results   = 20

For tiny meshes / CI, embedding_backend = "hash" is zero-deps. For best recall, ONNX with bge-small-en-v1.5 (~130 MB; auto-downloaded with SHA-256 verification on first start). For shared embeddings via OpenAI / Ollama, embedding_backend = "http" with embedding_endpoint = "...".

[search.ranking] ​

toml
[search.ranking]
method = "weighted"           # or "rrf"
text_relevance_weight     = 0.30
semantic_similarity_weight = 0.30
trust_weight              = 0.20
freshness_weight          = 0.10
availability_weight       = 0.10

weighted lets you tune. rrf needs no tuning.

[redis] (optional) ​

toml
[redis]
url = "redis://localhost:6379/0"

Without Redis the node still works — Tier-1 LRUs and in-memory rate buckets cover most needs.

[api] ​

toml
[api]
listen = "0.0.0.0:8080"
rate_limit_search   = 100
rate_limit_register = 10
cors_origins = ["https://my-dashboard.example.com"]

Use a reverse proxy (Caddy / nginx) for TLS on this port.

[onboarding] ​

toml
[onboarding]
mode = "open"                  # or "restricted"
auth_url = ""
webhook_secret = ""

open = self-registration on first handle claim or entity registration. restricted = developers must be approved via webhook.

[heartbeat] ​

toml
[heartbeat]
enabled = true
inactive_threshold_seconds = 300   # 5 min
sweep_interval_seconds = 60
max_clock_skew_seconds = 60

[dht] ​

toml
[dht]
enabled = true
k = 20
alpha = 3
republish_interval = 3600
expire_after = 86400
lookup_timeout_ms = 5000

Disable for light and gateway nodes.

Env var overrides ​

EnvOverrides
AGENTDNS_CONFIGPath to config file (same as --config)
AGENTDNS_DATA_DIR[node].data_dir
AGENTDNS_POSTGRES_URL[registry].postgres_url
AGENTDNS_REDIS_URL[redis].url
AGENTDNS_LISTEN[api].listen

Start ​

bash
agentdns start

Logs go to stdout. Block on SIGINT/SIGTERM.

For a systemd unit:

ini
# /etc/systemd/system/agentdns.service
[Unit]
Description=Zynd AgentDNS registry
After=network.target postgresql.service
Wants=postgresql.service

[Service]
ExecStart=/usr/local/bin/agentdns start --config /etc/agentdns/config.toml
EnvironmentFile=/etc/agentdns/agentdns.env
Restart=on-failure
User=agentdns

[Install]
WantedBy=multi-user.target
bash
sudo systemctl enable --now agentdns
sudo journalctl -u agentdns -f

TLS ​

Front the API with Caddy:

caddy
my-registry.example.com {
    reverse_proxy localhost:8080
}

Caddy auto-issues a Let's Encrypt cert. The mesh port (4001) does not need a CA cert — it uses self-signed TLS verified at the application layer.

CLI day-to-day ​

bash
agentdns status          # uptime, peers, agents, gossip rate, DHT state
agentdns peers           # connected peers + verification tier
agentdns version

For the full subcommand list see Architecture: AgentDNS — CLI.

Production checklist ​

  • [ ] [node].https_endpoint set to a domain you control.
  • [ ] TLS via Let's Encrypt on port 8080 (Caddy / nginx).
  • [ ] [registry].postgres_url uses sslmode=require.
  • [ ] [redis].url set if running multiple instances behind a load balancer.
  • [ ] [api].cors_origins restricted to your dashboard origin(s).
  • [ ] /.well-known/zynd-registry.json published (signed registry identity proof).
  • [ ] _zynd.<your-domain> DNS TXT record published — peer verification falls back to it.
  • [ ] [onboarding].mode = "restricted" if you don't want public developer signups.
  • [ ] Identity backed up — ~/.zynd/identity.json.
  • [ ] Postgres backed up daily.
  • [ ] Metrics scrape configured — see Metrics & Monitoring.

Joining the public Zynd mesh ​

If you want your node to be part of the global Zynd network (so registrations on your node show up in zns01.zynd.ai searches and vice versa):

  1. Set bootstrap_peers = ["zns-boot.zynd.ai:4001"].
  2. Make sure your [node].external_ip is reachable on port 4001 from the public internet.
  3. Publish a registry identity proof at /.well-known/zynd-registry.json so peers verify your domain.

Then start the node — it'll announce itself, exchange bloom filters, and begin gossiping.

Running a private mesh ​

For an air-gapped or internal-only deployment:

  1. Stand up two or more agentdns nodes within your network.
  2. Pick one to be the bootnode — set its address as bootstrap_peers on every other node.
  3. Don't publish to the public Zynd mesh — leave bootstrap_peers = [] (or just your private peers) on each node.
  4. Point your developers' ZYND_REGISTRY_URL at one of the nodes.

That's it — your developers' agents register on your private registry, your private peers gossip to each other, the public Zynd network is never touched.

See also ​

Released under the MIT License.