Skip to content

KaraZajac/rIRCd

Repository files navigation

rIRCd

A bleeding-edge IRC server in Rust, following IRCv3 specifications.

Requirements

  • Rust (stable, 2021 edition or later)
  • MariaDB or MySQL server

Initial Setup

1. Set up the database

Create a database and user in MariaDB:

CREATE DATABASE rircdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'rirc'@'localhost' IDENTIFIED BY 'your-password';
GRANT ALL PRIVILEGES ON rircdb.* TO 'rirc'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

The database schema (tables for users, channels, channel history, etc.) is created automatically on first startup — no SQL migration files to run.

2. Install rIRCd

cargo build --release
sudo cp target/release/rircd /usr/local/bin/

3. Run the interactive setup

sudo rircd init

This starts an interactive prompt that asks for:

  • Server hostname and network name
  • Plain-text port (default: 6667) and optionally a TLS port with cert/key paths
  • Database credentials (host, port, name, user, password)
  • Message of the day
  • Optionally, an IRC operator account (password is bcrypt-hashed automatically)

A config.toml is written to /etc/rIRCd/ with all your answers filled in. If the file already exists you are asked before overwriting.

Example session:

rIRCd interactive setup
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Press Enter to accept the [default] value.

[Server]
  Server hostname [irc.example.com]: irc.mynetwork.org
  Network name [rIRCd]: MyNet
  Plain-text IRC port [6667]:
  Message of the day [Welcome to rIRCd!]: Welcome to MyNet!

[TLS]
  Enable TLS listener? [y/N]: y
  TLS port [6697]:
  Path to certificate (PEM) [/etc/rIRCd/cert.pem]:
  Path to private key (PEM) [/etc/rIRCd/key.pem]:

[Database]
  (rIRCd requires MariaDB/MySQL for user accounts and channel history.)
  Database host [localhost]:
  Database port [3306]:
  Database name [rircdb]:
  Database user [rirc]:
  Database password:

[IRC Operator]
  Create an IRC operator account? [Y/n]:
  Operator name [admin]:
  Operator password:
  Operator password (confirm):

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Config written to /etc/rIRCd/config.toml
The database schema is created automatically on first startup.

Start the server with:  rircd run

You can always hand-edit /etc/rIRCd/config.toml afterwards — see Configuration Reference below.

4. Start the server

sudo rircd run

Connect with any IRC client to localhost:6667 (or whatever port you configured).


Configuration Reference

The only file rIRCd needs is /etc/rIRCd/config.toml. All user accounts, channels, and message history are stored in MariaDB.

[server]

Key Default Description
name rIRCd.local Server hostname shown to clients
listen [":6667"] Plain-text listener addresses
listen_tls [] TLS listener addresses (requires [tls])
listen_ws [] WebSocket listener addresses (e.g. [":7667"])
listen_wss [] WebSocket-over-TLS listener addresses (requires [tls])
motd "Welcome to rIRCd!" Message of the day (inline text, multiline OK)
registration_timeout_secs 60 Time allowed to complete NICK/USER before disconnect
ping_timeout_secs 90 How long to wait for PONG before sending next PING
disconnect_timeout_secs 150 Time after missed PONG before disconnecting client
client_tag_deny (unset) List of client-only tags to drop (e.g. ["+typing"] or ["*"] to drop all)
cloak_key (unset) If set, connecting clients receive an HMAC-SHA256-based virtual host cloak (e.g. "mysecret")

[network]

Key Default Description
name rIRCd Network name (shown in 005 NETWORK)
icon (unset) URL to a network icon image (advertised as ICON= in ISUPPORT; draft/network-icon)

[database]

Key Default Description
host localhost MariaDB/MySQL host
port 3306 MariaDB/MySQL port
user (empty) Database username
password (empty) Database password
database rircdb Database name

[tls]

Optional. Both fields must be set to enable TLS listeners.

Key Description
cert Path to PEM certificate file
key Path to PEM private key file
client_certs If true, request TLS client certificates for SASL EXTERNAL (default false)

Example:

[server]
listen_tls = [":6697"]

[tls]
cert = "/etc/rIRCd/cert.pem"
key  = "/etc/rIRCd/key.pem"

[limits]

