Running a node

Configuration

Every environment variable dedid serve reads, and every CLI subcommand. The node has no config file: one binary, configured by its environment, so the same image is every role. Unset means the default in the table; a duration is Go syntax (30s, 5m, 1h).

Core

Variable Default What it does
DEDI_DB_URL — Postgres URL. Wins over DATABASE_URL when both are set.
DATABASE_URL postgres://dedi:dedi@localhost:5433/dedi?sslmode=disable What managed Postgres add-ons inject; used when DEDI_DB_URL is unset. Migrations run on start.
DEDI_KEY — The node identity key itself (PRIVATE+KEY+…, from dedid keygen). Signs checkpoints, DeDi files and webhook pushes.
DEDI_KEY_FILE dedid.key if it exists A file holding that key. An explicitly named file that cannot be read stops the node rather than minting a new identity.
(neither) The node generates a key on first start and keeps it in its database, so it keeps its identity across restarts. Refused when DEDI_CLUSTER_ID is set: replicas must share one key.
DEDI_ORIGIN dev.dedi.local/log The log's name: first line of every checkpoint, and the key name of a self-generated key. Use your domain.
DEDI_LISTEN :8080 Listen address.
PORT — Used as :$PORT when DEDI_LISTEN is unset; what PaaS platforms set.
DEDI_CHECKPOINT_INTERVAL 30s How often to sign a checkpoint. No new one is written while the tree is unchanged.
DEDI_TTL 300 Seconds. The ttl in read responses and the max-age on latest-version reads. A record payload's own integer ttl overrides it for that record.
DEDI_PUBLIC_URL — This node's external base URL. Used as the callback for children, in push lookup_urls, and as the publisher domain in DeDi files (falls back to the request's Host).
DEDI_NODE_NAME the origin Label for this node in the network view.
DEDI_VERIFIER_KEY derived from the identity key Overrides the verifier key the node publishes on its pages and hands to children and domain challenges. Rarely needed: the key is always derivable.
DEDI_STATS_FLUSH_INTERVAL 10s How often the in-memory request counters are folded into the database, so /dedi/stats survives restarts and sums across replicas.

Write plane

Variable Default What it does
DEDI_PUBLISHER_KEYS — kid:namespace:base64pubkey entries, comma or whitespace separated, from dedid pubkeygen. Unset: no write routes and no /admin at all (404). Set: the 13 signed /admin routes exist. Each key may write only its own namespace. Append to the list; replacing it revokes every other key.
DEDI_WILDCARD_NAMESPACES — Comma-separated namespaces allowed to answer the Beckn wildcard lookup (…/subscribers.beckn.one/{key_id}) and ?domain= discovery. Set it only if this node serves the Beckn ONIX registry lookup. On a node with no publisher keys, unset means every namespace may answer.
DEDI_ADMIN_USER admin HTTP Basic user for /admin and every write route.
DEDI_ADMIN_PASSWORD — Turns that Basic-auth gate on. Unset on a node with publisher keys, the node logs a warning on every boot. A read-only node has no write routes for it to guard and logs nothing. The publisher signature is still required either way.

Witnessing and the network view

Variable Default What it does
DEDI_WITNESS_TARGET_URL — Turns witnessing on. The target's API base including /dedi, e.g. https://b.example/dedi.
DEDI_WITNESS_TARGET_KEY — The target's verifier key. Get it out of band.
DEDI_WITNESS_TARGET_ORIGIN target Must equal the first line of the target's checkpoint.
DEDI_WITNESS_INTERVAL 60s How often to check the target.
DEDI_WITNESS_RECORD_INTERVAL 1h Write a consistent verdict at most this often per target; an alarm is written at once. 0 writes one for every change, the old behaviour. See witnessing.
DEDI_PEERS — Other nodes to show in the network view: comma-separated url or name=url. Observation only (did it answer), never proof.
DEDI_PEER_INTERVAL 30s How often to poll peers.
DEDI_EXTERNAL_STATUS_URL — Link to an external monitor watching this node, shown on /status. Empty by design: the node will not imply someone independent watches it.
DEDI_DEMO_URL https://schemes.proto.theflywheel.in/ Target of the "Demo" tab in the page navigation. Only http(s) URLs are accepted.

Replication (Raft)

See replication. All replicas need the same DEDI_KEY or DEDI_KEY_FILE and the same DEDI_ORIGIN, and each its own database.

