docs: rework README + manual — refresh the feature set (services interface, rustls TLS backend, WebSocket, PROXY v1/v2, metrics + JSON-RPC endpoints), correct command/module/cap counts, and document the tls_backend/metrics_bind/rpc/sts config keys in configuration.md and the example
This commit is contained in:
parent
b106b66de5
commit
ebd6e29589
9 changed files with 121 additions and 98 deletions
107
README.md
107
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.**
|
||||
|
||||
[](Cargo.toml)
|
||||
[](https://www.rust-lang.org)
|
||||
[](src/lib.rs)
|
||||
[](https://ircv3.net)
|
||||
[](Cargo.toml)
|
||||
|
||||
</div>
|
||||
|
||||
## 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:<cc>` 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:<cc>` 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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Box<dyn Module>> {
|
|||
**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.
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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 <file>`.
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 (`<host> <cert> <key>`, 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 |
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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. |
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue