mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-09 16:14:40 +00:00
Backlog item 1 of the relay performance campaign: skip signature verification for events ingested from explicitly configured trusted upstream relays, strfry-router style. geode now dials each [[mirror]] url from the config, subscribes to everything newer than now - backfill_seconds, and feeds the stream through NostrServer.ingest (same group-commit writer + live fanout as client publishes). The NostrClient underneath owns reconnects, backoff and REQ re-sync; duplicate replays after a reconnect are rejected by the store's unique-id constraint and only surface as counters. trusted = true is the per-upstream trust switch: events from that connection skip Schnorr verify. The trusted identity is the URL this relay dialed (TLS-authenticated for wss://), never anything an inbound peer claims. Default is false — mirror-but-verify — and a relay with no [[mirror]] entries behaves exactly as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TtDNpayEYvJH7QuPswND3A
125 lines
5.1 KiB
TOML
125 lines
5.1 KiB
TOML
# Example config for geode. Section layout mirrors
|
|
# nostr-rs-relay's config.toml so existing operators can port across.
|
|
#
|
|
# Run with:
|
|
# ./gradlew :geode:run --args="--config /etc/geode.toml"
|
|
#
|
|
# CLI flags override individual values: e.g. `--port 8888` wins over
|
|
# `[network].port`.
|
|
|
|
[info]
|
|
# The wss:// URL clients use to reach this relay (mandatory for NIP-42
|
|
# AUTH challenges). If not set, the relay synthesises one from the
|
|
# [network] section.
|
|
relay_url = "wss://relay.example.com/"
|
|
name = "Example Geode"
|
|
description = "A geode deployment."
|
|
contact = "admin@example.com"
|
|
# Operator pubkey (NIP-11). Optional.
|
|
# pubkey = "..."
|
|
# Override the supported NIPs advertised on the NIP-11 endpoint. If
|
|
# omitted, the relay advertises the NIPs it actually implements.
|
|
# supported_nips = [1, 9, 11, 40, 42, 45, 50, 62]
|
|
|
|
[network]
|
|
host = "0.0.0.0"
|
|
port = 7447
|
|
path = "/"
|
|
# Ktor CIO event-loop pool sizing. Leave commented-out for sensible
|
|
# per-CPU defaults (typical for <2k concurrent connections). Lift on
|
|
# big-VM deployments targeting 10k+ connections — over-threading at
|
|
# low connection counts hurts L1/L2 cache locality, so always
|
|
# benchmark before/after when tuning these.
|
|
#
|
|
# Operators targeting >1k concurrent WebSockets should also raise the
|
|
# OS file-descriptor limit: `ulimit -n 65536` (or higher) before
|
|
# launching, plus a matching `LimitNOFILE=` in any systemd unit. The
|
|
# default of 1024 on most distros caps the relay well below 1k FDs
|
|
# (one per WS plus DB and listening sockets).
|
|
# connection_group_size = 4
|
|
# worker_group_size = 16
|
|
# call_group_size = 64
|
|
|
|
[database]
|
|
# True keeps an in-memory SQLite db (events vanish on restart). Useful
|
|
# for tests; set false + `file = "..."` for persistent storage.
|
|
in_memory = false
|
|
file = "/var/lib/geode/events.db"
|
|
|
|
[options]
|
|
# Drop events whose Schnorr signature does not verify. Strongly
|
|
# recommended for any relay accepting traffic from real clients.
|
|
# Verify Schnorr signatures on every EVENT. Default: true. Disable
|
|
# only for trusted-input scenarios (test fixtures, mirror replays).
|
|
verify_signatures = true
|
|
|
|
# Run signature verification in parallel inside the IngestQueue
|
|
# (across all CPU cores) instead of serially on each connection's
|
|
# WebSocket pump. Default: true. Set false to fall back to the
|
|
# legacy in-policy verify path.
|
|
# parallel_verify = true
|
|
|
|
# NIP-50 full-text search. Default: true. When false no FTS index is
|
|
# built or maintained (inserts skip tokenization — a measurable share
|
|
# of ingest cost), NIP-11 stops advertising NIP-50, and REQ filters
|
|
# with a `search` term match nothing. CLI: --no-search.
|
|
# full_text_search = true
|
|
|
|
# Require clients to NIP-42 AUTH before REQ/EVENT/COUNT.
|
|
require_auth = false
|
|
|
|
# Advertise NIP-42 AUTH without requiring it: the relay sends the
|
|
# challenge and records clients that authenticate (so downstream
|
|
# policies can gate on identity), but REQ/EVENT/COUNT still work for
|
|
# clients that never AUTH. Ignored when require_auth = true.
|
|
# optional_auth = false
|
|
|
|
# Reject events whose `created_at` is more than this many seconds in
|
|
# the future. Enforced by RejectFutureEventsPolicy.
|
|
# reject_future_seconds = 1800
|
|
|
|
[authorization]
|
|
# Allow / deny lists. Allow is a permissive ceiling; deny still
|
|
# removes specific entries inside it. Enforced by Pubkey/KindAllowDenyPolicy.
|
|
# pubkey_whitelist = ["abcdef...64hex..."]
|
|
# pubkey_blacklist = []
|
|
# kind_whitelist = [0, 1, 3, 7, 1059, 30023]
|
|
# kind_blacklist = [4]
|
|
|
|
# Mirror upstream relays (strfry-router style, "down" direction): the
|
|
# relay dials each [[mirror]] url, subscribes to everything newer than
|
|
# now - backfill_seconds, and ingests the stream alongside client
|
|
# publishes. Reconnects and re-subscribes automatically.
|
|
#
|
|
# `trusted = true` is the relay-to-relay trust switch: events from that
|
|
# upstream skip Schnorr signature verification (the upstream already
|
|
# verified its own ingest; re-verifying burns ~8% of ingest CPU). The
|
|
# trusted identity is the URL *this* relay dialed — TLS-authenticated
|
|
# for wss:// — so an inbound client can never claim it. Default false:
|
|
# mirror-but-verify. Only trust relays you operate or whose ingest
|
|
# discipline you'd stake your own db on.
|
|
#
|
|
# [[mirror]]
|
|
# url = "wss://upstream.example.com/"
|
|
# trusted = true
|
|
# backfill_seconds = 3600
|
|
|
|
[admin]
|
|
# NIP-86 relay management API. When `pubkeys` is non-empty, the relay
|
|
# accepts HTTP POST application/nostr+json+rpc on the same URL,
|
|
# authenticated with NIP-98 HTTP-Auth. Only events signed by one of
|
|
# the listed pubkeys can run admin RPCs (banpubkey / banevent /
|
|
# changerelayname / …). Empty (the default) disables the endpoint.
|
|
#
|
|
# NIP-98 binds admin tokens to the relay's HTTP URL, which is derived
|
|
# from [info].relay_url with the scheme swapped (ws -> http, wss ->
|
|
# https) per NIP-86. Make sure [info].relay_url is set to the
|
|
# canonical public URL when behind TLS termination or a reverse proxy.
|
|
# pubkeys = ["abcdef...64hex..."]
|
|
|
|
# Path for the JSON snapshot that persists NIP-86 admin state (ban
|
|
# lists + the live NIP-11 doc) across restarts. When unset, admin
|
|
# state is in-memory only and forgotten on every restart. Convention
|
|
# is to place this next to the SQLite event-store file.
|
|
# state_file = "/var/lib/geode/events.db.admin.json"
|