aboutsummaryrefslogtreecommitdiffstats
path: root/docs/example.toml
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-02 12:03:02 +0100
committertv <tv@krebsco.de>2026-11-02 16:29:16 +0100
commit29cad923a5e2d7dc3207c8d456440f8c37bfd7b6 (patch)
treec3ca35fa4841fb38f1d8c167aa3a47cf6909a8cb /docs/example.toml
parent9ecb59816f168647340776d72b735e60efc3b978 (diff)
add documentation
Diffstat (limited to 'docs/example.toml')
-rw-r--r--docs/example.toml280
1 files changed, 280 insertions, 0 deletions
diff --git a/docs/example.toml b/docs/example.toml
new file mode 100644
index 0000000..95b6f52
--- /dev/null
+++ b/docs/example.toml
@@ -0,0 +1,280 @@
+# An example configuration with every option, explained (`configuration.md` has the
+# rules). Use it with `continuum --config example.toml`; `continuum --print-config`
+# shows what a configuration amounts to, and `continuum --help` lists the options.
+#
+# Keys are the long option names. Nested tables join their keys with `-`: `key-file`
+# under `[mycelium]` is `mycelium-key-file`. Options left out (or commented out, as most
+# are here) take their defaults, shown in the comments. Command-line arguments win over
+# files.
+#
+# Any value can come from elsewhere instead of being written out:
+# { env = "NAME" }, { file = "PATH" }, { command = "COMMAND" } or
+# { command = ["program", "argument"] }, with format = "json" to parse it as JSON;
+# and text can mix in such values: "node-${env:HOSTNAME}" (`$$` for a `$`).
+# Imported values are never logged or shown by --print-config.
+
+# --- Other files -----------------------------------------------------------------------
+
+# Load these first (a path or a list), in this order; relative to this file. This file's
+# own values win over its includes, later includes over earlier ones. An entry
+# { path = "...", optional = true } is skipped where the file is missing.
+# include = ["/run/secrets/continuum.toml", { path = "local.toml", optional = true }]
+# Options to set back to their defaults here (e.g. one an include sets).
+# unset = ["alias"]
+
+# --- Who this node is ------------------------------------------------------------------
+
+# This node's key (Ed25519, 32 raw bytes): who the node is, whatever transport reaches
+# it. Keep it with the node: a new key is a new node. Required (but with relay-only).
+node-key-file = "/var/lib/continuum/node.key"
+
+# Create a new node key at node-key-file if there is no file there (a new node). Without
+# it, a missing key file is an error, so a mistyped path never makes a new node. Best
+# given once on the command line (--node-key-create) rather than kept here.
+# node-key-create = false
+
+# A name for this node, shown next to its node ID (/peers, metrics). Published in the
+# member list; not unique, never an identity.
+# alias = "node-${env:HOSTNAME}"
+
+# Only relay (libp2p circuit relay), without being a node: no document, no swarm, no
+# node key. Needs libp2p alone (libp2p's enable, no other), its listen and
+# key-file; options about a swarm or a document (node-key-file, seeds, genesis,
+# state-file, ...) are errors with it. The HTTP API, with htpasswd, has /health,
+# /admin/stats and /admin/log only. List such relays in the document
+# (_continuum/relays) or in libp2p's relays.
+# relay-only = false
+
+# --- The HTTP API ------------------------------------------------------------------------
+
+# Address of the HTTP API. Plain HTTP: to expose it, put a TLS proxy in front.
+# bind-addr = "127.0.0.1:3000"
+
+# Users of the HTTP API (an htpasswd file with Argon2 hashes). Required (but with
+# relay-only: without it, no HTTP API).
+htpasswd = "/etc/continuum/htpasswd"
+
+# HTTP API users (from htpasswd) who may write protocol data under /store/_continuum
+# (remake records, members, forget records), e.g. to repair a stuck remake. Such writes
+# act on the whole swarm and are logged. Epoch metadata and the swarm ID are never
+# writable.
+# protocol-writers = ["alice"]
+
+# How log lines look: text (timestamped), journal (for systemd's journal: no timestamp or
+# colours, the level as each line's priority, for journalctl -p), or auto: journal when
+# stdout goes to the journal, else text.
+# log-format = "auto"
+
+# Log node IDs and transport identities as they are. Without it, a member's read
+# `<scheme>:<alias>` wherever they appear (`continuum:<alias>`, `libp2p:<alias>`), as the
+# member list names it.
+# log-raw-ids = false
+
+# Enable the /debug endpoints (tests only).
+# debug-api = false
+
+# --- The swarm ---------------------------------------------------------------------------
+
+# How to reach a node of the swarm to join: an address (`mycelium:<public key>` or
+# `libp2p:<multiaddr>`, as GET /admin/stats lists them), a Mycelium public key or IPv6
+# address, a host name with an AAAA record for one, or a libp2p multiaddr (with or
+# without /p2p/<peer ID>). A node keeps trying until it has joined.
+# seeds = ["node1.example.org", "libp2p:/ip6/fd00::1/tcp/9661"]
+
+# Start a new swarm, as its genesis node, instead of joining one through seeds. Every
+# start with it starts another new swarm: drop it once the swarm exists, and give the
+# node seeds instead. Can't be combined with seeds. With a state file that remembers a
+# swarm, it starts that swarm again instead (empty; nodes of it still running merge with
+# this one). Best given once on the command line (--genesis).
+# genesis = false
+
+# With genesis: make the new swarm's document as a remake of this kind would, instead of
+# starting it empty: import:PATH (an Automerge document, e.g. a backup, without its
+# history and protocol data) or replace:PATH (a JSON document, the store root); compact
+# changes nothing.
+# remake = "import:/var/backups/continuum.automerge"
+
+# Start the swarm again from a backup (as GET /admin/document saves it): this node loads
+# it, on the swarm and epoch it names, and is ready at once; other nodes join it.
+# Members of the swarm still running merge with it, or it rejoins them if they moved on
+# to a newer epoch (the backup is then dropped). For one start: command line.
+# recover-from = "/var/backups/continuum.automerge"
+
+# Pre-shared swarm key: only nodes that know it may join (raw bytes, at least 16; e.g.
+# `head -c 32 /dev/urandom`). Without it, any node that can reach a member may join.
+# swarm-key-file = "/etc/continuum/swarm.key"
+
+# Create a new swarm key at swarm-key-file if there is no file there: on the swarm's
+# first node, as the others need a copy of it (a key of their own keeps them out).
+# Without it, a missing key file is an error.
+# swarm-key-create = false
+
+# Not in files: `force` (override checks that refuse to start: swarmId,
+# badDocumentFile, replaceDocumentFile) is for one start, on the command line only.
+
+# --- Files of this node ------------------------------------------------------------------
+
+# Where this node remembers its swarm across restarts: the swarm ID and some members to
+# rejoin through (not the document). Written once ready, then rarely. Without it, a
+# restarted node knows only its configured seeds.
+# state-file = "/var/lib/continuum/state.json"
+
+# This node's document on disk. Read at start: the node resumes with it, ready at once.
+# Kept up to date while ready: changes are appended every document-append, and the file
+# is rewritten after a switch, a rejoin or a restart, and when the appended changes
+# outgrew it.
+# document-file = "/var/lib/continuum/document.automerge"
+
+# How often changes are appended to the document file.
+# document-append = "5s"
+
+# Shortest time between rewrites of the document file because its appended changes
+# outgrew its full save (a new epoch or a restart rewrites it at once).
+# document-rewrite = "1h"
+
+# --- Timings and sizes -------------------------------------------------------------------
+# Durations: seconds (30, 0.5) or with units (500ms, 30s, 1m, 1h30m, 7d).
+# Sizes: bytes or with units (64KiB, 4MiB).
+
+# Keepalive interval; dormancy, resync and probe timings derive from it. 15–30s on a
+# LAN or between servers, 1–2m over WAN, mobile or metered links.
+# keepalive = "1m"
+
+# Longest wait between HELLOs to a member that doesn't answer: they start at 10
+# keepalives and double up to this, so it bounds how long a returning member, or the
+# other side of a partition, takes to be noticed. Default: 60 keepalives (1h at 1m).
+# dormant-probe-max = "15m"
+
+# Neighbours each node keeps (at least 2). Swarms of up to this many + 1 nodes are a
+# full mesh; larger ones sync over several hops. With several transports, about this
+# many per transport.
+# neighbours = 12
+
+# Members that renewed their alive stamp within this time vote on remakes (a majority of
+# them must agree). At least 7h. Members renew their stamps every seventh of the
+# shortest window any of them publishes, hourly at most, so nodes may differ. Matters
+# on the node that coordinates a remake.
+# electorate-window = "7d"
+
+# What becomes of a write a remake or rejoin would carry over into the new epoch though
+# a newer one touched its path (last writer wins, by the writers' clocks): "drop" leaves
+# it out (logged), "quarantine" keeps it for an operator (GET /admin/quarantine).
+# superseded-writes = "drop"
+
+# Warn in the log when this node's clock differs from most of its peers' by more than
+# this, for sure (beyond half the round trip it was measured over, from their PONGs); 0:
+# never.
+# clock-skew-warn = "2s"
+
+# Chunk size when serving large transfers to other nodes (e.g. an epoch's snapshot to a
+# rejoining node), 1KiB to 4MiB.
+# blob-chunk = "64KiB"
+
+# --- Transports --------------------------------------------------------------------------
+
+# The transports' order of preference, whether enabled or not (each is enabled in its
+# own table: enable = true). A peer is reached on the first enabled one both have until
+# the paths are measured, then on the fastest; nodes on several carry the traffic
+# between nodes that share none. Options of a transport not enabled are ignored.
+# transport-order = ["mycelium", "libp2p", "tor"]
+
+[mycelium]
+# Use this transport (in builds with the mycelium feature). A node needs one at least;
+# none is on by default.
+# enable = false
+
+# Peers of the supervised Mycelium daemon (overlay links), not continuum peers. Public
+# Mycelium nodes are used only if listed here.
+# peers = ["tls://127.0.0.1:9651"]
+
+# Private key of the supervised Mycelium daemon (its identity, and so its address); a
+# new one each start if absent.
+# key-file = "/var/lib/continuum/mycelium.key"
+
+# Create a new key at key-file if there is no file there (a new Mycelium address).
+# Without it, a missing key file is an error.
+# key-create = false
+
+# TCP port the supervised daemon listens on for overlay peers; a free port if absent.
+# tcp-listen-port = 9651
+
+# A private Mycelium network for the supervised daemon: its key and its name, together.
+# They keep other Mycelium nodes from reaching ours at all.
+# network-key-file = "/etc/continuum/mycelium-network.key"
+# network-name = "example"
+
+# Use a Mycelium daemon running elsewhere (its REST API) instead of supervising one.
+# Excludes the options above except peers. Secret: a URL may carry credentials.
+# rest-url = "http://[::1]:8989"
+
+[libp2p]
+# Use this transport (in builds with the libp2p feature).
+# enable = false
+
+# Where to listen. Without, the node only connects out (peers answer over its
+# connections, and a relay makes it reachable). Its listen addresses are published in
+# the member list, loopback and link-local ones left out.
+# listen = ["/ip4/0.0.0.0/tcp/9661", "/ip4/0.0.0.0/udp/9661/quic-v1", "/ip6/::/tcp/9661"]
+
+# The addresses to publish instead of those listened on, e.g. a public address forwarded
+# to this node's listen port.
+# announce = ["/ip4/203.0.113.7/tcp/9661"]
+
+# Its key (Ed25519, 32 raw bytes), which makes its peer ID; a new one each start if
+# absent (the node ID stays the same either way). Worth keeping on a relay, so others'
+# addresses through it stay the same.
+# key-file = "/var/lib/continuum/libp2p.key"
+
+# Create a new libp2p key at key-file if there is no file there (a new peer ID). Without
+# it, a missing key file is an error.
+# key-create = false
+
+# Relay for nodes of the swarm that can't be dialled (bounded: 1024 circuits, 64 per
+# peer, each up to an hour and 1 GiB), and say so in the member list, where nodes that
+# need a relay find it. Needs a listen address others can dial.
+# relay = false
+
+# Relays to use when this node can't be dialled (no listen address others could dial,
+# or AutoNAT says so): multiaddrs, with or without the relay's peer ID. It picks up to
+# two relays, these first, then members that relay. Any libp2p node serving circuit
+# relay v2 will do; most keep circuits short (2 minutes, 128 KiB), enough to punch holes.
+# relays = ["/ip4/203.0.113.7/tcp/9661"]
+
+# Find nodes on the LAN (multicast DNS, IPv4). Those that speak continuum are seeds
+# while joining, so nodes on one LAN find each other without seeds; a swarm key keeps a
+# new node from joining another swarm on the same LAN.
+# mdns = false
+
+# Ask the router to forward this node's listen ports (UPnP), and publish where, so that
+# nodes elsewhere can dial it without a relay or hole punching. Opens those ports on the
+# router for as long as the node runs.
+# upnp = false
+
+# Address ranges libp2p leaves out (VPNs, say): neither published nor offered for hole
+# punching nor dialled, and connections there are refused. Announced addresses are
+# published anyway.
+# ignore = ["10.244.0.0/16", "42::/16"]
+
+# Hosts on the internet (names or addresses), only to tell whether this node has a
+# route to the internet, per IPv4 and IPv6 (the routing table is asked; nothing is sent
+# to them). Where it has none, its own public addresses of that family aren't
+# published. Without, it isn't asked.
+# internet-hosts = ["one.one.one.one"]
+
+# Use public libp2p infrastructure: join the IPFS DHT (through the IPFS bootstrap nodes)
+# to find peers' addresses and public relays, picked after members that relay. Public
+# relays only keep circuits for minutes and some KiB: enough to punch holes through
+# NATs. Makes this node's peer ID and addresses known to the DHT. Without it, nothing
+# public is used.
+# public = false
+
+[tor]
+# Use this transport (in builds with the tor feature).
+# enable = false
+
+# Where arti (Tor, embedded) keeps its state and cache, among them the onion service's
+# key, which makes its address: keep it with the node. Required with tor.
+# state-dir = "/var/lib/continuum/tor"
+
+# The port of this node's onion service.
+# port = 9662