# echoIRCd config — simple key = value (repeat `motd` for extra lines). # Copy this file to `echoircd.conf` and fill in your own values. # NOTE: echoircd.conf is gitignored because it holds secrets (oper password, # cloak key, link password). Never commit your real config. servername = irc.example.net network = ExampleNet bind = 0.0.0.0:6667 # TLS listener. Generate a cert/key first, e.g.: # openssl req -x509 -newkey rsa:2048 -keyout tls/key.pem -out tls/cert.pem \ # -days 3650 -nodes -subj "/CN=irc.example.net" bind_tls = 0.0.0.0:6697 tls_cert = ./tls/cert.pem tls_key = ./tls/key.pem motd = Welcome to echoIRCd — a from-scratch IRC daemon in Rust. motd = Edit the MOTD in your echoircd.conf. # --- server-to-server linking --- sid = 0AA serverdesc = echoIRCd server bind_server = 0.0.0.0:7000 # link = [autoconnect] (the password is a shared secret) # link = peer.example.net 203.0.113.5 7000 CHANGE_THIS_LINK_SECRET autoconnect # services: the linked server that handles SASL (client AUTHENTICATE is relayed to # it). Leave unset to disable SASL. SASL EXTERNAL additionally needs the client on # TLS with a client certificate (its fingerprint is sent to services). # sasl_server = services.example.net # trusted web gateways (CGI:IRC / kiwiirc-style): they send WEBIRC to declare the # real client's host+ip. webirc = [gateway-name] [ip-mask]; the ip-mask # restricts which source IP may use the password (recommended). Repeat for more. # webirc = CHANGE_THIS_WEBIRC_SECRET mygateway 203.0.113.9 # IRC operators — oper = oper = admin CHANGE_THIS_PASSWORD # host-cloaking secret (+x). Use a long random hex string; keep it private. # Changing it re-cloaks everyone. cloak_key = CHANGE_THIS_TO_A_LONG_RANDOM_HEX_STRING # reverse-DNS clients on connect (the "*** Looking up your hostname..." notices). # on (default) performs the lookup and reports the result; off skips it (bare IP). resolve_hosts = on # whether a resolved hostname is used in the hostmask (nick!user@host). on (default) # shows the domain; off keeps the IP in the mask even though the lookup still runs # and reports "Found your hostname". Only matters when resolve_hosts = on. use_resolved_host = on # DNS blocklist (DNSBL) checks on connect, like InspIRCd's m_dnsbl. Repeat `dnsbl` # for multiple zones. On a listing, `dnsbl_action` decides what happens: # mark = just show the "*** ... LISTED" notice, let them in (default, safe) # kill = disconnect them (no persistent ban) # kline / gline / zline = add a 1-day ban and disconnect # (leave commented to disable DNSBL entirely) # dnsbl = dnsbl.dronebl.org # dnsbl = rbl.efnetrbl.org # dnsbl_action = mark # dnsbl_reason = Your host is listed in a DNS blocklist # antimixedutf8 — block spam that mixes look-alike scripts within words. # action = block | kill | gline | kline | zline ; target = both | channel | private antimixedutf8 = off amu_threshold = 8 amu_minlen = 10 amu_action = block amu_target = both # +G censor words: `badword = [replacement]` (omit replacement to block). # badword = examplebadword *** # --- OPERMOTD: message shown to opers via /OPERMOTD (one line per entry) --- # opermotd = Welcome to the staff team. # --- self-service vhosts: /VHOST sets your displayed host --- # vhost = alice s3cret alice.staff.example # --- command aliases: /NS ... -> PRIVMSG :... (services shortcuts) --- # alias = NS NickServ # alias = CS ChanServ # --- connflood: refuse >max connections per from a single IP --- # connflood = 5 10 # --- security groups (UnrealIRCd-style): securitygroup = [criteria...] # criteria: public tls insecure account unregistered oper exclude-oper # bot exclude-bot webirc exclude-webirc mask= exclude= # scoremin= scoremax= — use as an extban: MODE #c +b g: # securitygroup = trusted account tls public # securitygroup = newbies scoremax=10 public # --- reputation (m_reputation): per-address scoring + y: score extban --- # reputation_database = reputation.db # default: .reputation # reputation_ipv4prefix = 32 # CIDR bits used to key IPv4 scores # reputation_ipv6prefix = 64 # CIDR bits used to key IPv6 scores # reputation_bumpinterval = 5m # how often a score bumps (+1, +2 if logged in) # reputation_expireinterval = 605 # how often decay rules run # reputation_saveinterval = 902 # how often the db is written # reputation_minchanmembers = 3 # only bump if in a channel this big # reputation_scorecap = 10000 # max score # reputation_whois = all # all | opers | self | none # reputationexpire = 2 1h # score<=2 decays after 1h (repeatable; * = any) # reputationexpire = * 90d # any score decays after 90d # extban usage: MODE #chan +b y:<100 (ban score below 100) +b y:>500 (above 500) # --- whoisport: opers see the target's listener port in WHOIS (always on) --- # --- ircv3_network_icon: advertise a network icon via draft/ICON ISUPPORT --- # network_icon = https://example.org/icon.png # --- profileLink: a profile URL in WHOIS for logged-in users --- # profilelink_baseurl = https://example.org/profile/ # --- hidewhois: hide sensitive WHOIS lines from ordinary users --- # hidewhois = yes # hidewhois_opers = yes # opers still see everything # hidewhois_selfview = yes # a user sees their own full WHOIS # hidewhois_hide_server = yes # hide 312 # hidewhois_hide_idle = yes # hide 317 # hidewhois_hide_secure = yes # hide 671 # --- chanlog (m_chanlog): mirror the oper server-notice stream into a channel so # staff can watch it in a normal window. Set the channel (create/keep it opped): # chanlog = #snotices # --- helpmode (m_helpmode): no config — adds oper-settable user mode +h (helpop), # which shows "is available for help" in the user's WHOIS. # --- globops (m_globops): no config — adds the oper command /GLOBOPS , # broadcasting to all opers (like the server-notice stream). # --- autodrop (m_autodrop): silently drop a not-yet-registered client that sends # any of these commands (HTTP scanners blurt GET/POST before NICK/USER): # autodrop_commands = GET POST HEAD CONNECT PUT DELETE OPTIONS TRACE PATCH # --- hidelist (m_hidelist): list modes (+b/+e/+I/…) are viewable by members by # default; this restricts a given list to a minimum rank. Repeatable, # `hidelist = ` (rank: owner|admin|op|halfop|voice). Opers see # everything. e.g. only ops may view the ban list: # hidelist = b op # --- autoop (m_autoop): no config needed — it's the channel list mode +w. Grant a # status prefix to matching users on join, `+w :`, e.g. # /MODE #chan +w o:*!*@trusted.host (auto-op) # /MODE #chan +w v:*!*@*.friend.net (auto-voice) # /MODE #chan +w lists the entries. # --- banredirect (m_banredirect): no config needed — it extends ban syntax. A # ban `+b $<#channel>` bounces a matching user into #channel instead of # refusing them, e.g. /MODE #main +b *!*@*.spammer.net$#quarantine # The redirect fires at most once (never loops). # --- solvemsg (m_solvemsg): an un-vouched user must answer one arithmetic # question before their private messages are delivered (opers & logged-in # accounts are exempt). Cheap anti-spam-bot gate. # solvemsg = yes # --- dccallow (m_dccallow): block unwanted DCC transfers unless the recipient # ran /DCCALLOW +. Blocked file globs are repeatable; blockchat also # gates DCC CHAT. Recipients manage their allow-list with DCCALLOW +/-/LIST. # dccallow_blockfile = *.exe # dccallow_blockfile = *.scr # dccallow_blockchat = yes # dccallow_maxentries = 20 # --- conn_waitpong (m_conn_waitpong): hold registration until the client answers # a server PING with the exact cookie — filters bots that never PONG. Real # clients auto-reply, so it's transparent to them. # conn_waitpong = yes # conn_waitpong_killonbadreply = yes # drop on a wrong pong (default: keep waiting) # --- showfile (m_showfile): serve a text file as its own command. One line per # file: `showfile = `. The file is read fresh each use, so # edits show without a rehash. e.g. make /RULES stream a rules file: # showfile = RULES /etc/echoircd/rules.txt # --- geoip (m_geo_maxmind): native MaxMind .mmdb country lookup. Enables the # G: ban extban (e.g. +b G:CN,RU), the oper GEOIP command and # a country line in WHOIS (opers). Point at a GeoLite2-Country.mmdb file: # geoip_database = /etc/echoircd/GeoLite2-Country.mmdb # --- tunable limits & timeouts (every one shown with its built-in default; set a # line only to override it). None of these are hardcoded — all read at runtime. # flood: allow this many messages per this many seconds before dropping (opers exempt) # flood_messages = 8 # flood_seconds = 4 # dnsbl: ban length in seconds when dnsbl_action is kline/gline/zline (default 1 day) # dnsbl_duration = 86400 # draft/multiline: the max-bytes / max-lines advertised in the cap AND enforced # multiline_maxbytes = 4096 # multiline_maxlines = 24 # CHATHISTORY: messages kept per conversation (also the ceiling a client may request) # chathistory_limit = 256 # EXTJWT: token line-chunk size (bytes) when splitting a long token across lines # extjwt_chunk = 200 # per-user list sizes (advertised in ISUPPORT WATCH/MONITOR/SILENCE where applicable) # maxwatch = 128 # maxmonitor = 128 # maxsilence = 32 # maxaccept = 64 # WHOWAS: number of historical nick records retained # whowas_maxentries = 256 # nick / channel name length limits (advertised as NICKLEN / CHANNELLEN) # maxnick = 30 # maxchannel = 50 # connection timeouts, in seconds # registration_timeout = 60 # drop clients that never register (NICK+USER) in time # ping_frequency = 90 # send a PING after this much idle time # ping_timeout = 60 # then drop if no PONG within this much longer