Variable Default What it does
DEDI_CLUSTER_ID — Turns clustering on: this replica's id, which must appear in the peer list.
DEDI_CLUSTER_PEERS — id=raft-host:port=https://public-url, comma or whitespace separated. The URL is where followers redirect writes.
DEDI_CLUSTER_BIND this peer's advertised address Raft listen address.
DEDI_CLUSTER_DATA_DIR /data/raft Durable directory for the Raft log and snapshots.
DEDI_CLUSTER_BOOTSTRAP — true on exactly one replica, on its first start only.

Delegation (child nodes)

See delegation. The parent needs only DEDI_PUBLIC_URL. The child's values are rendered by the parent's console.

Variable Default What it does
DEDI_CHILD_WITNESS_INTERVAL 60s Parent: how often to witness each enrolled child.
DEDI_PARENT_URL — Child: the parent to enrol with (POST /enrol).
DEDI_PARENT_KEY — Child: the parent's verifier key, recorded in the child's delegated namespace.
DEDI_ENROL_NAMESPACE — Child: the namespace being claimed.
DEDI_ENROL_TOKEN — Child: the one-time offer token. Enrolment runs only when this, the namespace, the parent URL and DEDI_PUBLIC_URL are all set.

Crawling, push and anchoring

Variable Default What it does
DEDI_CRAWL_DOMAINS — Turns the crawler on: comma-separated domains whose DeDi files to verify and mirror. See crawler and mirror.
DEDI_CRAWL_INTERVAL 1h How often to crawl them.
DEDI_ALLOW_PRIVATE_WEBHOOK_TARGETS — true lets the crawler fetch from non-public addresses. Despite its name it does not affect webhooks.
DEDI_WEBHOOK_ALLOW_PRIVATE — 1 lets webhook subscriptions target non-public addresses. Off by default because the node makes these requests from inside your network.
DEDI_ANCHOR_BACKEND — Turns anchoring on. Only cord exists.
DEDI_ANCHOR_INTERVAL 5m How often to anchor the latest checkpoint.
DEDI_ANCHOR_RPC_URL ws://127.0.0.1:9944 The chain's RPC endpoint.
DEDI_ANCHOR_SURI — The signing account (a funded one on a real chain).
DEDI_ANCHOR_SS58 29 SS58 address prefix of the target chain.

The two private-target switches are separate on purpose and spelled differently by accident. Set the one for the subsystem you mean.

Tests

TEST_DATABASE_URL points the test suite at a throwaway Postgres; tests that need it fail rather than skip when it is unset, unless the run is -short or DEDI_TEST_SKIP_WITHOUT_DB is set.

The CLI

dedid <command> [flags]. In the Docker image the entrypoint is dedid, so docker run --rm flywheelai/dedi-node <command> … runs any of these.

Command Flags What it does
serve none; configured by the environment above Runs the node. The image's default command.
keygen -out (dedid.key), -name (dedi.local) Writes a node identity key and prints its verifier key. Only needed where the key must be supplied: a cluster, or a key you keep outside the database.
pubkey -key (default $DEDI_KEY, else dedid.key) Prints the verifier key for a node key you hold. A self-generated key lives in the database instead; read its verifier key from the boot log.
pubkeygen -kid, -namespace (both required), -out (publisher.key) Mints a publisher key. Writes the private half (refusing to overwrite an existing file) and prints the DEDI_PUBLISHER_KEYS entry.
sign -key (publisher.key), -kid, -path (both required), -method (POST), -body (file), -create, -if-match <tag>, -curl Prints the headers that authenticate one write: DeDi-Key-Id, DeDi-Timestamp, DeDi-Signature, plus the precondition. At most one of -create (the target must not exist) and -if-match (replace exactly this version); neither means no precondition, for routes that take none. -curl prints them as -H flags. A signature is valid for five minutes either side of the node's clock.
seed -file (required), -by (seed) Appends a seed file's namespace, registries and records straight to the database named by DEDI_DB_URL/DATABASE_URL, bypassing the write plane. For bootstrapping and tests; -by is recorded as created_by. Do not point it at a cluster replica's database.

Which writes need which precondition: publishing a namespace, registry or record needs -create or -if-match (without one the node answers 428); revoking a record needs -if-match. Children, node-config, domain verification and webhook subscriptions take no precondition. See API.

← All documentation