[node] id = "node-01" data_dir = "/var/lib/zocket" # /$data_dir/$id/* private_key = "/var/lib/zocket/node-01/identity.key" # ed25519, auto-generated on first run if missing, default = /$data_dir/$id/identity.key # DEFAULT ASSUMPTION: ephemeral. # A fresh keypair each restart is fine and expected as nothing is persisted to disk on purpose # (see mesh.discoverability + mesh.trust below), everything mesh-wide is rediscovered via # gossip/broadcast after (re)connecting to a seed peer in mesh.peers. # EXCEPTION: # If another node pins THIS node by pubkey in its own static mesh.peers[] entry, this # key must be persisted (mount on a volume) as a pinned pubkey is a promise of a stable identity, # and an ephemeral key breaks that pin on every restart. # Only relevant for statically pinned, long-lived "hub" style nodes; auto-enrolled/broadcast-mode peers never need this. [log] level = "info" # debug | info | warn | error format = "json" # json | text output = "stdout" # stdout | /path/to/file.log # ---- [listen.client] enabled = true bind = "0.0.0.0:8080" [listen.client.tls] enabled = false cert = "/etc/zocket/client.crt" key = "/etc/zocket/client.key" [listen.client.auth] mode = "token" # none | token # If mode is set to "token", then the client_id is DERIVED from the matched # identity's id below, never self-declared by the client. # If mode is set to "none", any client may self-declare their client_id. # On collision with an already-connected client_id, the NEW connection is rejected # (first-connected wins) to prevent a second client from silently taking over another's routing identity. [[listen.client.auth.identities]] id = "discord-bot" token = "sdfb08zbd98bzbh9r98gh98enb" [[listen.client.auth.identities]] id = "minecraft-mod" token = "sv8sovz987w98ruw9fwbgfubwf" [listen.client.access_control] mode = "allowlist" # allowlist | blocklist | disabled list = ["10.0.0.0/24", "127.0.0.1"] # IP | CIDR [listen.client.limits] max_message_bytes = 65536 max_frame_bytes = 65536 idle_timeout_secs = 300 ping_interval_secs = 30 max_missed_pongs = 2 max_connections = 256 [listen.client.limits.rate_limit] enabled = true messages_per_sec = 50 burst = 100 # ---- [listen.peer] enabled = true bind = "0.0.0.0:8181" [listen.peer.tls] enabled = false cert = "/etc/zocket/peer.crt" key = "/etc/zocket/peer.key" require_client_cert = false [listen.peer.auth] mode = "pubkey" # pubkey # Peer links can inject routes and broadcasts mesh-wide, so identity is always cryptographically verified, regardless of access_control. # Every connecting peer proves possession of the private key matching a pubkey via a signed nonce challenge - no shared secret ever transits the wire. # For a KNOWN node_id, the pubkey must match mesh.peers[].pubkey exactly, or the connection is rejected outright. # For a claimed node_id that isn't yet known, see mesh.discoverability = "broadcast" below. [listen.peer.access_control] mode = "allowlist" # allowlist | blocklist | disabled list = ["10.0.0.0/24", "127.0.0.1"] # IP | CIDR [listen.peer.limits] max_message_bytes = 1048576 idle_timeout_secs = 60 ping_interval_secs = 15 # ---- [mesh] enabled = true topology = "full" # full | static-partial | disabled routing_mode = "gossip" # gossip | reactive | static [mesh.discoverability] mode = "static" # static | broadcast # static: mesh.peers below is the complete, manually-maintained set of instances. # broadcast: mesh.peers is just the initial seed; unknown nodes may connect and prove # possession of a pubkey; they're auto-trusted and gossiped mesh-wide immediately. # listen.peer.access_control is the real gate in this mode; scope it tightly. [[mesh.peers]] id = "node-02" addr = "10.0.0.2:8181" pubkey = "rijgeb8u845un34tun34tou3nt3ot3untz3otn3to" reconnect = true backoff_min_ms = 500 backoff_max_ms = 30000 [mesh.trust] gossip_new_peers = true # propagate newly-enrolled peer identities to the rest of the mesh [mesh.gossip] seen_cache_ttl_secs = 300 route_ttl_secs = 0 # 0 = no expiry, rely on explicit ROUTE_REMOVE [mesh.broadcast] enabled = true # Broadcasting (target = "*") is peer-only and never exposed to clients on listen.client. # Floods across peer links using the same seen_cache dedup as gossip route announcements. # only used if routing_mode = "reactive" [mesh.reactive] query_ttl_hops = 4 query_timeout_ms = 2000 negative_cache_secs = 30 # ---- # prometheus format [metrics] enabled = true bind = "127.0.0.1:9090"