website/content/docs/configuration.md

306 lines
10 KiB
Markdown

# Configuration
echoIRCd reads one file — `echoircd.conf` by default. This page walks you from a two-line starter
config to a full, production-ready one, section by section. Every option (with its default) is listed
in the [Configuration reference](/docs/config-reference), and the shipped `echoircd.conf.example` is
the same thing as a file you can copy.
```sh
cp echoircd.conf.example echoircd.conf # then edit it
```
## The format
Config is a set of **blocks**`section { field value; … }`:
- **One field per `;`.** A block may span multiple lines.
- **Comments:** `#` and `//` for a line, `/* … */` for a range. An inline `#` on an active line is
part of the value unless you quote the value, so quote anything containing `#` or spaces.
- **Booleans** are `yes` / `no`. A bare field (e.g. `operprefix;`) means `yes`.
- **Defaults are built in** — you only set a field to *change* it.
- Most changes re-apply on **`echoircd rehash`** (SIGHUP) with no restart; the TLS cert is re-read
too.
> `echoircd.conf` holds secrets (oper password, cloak key, link password) — it's gitignored in the
> source tree for that reason. Never commit your real config.
## Minimal config
The smallest thing that boots — plaintext on 6667:
```ini
server {
name "irc.example.net"; # your server's unique name
network "ExampleNet"; # the network name clients see
sid "0AA"; # 3 chars: a digit + 2 alphanumerics
}
listen { ip "[::]"; port 6667; } # plaintext, IPv4 + IPv6
```
That's a working IRC server. Everything below adds TLS, operators, services, and hardening.
## A complete example
A realistic config you can copy and adapt. Uncommented lines are a sensible starting point;
commented lines show common extras.
```ini
# ── server identity ──────────────────────────────────────────────
server {
name "irc.example.net";
network "ExampleNet";
sid "0AA";
description "ExampleNet IRC";
pidfile "echoircd.pid"; # lets `echoircd rehash` find the process
}
# ── listeners (repeatable; [::] = IPv4 + IPv6) ───────────────────
listen { ip "[::]"; port 6667; } # plaintext
listen { ip "[::]"; port 6697; tls yes; } # direct TLS
listen { ip "[::]"; port 7799; wss yes; } # WebSocket (browser clients)
listen { ip "[::]"; port 7000; type server; } # server-to-server links
# ── TLS (cert re-read on rehash) ─────────────────────────────────
tls {
cert "./tls/cert.pem";
key "./tls/key.pem";
# backend openssl; # or rustls (pure-Rust, no system OpenSSL)
}
# ── message of the day ───────────────────────────────────────────
motd {
"Welcome to ExampleNet.";
"Be excellent to each other.";
}
# ── host cloaking: mode +x hides a user's real host ──────────────
cloak { key "REPLACE-WITH-A-LONG-RANDOM-HEX-STRING"; }
# ── operators ────────────────────────────────────────────────────
# Hash the password: printf '%s' 'yourpass' | ./echoircd mkpasswd
oper {
name "admin";
password "$2b$11$REPLACE_WITH_A_BCRYPT_HASH";
type netadmin; # full access (a built-in type)
# fingerprint "<sha256-cert-fp>"; # optional TLS-cert 2FA
}
# ── link to services (NickServ / ChanServ / …) ───────────────────
# link {
# name "services.example.net";
# ip 127.0.0.1;
# port 7000;
# password "REPLACE-WITH-A-LINK-SECRET";
# services yes; # mark it a U-lined services server
# }
# services { sasl_server "services.example.net"; }
# ── sensible tuning ──────────────────────────────────────────────
flood { flood_messages 8; flood_seconds 4; }
timeouts { registration_timeout 60; ping_frequency 90; ping_timeout 60; }
antiabuse { antirandom yes; solvemsg yes; }
logging { metrics_bind "127.0.0.1:9109"; }
```
The rest of this page explains each piece.
## Listeners
Each `listen` block opens one socket; add as many as you need. `ip "[::]"` (or `"*"`) binds IPv4 and
IPv6 at once. `type server` is the port other servers (and the services package) link to.
```ini
listen { ip "[::]"; port 6667; } # plaintext
listen { ip "[::]"; port 6697; tls yes; } # direct TLS
listen { ip "[::]"; port 7799; wss yes; } # WebSocket-over-TLS
listen { ip "127.0.0.1"; port 8097; ws yes; } # plaintext WebSocket (behind a proxy)
listen { ip "[::]"; port 7000; type server; } # S2S
```
## TLS
Point the `tls` block at a certificate and key. Use a real certificate (Let's Encrypt) in production;
for a quick test, a self-signed one works:
```sh
openssl req -x509 -newkey rsa:2048 -keyout tls/key.pem -out tls/cert.pem \
-days 3650 -nodes -subj "/CN=irc.example.net"
```
```ini
tls {
cert "./tls/cert.pem";
key "./tls/key.pem";
backend openssl; # or: rustls
# Per-host certificate by TLS SNI (repeatable):
# sni "irc.other.net ./tls/other.crt ./tls/other.key";
}
```
The certificate is re-read on `echoircd rehash`, so a renewed cert applies without a restart.
## Operators
First hash a password:
```sh
printf '%s' 'my-strong-password' | ./echoircd mkpasswd
```
Then an `oper` block ties a login to a role. `type netadmin` gives full access; drop `type` for full
access with no role. A block with neither a password nor a fingerprint is refused.
```ini
oper {
name "alice";
password "$2b$11$…"; # from mkpasswd
type netadmin;
host "*@192.0.2.0/24"; # optional: restrict where alice may oper from
# fingerprint "AA:BB:…"; # require this TLS client-cert (2FA, or alone)
}
```
`/oper alice my-strong-password` logs in. For custom roles — limiting which commands, privileges, and
modes an operator has — define `class` and `opertype` blocks; see [Operators](/docs/operators).
## Host cloaking
Mode `+x` replaces a user's host with a stable, keyed cloak. Set a long random secret and keep it
private (changing it re-cloaks everyone):
```ini
cloak {
key "a-long-random-hex-secret";
# method hmac-sha256; # default; or account / fingerprint / static
}
```
## Connection classes
Fine-grained per-client policy, matched by IP/host/TLS/port — first match wins. Each class is one
quoted string of `key=value` tokens.
```ini
classes {
connectclass "trusted allow=10.0.0.0/8 maxchans=200 pingfreq=120 fakelag=no";
connectclass "secure allow=* requiressl=yes";
connectclass "vpn allow=* parent=trusted localmax=2 maxchans=20 modes=+ix";
connectclass "banned allow=1.2.3.0/24 deny=yes";
# connectclass_required yes; # refuse clients matching no allow class
}
```
Common tokens: `allow=`, `deny=yes`, `requiressl=yes|trusted`, `password=`, `port=`, `asn=`,
`localmax=`/`globalmax=`, `maxchans=`, `pingfreq=`/`timeout=`, `modes=`, `recvq=`/`softsendq=`/
`hardsendq=`, `fakelag=no`, `useident=yes`. The full list is in the
[reference](/docs/config-reference#classes).
## DNS & ident
```ini
dns {
resolve_hosts yes; # reverse-DNS on connect (no = show the bare IP)
use_resolved_host yes; # use the resolved name in the hostmask
# useident yes; # RFC 1413 ident lookups (adds connect latency)
# requireident yes;
}
```
## Limits, timeouts & flood
All optional — the defaults are sane. Set only what you want to change.
```ini
limits { maxchannel 50; maxnick 30; chathistory_limit 256; }
timeouts { registration_timeout 60; ping_frequency 90; ping_timeout 60; }
flood { flood_messages 8; flood_seconds 4; connflood "5 10"; }
```
## Anti-abuse
Layered spam/drone defence — turn on what you need:
```ini
antiabuse {
antirandom yes; # score random-looking nick/ident/realname
solvemsg yes; # unvouched users answer a sum before PMs deliver
# badword "spamword ***"; # +G censor (omit the replacement to block)
}
restrictions {
# restrictmsg yes; # only opers/services may be PM'd by regular users
autodrop_commands "GET POST HEAD CONNECT PUT DELETE OPTIONS TRACE PATCH";
}
# DNS blocklists (repeatable):
# dnsbl {
# dnsbl "dnsbl.dronebl.org";
# dnsbl_action "mark"; # mark | kill | kline | gline | zline
# }
```
See [Security & anti-abuse](/docs/security) for the whole picture.
## Logging & metrics
```ini
logging {
metrics_bind "127.0.0.1:9109"; # Prometheus endpoint (keep it private)
# syslog yes; # mirror to the system logger
# syslog_target "/dev/log";
# log_json "/var/log/echoircd/events.jsonl";
# chanlog "#snotices"; # mirror oper notices into a channel
}
```
See [Metrics & RPC](/docs/metrics-rpc).
## Linking services
The services package (NickServ, ChanServ, …) connects over the S2S port. Give it a `link` block, mark
it U-lined, and name it as the SASL server:
```ini
listen { ip "[::]"; port 7000; type server; }
link {
name "services.example.net";
ip 127.0.0.1;
port 7000;
password "shared-link-secret";
services yes; # U-lined services server
}
services { sasl_server "services.example.net"; }
```
Full details on both sides are in [Server links](/docs/linking) and [Services](/docs/services).
## WebSocket & STS
If you run a `ws`/`wss` listener, tune it and (once TLS is solid) advertise STS to push plaintext
clients onto TLS:
```ini
websocket {
ws_origin "https://webchat.example.net"; # allowed Origins (repeatable; empty = any)
ws_proxyranges "127.0.0.1"; # trusted reverse-proxy IPs
}
# sts {
# sts_duration 2592000; # seconds clients should stick to TLS (0 = off)
# sts_port 6697;
# }
```
## Validate & apply
Always check a config before deploying it, then reload in place:
```sh
echoircd checkconfig echoircd.conf # parse + print every resolved key (catches typos)
echoircd rehash echoircd.conf # SIGHUP the running server — no restart, no disconnects
```
For every field and its default, see the [Configuration reference](/docs/config-reference).