Complete config.example.toml with all sections
All checks were successful
CI / check (push) Successful in 5m18s

This commit is contained in:
Jean Chevronnet 2026-07-21 14:54:26 +00:00
parent dc046cd6f0
commit 8df07f22f9
No known key found for this signature in database

View file

@ -1,127 +1,154 @@
# Copy to config.toml and edit. config.toml is gitignored (holds the link password).
# Copy to config.toml and edit. config.toml is gitignored (it holds the link password).
# Only [uplink] and [server] are required; every other section is optional and off when
# omitted. A few settings reload on OperServ REHASH (noted below); the rest need a restart.
[uplink]
host = "127.0.0.1"
port = 7000
password = "changeme" # must match the <link> block on the uplink IRCd
password = "changeme" # must match the <link> block on the uplink ircd
# Link over TLS instead of plaintext, pinning the server's SPKI fingerprint (base64 of
# SHA256 over its SubjectPublicKeyInfo) rather than a CA, so a self-signed link cert is
# fine. Read the fingerprint with:
# openssl s_client -connect HOST:PORT </dev/null 2>/dev/null | openssl x509 \
# -pubkey -noout | openssl pkey -pubin -outform DER | openssl dgst -sha256 -binary | base64
# tls = true
# spki_fingerprint = ""
[server]
name = "services.example.net"
sid = "42S" # 3 chars, unique on the network
description = "Federated Services"
protocol = 1206 # InspIRCd link protocol version (1206 = insp4, 1205 = insp3)
description = "Network Services"
protocol = 1206 # InspIRCd link protocol (1206 = insp4, 1205 = insp3)
# scram_iterations = 210000 # PBKDF2 cost for new SCRAM verifiers; high by default
# guest_nick = "Guest" # nick prefix after LOGOUT; must start with a letter
# service_host = "" # host the pseudo-clients wear; empty = the server name
# service_modes = "iHkB" # invisible, hideoper, servprotect (needs a U-line), bot
# service_oper_type = "Network Service" # shown in /whois; empty = non-opers
# services_channel = "#services" # channel every pseudo-client joins; empty = none
# standard_replies = false # IRCv3 FAIL/WARN/NOTE; needs m_services_stdrpl on the ircd
# Node-to-node replication. Omit this section (and [[peer]]) to run a single node.
# [gossip]
# bind = "0.0.0.0:16700" # where peers reach us; omit for a dial-only node
# secret = "shared-secret" # both nodes must present the same secret
#
# [gossip.tls] # omit for a plaintext link; see scripts/gen-certs.sh
# cert = "certs/node.crt"
# key = "certs/node.key"
# ca = "certs/ca.crt" # a peer must present a certificate signed by this CA
#
# [[peer]] # one block per other node
# addr = "other-node:16700"
# name = "other-node" # TLS name to expect; must match the peer certificate
# Directory replication (gRPC) — lets a website mirror the account/channel
# directory (identity + metadata only, never credentials; see proto/echo.proto).
# Omit this section to run without it.
# [grpc]
# bind = "127.0.0.1:50051" # a private network hop is the expected deployment
# token = "shared-secret" # every RPC must send `authorization: Bearer <token>`
#
# [grpc.tls] # omit for plaintext (fine on a private/loopback hop)
# cert = "certs/node.crt"
# key = "certs/node.key"
# Liveness + Prometheus metrics (plain HTTP, read-only, unauthenticated). Omit to
# leave it off. Bind to localhost and point a monitor at it: GET /health for a
# liveness probe (JSON), GET /metrics for a scrape (gauges: account/channel/oper
# totals, per-service counters, and event.lamport — a monotonic log-progress gauge).
# [health]
# bind = "127.0.0.1:9099"
# Which service modules to start. Omit this section for the full standard suite
# (every service comes up by default). List names here to run a subset; add
# "example" to also start the example template service.
# Which service modules to start. Omit for the full standard suite; list names to run a
# subset. Add "example" to also start the example template service.
# [modules]
# services = ["nickserv", "chanserv"]
# Services operators, in three tiers of increasing power:
# operator day-to-day moderation: view hidden info, network bans, kick,
# kill, session limits, ignores, mode, spam filters, log search.
# administrator — the above plus account/channel data: suspend, drop, set flags,
# operator day-to-day moderation: view hidden info, network bans, kick, kill,
# session limits, ignores, mode, spam filters, log search.
# administrator the above plus account and channel data: suspend, drop, set flags,
# forbid, global notices, defcon, memo/info/bot administration.
# root the above plus daemon control: add/remove opers, set, rehash,
# root the above plus daemon control: add/remove opers, set, rehash,
# restart, shutdown, the activity feed.
# Name a tier with `type`, or list individual privileges with `privs` (auspex,
# oper, suspend, admin, root). Omit the whole block for a network with no opers.
# Name a tier with `type`, or list individual privileges with `privs` (auspex, oper,
# suspend, admin, root). Repeat the block per operator. Omit for a network with no opers.
# [[oper]]
# account = "yournick"
# type = "root"
# Staff audit feed: notable service actions (registrations, drops, vhosts,
# suspensions, akicks, access and bot changes, oper host config) are announced
# to this channel so operators can see who did what. Private material (memo
# bodies, password/verifier data) and cosmetic self-service tweaks are never
# surfaced. Omit the section to disable the feed.
# Staff audit feed: notable service actions (registrations, drops, vhosts, suspensions,
# akicks, access and bot changes) are announced here so operators see who did what. Memo
# bodies and credential material are never shown. Omit to disable the feed.
# [log]
# channel = "#services"
# Masks OperServ NOTIFY never announces, so they can't flood the feed. Three kinds:
# "#channel" mute a channel (keep a broad `#*` watch out of "#staff")
# "server:<glob>" mute everyone on a server (a relay whose users have clean
# nicks; alias "via:", matching the "via <server>" in the feed)
# anything else mute a user — nick glob, user@host, or extban ("*/*" catches
# PyLink relays that suffix nicks with /network)
# Reloadable with OperServ REHASH.
# notify_exclude = ["*/*", "server:chatnova.relay", "#staff"]
# Masks OperServ NOTIFY never announces: "#channel" mutes a channel, "server:<glob>"
# (alias "via:") mutes a server, anything else mutes a user (nick glob, user@host, or an
# extban). Reloadable with OperServ REHASH.
# notify_exclude = ["*/*", "server:relay.example.net", "#staff"]
# Inactivity-expiry: accounts not identified to, and channels not joined, for
# longer than the threshold are dropped on a periodic pass (opers, live
# sessions, occupied channels, and NOEXPIRE-pinned records are spared). A zero
# or omitted field leaves that kind never expiring. Omit the section to disable
# expiry entirely.
# [expire]
# accounts_days = 90
# channels_days = 30
# warn_days sends the owner a heads-up email this many days before expiry (only
# where an address is on file and [email] is configured); 0 or omitted = no
# warning email.
# warn_days = 7
# Registration policy. Reloadable with OperServ REHASH.
# [register]
# confusable_check = true # refuse look-alike, mixed-script, or invisible names
# vouch = false # invite-only: a new account waits for a NickServ VOUCH
# Per-IP session limiting: the connection that puts an IP over `default_limit`
# is killed on connect. OperServ EXCEPTION entries raise or lower the allowance
# per IP-mask (an exception limit of 0 means unlimited). 0 or omitted = off.
# [session]
# default_limit = 3
# Extbans echo accepts. Omit (or leave empty) to accept every extban the ircd offers.
# [extban]
# enabled = ["account", "realname", "country"]
# Account authority. Omit this section (the default) and Echo owns accounts
# itself: NickServ REGISTER / IDENTIFY / SET PASSWORD all work standalone, no
# external service needed. Set external = true to hand identity to an outside
# authority (e.g. your website): IRC can then only IDENTIFY — REGISTER, DROP,
# SET PASSWORD/EMAIL, RESETPASS, CONFIRM, CERT and GROUP are refused, and the
# authority pushes accounts in via the gRPC Accounts API (see [grpc]). Echo
# still owns all channel/vhost/ban data, keyed by the account name.
# Account authority. Default (omitted): echo owns accounts and REGISTER/IDENTIFY/SET all
# work standalone. Set external = true to hand identity to an outside authority (your
# website): IRC can then only IDENTIFY, and the authority pushes accounts in over the
# gRPC Accounts API. echo still owns all channel, vhost, and ban data, keyed by account.
# [auth]
# external = true
# DictServ: dictionary / thesaurus / reference lookups over the DICT protocol
# (RFC 2229). Present = the service loads and channel bots answer !dict, !define,
# !thes, !acronym, !law, !element, !bible, and friends (DictServ LOOKUP lists them
# all); also queryable directly with /msg DictServ <cmd> <term>. Omit it and echo
# makes no outbound lookups at all — this is opt-in because it reaches the network.
# Lookups are globally rate-limited and the reply is truncated to one line. The log
# channel is unaffected; keep this off if you don't want echo talking to dict.org.
# Inactivity expiry: drop accounts not identified to, and channels not joined, for longer
# than the threshold (opers, live sessions, occupied channels, and NOEXPIRE records are
# spared). 0 or omitted leaves that kind never expiring. Omit the section to disable.
# [expire]
# accounts_days = 90
# channels_days = 30
# warn_days = 7 # email the owner this many days before expiry (needs [email])
# Per-IP session limiting: the connection that puts an IP over default_limit is killed on
# connect. OperServ EXCEPTION raises or lowers it per IP-mask. 0 or omitted = off.
# [session]
# default_limit = 3
# Reply language. echo ships en, fr, de, es, es-ar, pt, pt-br.
# [language]
# default = "en"
# dir = "lang"
# available = ["en", "fr", "de", "es", "es-ar", "pt", "pt-br"]
# Outbound email for registration confirmation and password recovery. Omit to disable.
# [email]
# from = "services@example.net"
# command = "msmtp -t" # the message is piped on stdin, run via sh -c
# brand = "Example Network" # display name in the template
# accent = "#4f46e5" # any CSS colour
# logo = "" # hosted image URL (no inline SVG or data URIs in email)
# confirm_url = "" # e.g. https://example.net/confirm, adds a one-click link
# Liveness and Prometheus metrics (plain HTTP, read-only, unauthenticated). GET /health
# for a liveness probe, GET /metrics for a scrape (account/channel/oper totals, per-service
# counters, event.lamport). Keep it on localhost. Omit to disable.
# [health]
# bind = "127.0.0.1:9099"
# gRPC directory of accounts and channels for a website to mirror (identity and metadata
# only, never credentials), plus the Accounts API to register and confirm accounts with
# the token. See proto/echo.proto. Omit to disable.
# [grpc]
# bind = "127.0.0.1:50051"
# token = "a-long-shared-secret" # every RPC sends `authorization: Bearer <token>`
# [grpc.tls] # optional; omit on a private or loopback hop
# cert = "certs/node.crt"
# key = "certs/node.key"
# HTTP JSON-RPC endpoint for a staff web panel. Keep on localhost behind a proxy, or
# terminate TLS here. Omit to disable.
# [jsonrpc]
# bind = "127.0.0.1:5601"
# token = "a-long-shared-secret"
# origins = ["https://example.net"] # browser origins allowed cross-site (CORS)
# [jsonrpc.tls]
# cert = "certs/node.crt"
# key = "certs/node.key"
# Passwordless web login: a member already signed in on the website connects with a
# one-time kc_... token instead of a password, redeemed against this endpoint. Omit to disable.
# [keycard]
# url = "http://127.0.0.1:8000/accounts/api/login-token"
# api_key = "shared-key" # matches the endpoint's X-API-Key
# DictServ: dictionary, thesaurus, and reference lookups over DICT (RFC 2229). Opt-in
# because it makes outbound requests. Lookups are rate-limited and truncated to one line.
# Omit to make no outbound lookups at all.
# [dictserv]
# server = "dict.org:2628"
# Registration policy. The look-alike guard refuses REGISTER of a nick or channel
# that mixes alphabets (Cyrillic "аdmin"), is built from homoglyphs or styled
# (fullwidth/math) letters imitating Latin, or hides invisible/bidi characters —
# while genuine monolingual text (including accented French) passes. It's on by
# default; turn it off for a community that legitimately uses mixed/non-Latin
# names. Reloadable with OperServ REHASH.
# [register]
# confusable_check = false
# Node-to-node replication (optional; most setups are a single node). Omit [gossip] and
# [[peer]] to run standalone. See the Federation wiki page.
# [gossip]
# bind = "0.0.0.0:16700" # where peers reach us; omit for a dial-only node
# secret = "shared-secret" # both nodes must present the same secret
# [gossip.tls] # omit for a plaintext link; see scripts/gen-certs.sh
# cert = "certs/node.crt"
# key = "certs/node.key"
# ca = "certs/ca.crt" # a peer must present a cert signed by this CA
# [gossip.signing] # optional per-origin Ed25519 signing; key from --gen-gossip-key
# key = "base64-secret-key" # this node's signing key
# trust = { "42S" = "base64-pubkey", "43S" = "base64-peer-pubkey" }
# [[peer]] # one block per other node
# addr = "other-node:16700"
# name = "other-node" # TLS name to expect; must match the peer's certificate