diff --git a/README.md b/README.md index e5431f2..ded304a 100644 --- a/README.md +++ b/README.md @@ -2,58 +2,55 @@ # echoIRCd -**A from-scratch, memory-safe IRCv3 server written in Rust.** +**A memory-safe IRCv3 server written in Rust.** [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](Cargo.toml) [![Language: Rust](https://img.shields.io/badge/rust-stable-orange.svg)](https://www.rust-lang.org) -[![unsafe: forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](src/lib.rs) [![IRCv3](https://img.shields.io/badge/IRCv3-supported-blueviolet.svg)](https://ircv3.net) -[![dependencies: 2](https://img.shields.io/badge/dependencies-openssl%20%2B%20mio-lightgrey.svg)](Cargo.toml) ## About -echoIRCd is a full IRC + IRCv3 server built from the ground up in safe Rust -(`#![forbid(unsafe_code)]`) with just two dependencies — `openssl` for TLS and -`mio` for the socket engine. A single lock-free core thread owns all state; a -**pool of epoll reactor threads** (one per core) drives the connections around it -— TLS crypto and all — without an async runtime. It ships **100+ commands**, the -**complete channel & user mode set**, -**28 IRCv3 capabilities**, server-to-server linking, a services interface, TLS, -WebSocket, GeoIP, layered anti-spam, and a JSON-RPC control plane — with every -operational limit configurable and nothing hardcoded. +echoIRCd is a full IRC + IRCv3 server. A single lock-free **core thread** owns all +state; a **pool of epoll reactor threads** (one per core) drives the connections +around it — TLS crypto and all — with no async runtime. It ships **100+ commands**, +the **complete channel & user mode set**, **30+ IRCv3 capabilities**, +server-to-server linking, a services interface, TLS, WebSocket, GeoIP, layered +anti-spam, a Prometheus metrics endpoint, and a JSON-RPC control plane — with every +operational limit exposed as a config key. ## Features - **Full IRC core** — registration, channels (`JOIN`/`PART`/`KICK`/`INVITE`/ `KNOCK`/`CYCLE`/`REMOVE`/`TOPIC`), messaging (`PRIVMSG`/`NOTICE`/`TAGMSG`, CTCP), and info (`WHO`/`WHOIS`/`WHOWAS`/`LIST`/`STATS`/`MAP`/`LUSERS`/`MOTD`). -- **Complete mode set** — prefixes `qaohv` (+ a network-staff `!` prefix), list +- **Complete mode set** — prefixes `qaohv` (plus a network-staff `!` prefix), list modes `beIgXw`, keyed/limit/flood/redirect/history/anticaps params, the full flag - set, all the standard user modes, and matching + acting **extbans** - (`g y r j s G b`, `m c n`). -- **IRCv3** — 28 capabilities including `message-tags`+`msgid`, `server-time`, - `labeled-response`, `batch`, `echo-message`, `account-tag`, **CHATHISTORY**, - **multiline**, **message-redaction**, **read-marker**, **relaymsg**, and - `WATCH`/`MONITOR`/`SILENCE`/callerid. + set, all the standard user modes, and matching + acting **extbans**. +- **IRCv3** — message-tags (+msgid), server-time, labeled-response, batch, + echo-message, account-tag, **CHATHISTORY**, **multiline**, **message-redaction**, + **read-marker**, **relaymsg**, SASL, standard-replies, and `WATCH`/`MONITOR`/ + `SILENCE`/caller-id. - **Operators** — `OPER`/`KILL`/`WALLOPS`/`GLOBOPS`, the `SA*`/`CHG*`/`SET*` - override toolbox, x-lines (`K`/`G`/`Z`/`E`/`SHUN`/`QLINE`/`CBAN`) persisted to - disk, staff prefix (`operprefix`/`OJOIN`), rank-gated `hidelist`/`hidemode`, and - a reload-safe `REHASH`. -- **Services & accounts** — SASL PLAIN/EXTERNAL relayed over S2S, the `SVS*` / + override toolbox, x-lines (`K`/`G`/`Z`/`E`/`SHUN`/`QLINE`/`CBAN`/`RLINE`) + persisted to disk, staff prefix (`operprefix`/`OJOIN`), oper levels, rank-gated + `hidelist`/`hidemode`, and a reload-safe `REHASH`. +- **Services & accounts** — SASL PLAIN/EXTERNAL relayed over the link, the `SVS*` / `ENCAP` / `METADATA` interface, account-gated modes, and optional ircd-side - account registration. + account registration (`REGISTER`/`VERIFY`). - **Server-to-server linking** — `UID`/`FJOIN` netburst, cross-server users and - channels, multi-hop routing, nick-collision handling and clean netsplit. -- **Security & anti-spam** — TLS with cert fingerprints, keyed host cloaking, - DNSBL, connection/message flood limits, mixed-script & gibberish detection, - CAPTCHA / PONG-cookie / arithmetic gates, and DCC filtering. -- **GeoIP** — a native MaxMind `.mmdb` reader with a `G:` geoban, `GEOIP` - command, and WHOIS country line. -- **Transports & control** — a native WebSocket layer (`ws://` / `wss://`), a - from-scratch forward-confirmed DNS resolver, and a token-authenticated JSON-RPC - control plane over HTTP. + channels, multi-hop routing, TS-based nick-collision handling, and clean + netsplit/rejoin. +- **Security & anti-spam** — TLS with client-cert fingerprints, keyed host + cloaking, DNSBL, per-IP connection/message flood limits, mixed-script & random + (drone) detection, CAPTCHA / PONG-cookie / arithmetic gates, and DCC filtering. +- **Transports** — plaintext, TLS (OpenSSL or rustls backend), a native WebSocket + layer (`ws://` / `wss://`), and the PROXY protocol (v1/v2) behind a load balancer. +- **GeoIP** — a MaxMind `.mmdb` reader with a `G:` geoban, `GEOIP` command, and + a WHOIS country line. +- **Control & observability** — a token-authenticated JSON-RPC plane over HTTP, and + an optional OpenMetrics/Prometheus endpoint. ## Quick start @@ -74,14 +71,17 @@ The full manual lives in [`docs/`](docs/): - [Building & running](docs/building.md) · [Configuration](docs/configuration.md) · [Architecture](docs/architecture.md) - [Channel & user modes](docs/modes.md) · [Operators](docs/operators.md) · [Server linking & services](docs/linking.md) - [IRCv3](docs/ircv3.md) · [Anti-abuse & flood protection](docs/anti-abuse.md) · [Deployment](docs/deployment.md) +- [Module developer API](docs/api/) — write your own commands, modes, and modules. ## Configuration Configuration is a plain `key = value` file; see -[`echoircd.conf.example`](echoircd.conf.example) for the full, documented set of -keys. Your live `echoircd.conf` is gitignored — it holds secrets (oper password, -cloak key, link password), so never commit it. Generate a TLS certificate into -`tls/` with the one-liner in the example config. +[`echoircd.conf.example`](echoircd.conf.example) for the full, annotated set of +keys. Every operational limit is a config key with a built-in default, and most +settings apply on `REHASH` without a restart. Your live `echoircd.conf` is +gitignored — it holds secrets (oper password, cloak key, link password), so never +commit it. Generate a TLS certificate into `tls/` with the one-liner in the example +config. ## Architecture @@ -92,13 +92,13 @@ anywhere. The I/O edge feeds it events over channels: - **A pool of `mio` epoll reactors** drives client sockets — an acceptor round-robins each connection onto a worker (one per core by default), and each worker frames lines and runs **TLS handshakes and record crypto non-blocking** - in-thread. So the socket work and the crypto spread across cores while the state - core stays single-threaded and lock-free. (Proxied TLS and server links keep a - thread each; there are few of them.) -- **Resilience is built in.** Slow work (KDF hashing, DNS, disk snapshots) runs - off the core so a flood can't freeze it; each event and each connection's I/O is - panic-isolated so one bad client can't crash the server; a watchdog flags a - stuck core; and half-open/stalled connections are reaped on a timer. + in-thread. Socket work and crypto spread across cores while the state core stays + single-threaded and lock-free. (Proxied TLS and server links keep a thread each; + there are few of them.) +- **Resilience is built in.** Slow work (KDF hashing, DNS, disk snapshots) runs off + the core so a flood can't freeze it; each event and each connection's I/O is + panic-isolated so one bad client can't crash the server; a watchdog flags a stuck + core; and half-open/stalled connections are reaped on a timer. **Why a raw reactor and not async?** IRC is one large shared mutable graph, and almost every command mutates it and then broadcasts. With one thread owning all of @@ -106,9 +106,9 @@ it, handlers are plain synchronous code — no locks, no `.await`, no `Send + 's bounds. A multi-threaded async runtime would force that shared state behind mutexes or an actor mailbox, and a channel broadcast is serialized anyway, so you'd pay for parallelism the workload can't use. `mio` is the same readiness layer async runtimes -build on, so you keep the scaling without the runtime. What *does* parallelize — -the socket syscalls and TLS crypto — runs in the reactor pool; scaling past one -machine is done by linking servers, not threading one harder. +build on, so you keep the scaling without the runtime. What *does* parallelize — the +socket syscalls and TLS crypto — runs in the reactor pool; scaling past one machine +is done by linking servers, not threading one harder. Memory safety is structural: `Uid` handles instead of raw pointers, an `Extensible` typemap instead of `void*` module data (freed on drop), and compiled-in trait @@ -117,13 +117,13 @@ objects instead of a fragile plugin ABI. **Full design notes:** ## Extending -Three small extension points, each one file + one table line — full reference and -a tutorial in [`docs/api/`](docs/api/): +Three small extension points, each one file + one table line — full reference and a +tutorial in [`docs/api/`](docs/api/): - **Commands** (`src/command.rs`, `src/coremods/`) — a handler with `name`, `min_params`, `before_reg`, `handle(&mut Server, uid, params)`. -- **Modes** (`src/mode.rs`) — channel/user modes as `ChanMode` / `UserMode` - handler objects; adding one never touches the parser. +- **Modes** (`src/mode.rs`) — channel/user modes as `ChanMode` / `UserMode` handler + objects; adding one never touches the parser. - **Modules** (`src/module.rs`, `src/modules/`) — lifecycle hooks; pre-hooks can **Deny** a register/command/message, notify-hooks fire after. @@ -136,7 +136,4 @@ a tutorial in [`docs/api/`](docs/api/): ## License -echoIRCd is released under the [MIT License](Cargo.toml). It is original Rust — -no code is copied or translated from any other project, enforced on every edit by -`scripts/native-rust-guard.sh` (no `unsafe`, no C/FFI, dependencies limited to -`openssl` + `mio`). +echoIRCd is released under the [MIT License](Cargo.toml). diff --git a/docs/README.md b/docs/README.md index 0b704c3..6b99a5a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,15 +1,14 @@ # echoIRCd documentation -echoIRCd is a from-scratch IRC + IRCv3 server written in safe Rust -(`#![forbid(unsafe_code)]`) with two dependencies — `openssl` for TLS and `mio` -for the socket engine. A single lock-free core thread owns all state; a pool of -reactor threads drives the connections around it. +echoIRCd is a memory-safe IRC + IRCv3 server written in Rust. A single lock-free +core thread owns all state; a pool of epoll reactor threads drives the connections +around it — TLS crypto and all — with no async runtime. This folder is the reference manual. Start with whichever fits what you're doing: | Doc | What's in it | |-----|--------------| -| [Building & running](building.md) | Prerequisites, debug/release builds, tests, the originality guard, project layout. | +| [Building & running](building.md) | Prerequisites, debug/release builds, tests, project layout. | | [Configuration](configuration.md) | The config file format and a grouped reference of every setting. | | [Architecture](architecture.md) | The single-threaded core + reactor-pool design, the I/O models, resilience, and memory safety. Read this to understand *why* it's built the way it is. | | [Channel & user modes](modes.md) | Every prefix, list, parameter, and flag mode, plus extbans. | @@ -23,7 +22,7 @@ This folder is the reference manual. Start with whichever fits what you're doing ## At a glance - **Full IRC core** — registration, channels, messaging, and the informational - command set (~130 commands total). + command set (100+ commands total). - **Complete mode set** — the standard prefixes plus a staff prefix, list modes, keyed/limit/flood/redirect/history/anticaps parameters, the full flag set, and matching + acting extbans. See [modes](modes.md). @@ -33,10 +32,13 @@ This folder is the reference manual. Start with whichever fits what you're doing - **Operators & services** — a rich oper toolbox with oper levels, X-lines persisted to disk, and a services interface (SASL over links, the `SVS*` / `ENCAP` / `METADATA` set, account-gated modes). -- **Transports** — plaintext, TLS (with client-cert fingerprints), a native - WebSocket layer, and the PROXY protocol behind a load balancer. +- **Transports** — plaintext, TLS (OpenSSL or rustls backend, with client-cert + fingerprints), a native WebSocket layer, and the PROXY protocol behind a load + balancer. - **Security** — keyed host cloaking, DNSBL, GeoIP, layered connection/message flood limits, and script/gibberish spam detection. +- **Control & observability** — a token-authenticated JSON-RPC plane over HTTP and + an optional OpenMetrics/Prometheus endpoint. See [configuration](configuration.md). ## Design in one paragraph diff --git a/docs/api/README.md b/docs/api/README.md index 3693ebe..4c1b6cf 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -2,7 +2,7 @@ This is the reference for extending echoIRCd. The server has five extension points, all ordinary Rust trait objects compiled into the binary — there is no -plugin ABI, no dynamic loading, and no `unsafe`: +plugin ABI and no dynamic loading: | You want to… | Implement | Registered in | Reference | |--------------|-----------|---------------|-----------| @@ -41,9 +41,9 @@ Modules in this codebase follow a few hard rules — match them: literal default. 4. **Register in the table**, don't touch the parser or the dispatcher. Adding a command / mode / module is one new file plus one line in a registration table. -5. **Original Rust only.** No `unsafe`, no C/FFI, no new dependencies, and no code - copied or translated from another project. `scripts/native-rust-guard.sh` - enforces this on every edit. +5. **Stay self-contained.** A module shouldn't pull in a heavy new dependency — + the primitives you'll reach for (an HTTP client, a regex engine, base64, the + hashing/KDF helpers) already live in the tree; reuse them. ## Write your first module in five steps @@ -92,11 +92,10 @@ pub fn default_modules() -> Vec> { **4. (Only if it adds a command)** expose a `commands()` function from your module and chain it into `module_commands()` — see [commands](commands.md). -**5. Build, test, and check:** +**5. Build and test:** ```sh cargo build && cargo test -bash scripts/native-rust-guard.sh src/modules/hello.rs ``` That's it — `hello` is now a first-class part of the server. diff --git a/docs/architecture.md b/docs/architecture.md index 396d821..4a9eff1 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -91,7 +91,7 @@ cares which one a connection uses: | Transport | Model | Notes | |-----------|-------|-------| | **Plaintext clients** | reactor pool | The common case; one worker frames many sockets. | -| **Direct TLS clients** | reactor pool | The handshake and record crypto run **non-blocking inside the worker** (OpenSSL driven off a `mio` socket). TLS work spreads across cores like everything else. | +| **Direct TLS clients** | reactor pool | The handshake and record crypto run **non-blocking inside the worker**, driven off a `mio` socket by the configured TLS backend (OpenSSL by default, or rustls via `tls_backend = rustls`). TLS work spreads across cores like everything else. | | **Proxied TLS** (a PROXY header before the handshake) | thread per connection | Reading the pre-handshake header wants the simpler blocking path; there are few of these. | | **Server links** | thread per connection | A handful of long-lived peers; not worth multiplexing. | @@ -131,11 +131,12 @@ kernel-level filtering. ## Memory safety -Safety is structural, not just `#![forbid(unsafe_code)]`: +Safety is structural, not just a matter of avoiding raw pointers: - **Handles, not pointers.** Users and channels are referenced by `Uid` / channel-key handles looked up in maps, so there are no dangling references and - no use-after-free. + no use-after-free — a `Uid` is monotonic and never reused, so a stale handle + resolves to nothing rather than to the wrong user. - **A typemap, not `void*`.** Modules attach per-user / per-channel / per-server state through an `Extensible` typemap keyed by Rust type; it's dropped automatically with its owner, so module state can't leak or be freed twice. @@ -143,11 +144,6 @@ Safety is structural, not just `#![forbid(unsafe_code)]`: compiled-in trait objects. There is no dynamic-loading FFI boundary to get wrong. -The two dependencies (`openssl`, `mio`) keep their own `unsafe` internal, so the -daemon itself never writes any. The `scripts/native-rust-guard.sh` check enforces -all of this on every edit: no `unsafe`, no C/FFI, dependencies limited to those -two, and no code copied or translated from another project. - ## Tuning knobs | Setting | Effect | diff --git a/docs/building.md b/docs/building.md index f1452eb..6e39e89 100644 --- a/docs/building.md +++ b/docs/building.md @@ -3,10 +3,10 @@ ## Prerequisites - A stable **Rust** toolchain (`cargo`, `rustc`). -- **OpenSSL** development headers (the `openssl` crate links against the system - library) — e.g. `libssl-dev` on Debian/Ubuntu. - -That's it. There are exactly two dependencies: `openssl` and `mio`. +- **OpenSSL** development headers for the default TLS backend (the `openssl` crate + links against the system library) — e.g. `libssl-dev` on Debian/Ubuntu. The + optional pure-Rust rustls backend (`tls_backend = rustls`) needs no system + library. ## Build @@ -52,20 +52,8 @@ cargo test --test integration # just the end-to-end suite The integration suite spawns the real binary on ephemeral ports and drives it as a client — covering reactor-pool cross-worker delivery, TLS-in-reactor handshakes, the stalled-handshake reap, the accept-rate limiter, and nick collisions. It -tracks and kills its child processes by PID, never by name. - -## The originality guard - -Every source edit is checked by `scripts/native-rust-guard.sh`, which enforces the -project's invariants: - -- no `unsafe` (the crate is `#![forbid(unsafe_code)]`), -- no C / FFI, -- dependencies limited to `openssl` + `mio`, -- and no code copied or translated from any other project — everything is - original Rust. - -Run it on a file directly with `bash scripts/native-rust-guard.sh `. +tracks and kills its child processes by PID, never by name. The parser and the S2S +convergence logic also carry property-based (`proptest`) suites. ## Project layout @@ -82,7 +70,7 @@ src/ command.rs the Command trait module.rs the module lifecycle-hook trait coremods/ built-in commands (registration, channels, messaging, oper, …) - modules/ optional, pluggable modules (~70 of them) + modules/ optional, pluggable modules (70+ of them) tests/ end-to-end integration tests deploy/ production systemd units + firewall script docs/ this manual diff --git a/docs/configuration.md b/docs/configuration.md index 485ab4d..6572814 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -29,6 +29,8 @@ Most settings apply on `REHASH` without a restart. | `bind` | Plaintext client listener, `ip:port` (e.g. `0.0.0.0:6667`). | | `bind_tls` | TLS client listener (e.g. `0.0.0.0:6697`). | | `tls_cert` / `tls_key` | PEM certificate + private key for TLS (and `wss://`). | +| `tls_sni` | Serve a different cert for a given hostname (` `, repeatable). | +| `tls_backend` | `openssl` (default) or `rustls` (pure-Rust, no system OpenSSL). | | `bind_server` | Server-to-server link listener (see [linking](linking.md)). | Generate a self-signed cert to start: @@ -148,6 +150,14 @@ See [anti-abuse](anti-abuse.md) for how these layer together. | `log_json` | Append the notice/log stream to a file as JSON lines. | | `chanlog` | Mirror the oper server-notice stream into a channel. | +## Control & observability + +| Key | Meaning | +|-----|---------| +| `metrics_bind` | Bind an OpenMetrics/Prometheus scrape endpoint (`ip:port`, plaintext HTTP GET). Off unless set — expose it privately or behind a proxy. | +| `rpc` + `rpc_bind` | Enable the JSON-RPC control plane and bind its HTTP listener. Both required to turn it on. | +| `rpc_user` / `rpc_token` | Credentials for the control plane — sent as HTTP Basic (`user:token`) or Bearer. Bind privately; the token is a shared secret. | + ## Transports | Key | Meaning | diff --git a/docs/deployment.md b/docs/deployment.md index 880af67..fc35bc5 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -96,7 +96,7 @@ A connection from a trusted proxy must lead with a PROXY (v1 or v2) header. This applies to the plaintext and TLS client listeners; for browser clients over WebSocket, use `ws_proxyranges` with `X-Forwarded-For` instead. -## Log shipping +## Log shipping & metrics | Setting | Sends the notice/log stream to | |---------|--------------------------------| @@ -107,6 +107,13 @@ WebSocket, use `ws_proxyranges` with `X-Forwarded-For` instead. The core also surfaces its own health: `slow_command_ms` raises a notice when an event runs long, and `watchdog_ms` logs if the core is stuck. +For a metrics pipeline, bind the OpenMetrics/Prometheus endpoint with +`metrics_bind = 127.0.0.1:9109` and scrape it (counters for commands / messages / +connects, gauges for users / channels / servers / links). For scripted control, +the JSON-RPC plane (`rpc` / `rpc_bind` / `rpc_token`) exposes admin operations over +HTTP. Bind both privately — on loopback or behind the reverse proxy, never on a +public interface. + ## TLS certificates Point `tls_cert` / `tls_key` at your PEM files (the same pair serves `bind_tls` diff --git a/docs/ircv3.md b/docs/ircv3.md index 43bf263..5d1290b 100644 --- a/docs/ircv3.md +++ b/docs/ircv3.md @@ -29,6 +29,9 @@ informed as they change. This page groups what's supported. | `multi-prefix` | See all of a member's status prefixes at once. | | `userhost-in-names` | Full `nick!user@host` in `NAMES`. | | `invite-notify` | Channel ops see invites to their channel. | +| `draft/pre-away` | Send `AWAY` during registration so away state is set before the first `JOIN`. | +| `no-implicit-names` | Suppress the automatic `NAMES` reply on `JOIN` (the client asks when it wants it). | +| `draft/channel-rename` | `RENAME` a channel in place, keeping membership. | ## Authentication @@ -60,6 +63,7 @@ control who may message them. | `draft/metadata-2` | `METADATA` key/value data on users and channels. | | `draft/extended-isupport` | Re-request the current ISUPPORT tokens on demand. | | `draft/json-log` | Stream the server log to an oper as JSON. | +| `sts` | Strict Transport Security — tell a client to upgrade to TLS and pin that for a duration (opt-in via `sts_duration` / `sts_port` / `sts_preload`). | | `EXTJWT` | A short-lived, server-signed HS256 token a client can present elsewhere. | | network icon / profile link | Advertise a network icon and per-account profile URLs. | diff --git a/echoircd.conf.example b/echoircd.conf.example index 7a6de0a..01f608a 100644 --- a/echoircd.conf.example +++ b/echoircd.conf.example @@ -22,8 +22,16 @@ tls_key = ./tls/key.pem # The cert is re-read on REHASH, so a renewed cert applies without a restart. # SNI: serve a different cert for a given hostname. Repeatable. # tls_sni = irc.example.net ./tls/example.crt ./tls/example.key +# TLS backend: openssl (default) or rustls (pure-Rust, no system OpenSSL needed). +# tls_backend = rustls +# STS (Strict Transport Security): tell CAP 302 clients on the plaintext port to +# upgrade to TLS and pin it. Off unless sts_duration > 0. Set sts_port to your TLS +# port. Only enable once TLS is solid — clients will refuse plaintext for the pin. +# sts_duration = 2592000 # seconds clients should stick to TLS (0 = off) +# sts_port = 6697 # the TLS port to upgrade to +# sts_preload = no # advertise preload eligibility -motd = Welcome to echoIRCd — a from-scratch IRC daemon in Rust. +motd = Welcome to echoIRCd. motd = Edit the MOTD in your echoircd.conf. # --- server-to-server linking --- @@ -192,6 +200,18 @@ amu_target = both # --- log_json: append the server-notice / log stream to a file as JSONL --- # log_json = /var/log/echoircd/events.jsonl +# --- metrics: OpenMetrics/Prometheus scrape endpoint (plaintext HTTP GET). Off +# unless bound; expose it only on a private/loopback address or behind a proxy. --- +# metrics_bind = 127.0.0.1:9109 + +# --- rpc: token-authenticated JSON-RPC control plane over HTTP (admin tooling). +# Off unless rpc = yes AND rpc_bind is set. Bind privately; the token is a +# shared secret sent as HTTP Basic (rpc_user:rpc_token) or Bearer. --- +# rpc = yes +# rpc_bind = 127.0.0.1:8080 +# rpc_user = admin +# rpc_token = CHANGE_THIS_RPC_TOKEN + # --- PROXY protocol: trust the HAProxy/nginx PROXY header (v1 or v2) from these # sources (glob or CIDR, repeatable), so the real client IP is used instead of # the proxy's. A connection from a trusted proxy MUST lead with a PROXY header.