# 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 ""; # 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).