Key Default Description
max_channels_per_client 50 Max channels a single client may join
max_line_length 8191 Max IRC line length in bytes

[[opers]]

Define IRC operators. Multiple [[opers]] blocks are allowed.

[[opers]]
name = "admin"
hostmask = "*"           # optional; restrict by host
password_hash = "$2a$..." # generate with: rircd genpasswd

[filehost]

Optional. Enables the draft/filehost HTTP file upload endpoint. When configured, rIRCd embeds an HTTP server that accepts authenticated file uploads and serves them back. Authenticated IRC users upload via HTTP Basic auth (same credentials as SASL PLAIN). The draft/FILEHOST=<url> ISUPPORT token is advertised to clients.

Key Default Description
listen 0.0.0.0:8080 HTTP listen address for the filehost
public_url (required) Public base URL clients use to reach uploads (e.g. https://irc.example.com/uploads)
upload_dir /var/lib/rircd/uploads Local directory where uploaded files are stored
max_size 52428800 (50 MiB) Maximum upload size in bytes

Example:

[filehost]
listen = "0.0.0.0:8080"
public_url = "https://irc.example.com/uploads"
upload_dir = "/var/lib/rircd/uploads"
max_size = 52428800

[webirc]

Optional. Enables WEBIRC gateway support so reverse proxies can pass the real client IP.

[webirc]
password = "gateway-secret"

Full example config

[server]
name = "irc.example.com"
listen = [":6667"]
listen_tls = [":6697"]
motd = """
Welcome to Example IRC!
Have fun and be nice.
"""
registration_timeout_secs = 60
ping_timeout_secs = 90
disconnect_timeout_secs = 150

[network]
name = "ExampleNet"

[database]
host = "localhost"
port = 3306
user = "rirc"
password = "s3cr3t"
database = "rircdb"

[tls]
cert = "/etc/rIRCd/cert.pem"
key  = "/etc/rIRCd/key.pem"

[limits]
max_channels_per_client = 50
max_line_length = 8191

[[opers]]
name = "admin"
hostmask = "*"
password_hash = "$2a$12$..."

[filehost]
listen = "0.0.0.0:8080"
public_url = "https://irc.example.com/uploads"
upload_dir = "/var/lib/rircd/uploads"
max_size = 52428800

CLI Commands

Command Description
rircd init [--dir /etc/rIRCd] Create config directory with a default config.toml
rircd run [--config /etc/rIRCd/config.toml] Start the server; connects to DB, inits schema, writes PID file
rircd stop [--config /etc/rIRCd/config.toml] Send SIGTERM to the running server (Unix only)
rircd status [--config /etc/rIRCd/config.toml] Check if the server is running via PID file
rircd genpasswd Interactively hash a password for use in [[opers]]

The PID file is written to the same directory as config.toml (e.g. /etc/rIRCd/rircd.pid) and is removed on clean shutdown. rircd stop and rircd status use it to find the process.


User Accounts

User registration is handled via the IRC REGISTER command (draft/account-registration) from any connected client:

REGISTER * [email|*] <password>

This stores a bcrypt hash of the password (for SASL PLAIN) and full SCRAM credentials (for SASL SCRAM-SHA-256) in MariaDB. Passwords must be at least 6 characters.

Authentication is supported via two SASL mechanisms:

SASL PLAIN:

CAP REQ :sasl
AUTHENTICATE PLAIN
AUTHENTICATE <base64-encoded NUL-separated authzid NUL authcid NUL password>

SASL SCRAM-SHA-256 (recommended):

CAP REQ :sasl
AUTHENTICATE SCRAM-SHA-256
AUTHENTICATE <base64-encoded client-first-message>
AUTHENTICATE <base64-encoded client-final-message>

SCRAM-SHA-256 uses PBKDF2 key derivation (4096 iterations) and provides mutual authentication — the server proves it knows your credentials without ever seeing your password in clear text over the protocol exchange.

Accounts are keyed by nick (lowercase). There is no separate admin interface for user management — use direct SQL queries on the users table if needed.


Channel Persistence

Channels, topics, modes, operator lists, voice lists, and message history are all stored in MariaDB automatically:

  • Topic — persisted whenever a channel topic is set; 333 RPL_TOPICWHOTIME and 329 RPL_CREATIONTIME sent on JOIN.
  • Channel modes — mode flags (+imnstRcC), key (+k), and user limit (+l) are saved to the database on every MODE change and restored on startup.
  • Operators / Voice — stored per channel; users in these lists receive @/+ automatically when they join.
  • Message history — PRIVMSG, NOTICE, and channel events (JOIN, PART, QUIT, TOPIC, NICK) are appended (up to 1,000 entries per channel, oldest pruned). Clients with draft/chathistory can request history via CHATHISTORY LATEST/BEFORE/AFTER/AROUND/BETWEEN #channel <cursor> <limit> or list active conversations with CHATHISTORY TARGETS timestamp=<from> timestamp=<to> <limit>. Clients with draft/event-playback receive the full event timeline; otherwise only messages are returned.
  • Edit history — Edited messages retain a pointer to their original msgid. On CHATHISTORY replay, clients with draft/message-edit receive the +draft/edit tag so they can update their local buffer.
  • Read markersMARKREAD timestamps are persisted per account in MariaDB and survive server restarts.
  • MetadataMETADATA key-value entries set on users and channels are persisted in MariaDB.

IRCv3 Support

Capability / feature Status Notes
capability-negotiation Full CAP LS/REQ/ACK/NAK/END, 302 multi-line
message-tags Full Parse & send tags; TAGMSG; msgid/server-time/account tags
Client-only tags Full Server forwards +-prefixed tags on PRIVMSG/NOTICE/TAGMSG
server-time Full time tag on messages for capped clients
message-ids Full msgid tag (with message-tags); unique id per message
batch Full NAMES and chathistory wrapped in BATCH
echo-message Full PRIVMSG, NOTICE, TAGMSG echoed to sender when cap set
multi-prefix Full NAMES/WHO send all prefixes in rank order (@%+)
extended-join Full JOIN #ch account :realname for clients with cap
account-tag Full account= tag on messages for capped clients
account-notify Full ACCOUNT on SASL login/quit to channel peers with cap
chghost Full SETHOST/SETUSER (oper-only); CHGHOST to channel peers with cap
setname Full SETNAME command; broadcast to setname peers
away-notify Full AWAY to channel peers with cap when user sets/unsets away
invite-notify Full INVITE to channel members with cap when someone is invited
labeled-response Full Client label tag echoed on all replies
standard-replies Full FAIL for SETNAME, REDACT, UTF-8 errors
no-implicit-names Full No NAMES burst on JOIN when client has cap
userhost-in-names Full NAMES (353) with full nick!user@host when client has cap
utf8only Full Non-UTF-8 rejected with FAIL when client has standard-replies
cap-notify Full CAP NOTIFY with current cap list on REQ/ACK and END; dynamic CAP NEW/CAP DEL on REHASH
draft/extended-isupport Full ISUPPORT command; 005 before registration
whox Full WHO with %fields; 354 RPL_WHOSPCRPL
bot Full Umode +B; RPL_WHOISBOT (335) in WHOIS
message-redaction Full REDACT command; soft-delete in DB; CHATHISTORY replays REDACT events for client sync
draft/message-edit Full PRIVMSG with +draft/edit=<msgid> tag; DB-backed ownership check; edit history replayed in CHATHISTORY
draft/react Full TAGMSG with +draft/react=<emoji>; forwarded via client-only tag relay
draft/unreact Full TAGMSG with +draft/unreact=<emoji>; forwarded via client-only tag relay
typing Full TAGMSG with +typing=active/paused/done; forwarded via client-only tag relay
reply Full Messages with +reply=<msgid> tag forwarded as-is
account-extban Full MODE +b ~a:account; JOIN 474 when banned by account
sasl Full AUTHENTICATE PLAIN, SCRAM-SHA-256, and EXTERNAL (TLS client cert); 903/904; certfp auto-associated on PLAIN/SCRAM login
monitor Full MONITOR +/−/C/L/S; 730/731/732/733/734; on join/quit/nick
extended-monitor Full MONITOR patterns with nick!user@host globs (*/? wildcards)
sts Full Strict Transport Security; advertised in CAP LS only when TLS is configured; duration=2592000
draft/channel-rename Full RENAME old new [reason]; op-only; fallback PART+JOIN for clients without cap
draft/chathistory Full CHATHISTORY LATEST/BEFORE/AFTER/AROUND/BETWEEN/TARGETS; BATCH chathistory; DB-backed; limit 200
draft/event-playback Full JOIN/PART/QUIT/TOPIC/NICK events stored in DB and replayed in CHATHISTORY
draft/network-icon Full Optional ICON= ISUPPORT token; config network.icon
draft/read-marker Full MARKREAD target [timestamp]; per-account, persisted in MariaDB
draft/metadata-2 Full METADATA GET/LIST/SET/CLEAR; key-value per user/channel, persisted in MariaDB
STATUSMSG Full PRIVMSG/NOTICE to @#channel (ops+) or +#channel (voiced+); advertised in 005 STATUSMSG=@+
draft/account-registration Full REGISTER * [email] password; VERIFY returns INVALID_CODE (no email verification)
draft/multiline Full BATCH draft/multiline; max-bytes=4096, max-lines=20; fallback for non-multiline clients
draft/pre-away Full AWAY during registration; applied after NICK/USER complete
draft/channel-context Full +draft/channel-context tag forwarded to channel members
draft/client-batch Full Client-originated BATCH types collected and relayed to recipients
CLIENTTAGDENY Full Optional 005 token; config server.client_tag_deny
WebIRC Full WEBIRC password gateway hostname ip; config [webirc]
WebSocket Full IRCv3 WebSocket transport; listen_ws/listen_wss config; subprotocol text.ircv3.net
draft/filehost Full HTTPS file upload endpoint with HTTP Basic auth (same credentials as SASL PLAIN); reuses [tls] certs; FILEHOST= / draft/FILEHOST= ISUPPORT tokens; MIME-typed downloads; configurable max upload size

Roadmap

Features under consideration for future releases:

Feature Description
draft/webpush Web Push notifications (RFC 8291) via WEBPUSH REGISTER/UNREGISTER
draft/account-registration VERIFY Email-based account verification (currently returns INVALID_CODE)

Standard IRC Commands

In addition to IRCv3 features, rIRCd implements the standard IRC command set:

Command Numerics Description
LIST 321/322/323 List channels; supports >N/<N (user count filter) and glob name masks
LUSERS 251/252/254/255/265/266 Server user/channel statistics
VERSION 351 Server version string
TIME 391 Server local time
INFO 371/374 Server info and uptime
LINKS 364/365 Linked servers (single-server: lists self)
STATS u 242/219 Server uptime
STATS o 243/219 IRC operator list
WHOWAS 314/312/369 Historical nick info; up to 5 entries per nick, in-memory
WHO mask 352/315 Supports glob masks (*, ?) against nick!user@host; respects +i invisible mode
HELP 704/705/706 Per-command help text
KNOCK 710/711 Request invite to an invite-only channel; notifies ops
KILL Oper-only: forcibly disconnect a user; broadcasts QUIT to their channels
WALLOPS Oper-only: broadcast a message to all users with +w
MOTD 375/372/376 Send the message of the day
ISON 303 Check which nicks in a list are currently online
USERHOST 302 Return nick=+user@host info for up to 5 nicks

User Modes

Mode Set by Description
+B User Bot mode — shown in WHOIS as a bot (RPL_WHOISBOT 335)
+i User Invisible — hidden from WHO unless sharing a channel
+o Server IRC operator — set by successful OPER command
+r Server Registered — set automatically on SASL login
+w User Receives WALLOPS broadcasts from opers

Channel Modes

Mode Description
+o Channel operator
+v Voice (+)
+h Half-op (%)
+b Ban list (supports ~a:account extban and glob masks)
+e Ban exception list — exempt users bypass +b bans
+I Invite exception list — matching users bypass +i without explicit INVITE
+q Quiet list — silences matching users without kicking
+i Invite-only
+m Moderated — only +v/+h/+o may speak
+n No external messages
+s Secret channel
+t Topic restricted to ops
+k Channel key (password)
+l User limit
+R Registered users only — unregistered users cannot join or speak
+c Strip mIRC colour and formatting codes from messages
+C Block CTCP messages (including /me actions)

License

See LICENSE.

About

A Rust-based IRC server with bleeding edge capabilities.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages