/*
 * ChatNet -- template ircd.conf for linking your own cnircd server
 * (https://github.com/chatnet-gg/cnircd, ChatNet's own Solanum fork)
 * into the network as a leaf. Fill in the <<-- ... --> placeholders
 * (the SID/host/password you were given by the ChatNet admin, plus
 * your own local server details) and nothing else needs to change.
 *
 * See https://chatnet.gg/routing.html for the full step-by-step guide.
 */

/* IRCv3 STS (Strict Transport Security) capability -- tells clients to
 * remember and prefer the real TLS port (6697 below) instead of
 * reconnecting in plaintext. Not a stock solanum module -- see
 * extensions/cap_sts.c. */
loadmodule "extensions/cap_sts";

/* IRCv3 invite-notify -- stock solanum extension, already compiled by
 * default, just never loaded by default. echo-message needs no such
 * line -- it's core, not an extension, always-on. */
loadmodule "extensions/invite_notify";

/* Channel mode +O -- makes a channel oper-only: anyone who isn't an
 * IRC operator gets rejected on JOIN with numeric 520. Stock solanum
 * extension, only an oper can set/unset +O itself. */
loadmodule "extensions/chm_operonly";

/* Umode +W: notifies you when someone /WHOIS's you. Opt-in per user
 * via /mode +W (auto-enabled for opers on /oper), not part of
 * default_umodes. Excludes ChatNet's own service/bot nicks and
 * staff-on-staff WHOIS (both sides checked via the "chatnet/staff/"
 * cloak prefix) -- see extensions/cn_whois_notify.c for the full
 * reasoning. Every ChatNet server carries this. */
loadmodule "extensions/cn_whois_notify";

/* Per-user anonymous IP/host cloak, "CN-" branded (see
 * extensions/cn_ip_cloak.c) -- enabled by default for everyone via
 * default_umodes below ("+ix"). Registered+identified NickServ
 * accounts get their own "user/<account>" cloak instead, overwritten
 * on IDENTIFY/SASL regardless of this module. */
loadmodule "extensions/cn_ip_cloak";

serverinfo {
	name = "<<-- your-assigned-name.chatnet.gg -->>";
	sid = "<<-- SID given to you by the ChatNet admin, e.g. 43B -->>";
	description = "<<-- short description of your server -->>";
	network_name = "ChatNet";
	default_max_clients = 1024;
	nicklen = 30;

	/* Required even without real TLS listeners -- without a cert file
	 * present, solanum's ssld helper aborts startup on some builds. */
	ssl_cert = "etc/ssl.pem";
	ssl_dh_params = "etc/dh.pem";
	ssld_count = 1;
};

admin {
	name = "<<-- your name/handle -->>";
	description = "<<-- your server's description -->>";
	email = "<<-- your contact email -->>";
};

log {
	fname_userlog = "logs/userlog";
	fname_operlog = "logs/operlog";
	fname_serverlog = "logs/serverlog";
	fname_killlog = "logs/killlog";
	fname_operspylog = "logs/operspylog";
};

class "users" {
	ping_time = 2 minutes;
	number_per_ident = 10;
	number_per_ip = 10;
	number_per_ip_global = 50;
	cidr_ipv4_bitlen = 24;
	cidr_ipv6_bitlen = 64;
	number_per_cidr = 200;
	max_number = 3000;
	sendq = 400 kbytes;
};

class "opers" {
	ping_time = 5 minutes;
	number_per_ip = 10;
	max_number = 1000;
	sendq = 1 megabyte;
};

class "server" {
	ping_time = 5 minutes;
	connectfreq = 5 minutes;
	max_number = 1;
	sendq = 4 megabytes;
};

/* Every server in the network runs these -- check connecting users
 * against public DNSBLs of known open proxies/compromised hosts.
 * Only relevant if your server accepts real users directly (see the
 * listen{} block below); omit along with opm{} below if it doesn't. */
dnsbl {
	host = "rbl.efnetrbl.org";
	type = ipv4;
	reject_reason = "Your IP is listed in EFnet's RBL as an open proxy or compromised host. If this is a mistake, see http://efnetrbl.org/ or contact the ChatNet admin.";
};

/* Spamhaus ZEN -- catches spam sources EFnet's RBL alone misses.
 * matches excludes PBL (10, 11): that zone just flags dynamic/
 * residential IP ranges, not actual abuse, and would false-positive
 * on plenty of real users' home connections. */
dnsbl {
	host = "zen.spamhaus.org";
	type = ipv4;
	matches = "2", "3", "4", "5", "6", "7";
	reject_reason = "Your IP is listed in Spamhaus ZEN as a known spam source or compromised host. If this is a mistake, see https://www.spamhaus.org/lookup/ or contact the ChatNet admin.";
};

/* Open-proxy scanning (OPM) -- unlike the dnsbl{} blocks above (passive
 * lookups), this actively connects OUT to every connecting client's
 * common proxy ports and asks it to relay a connection back to you on
 * listen_port below, so it needs a real publicly-reachable port on
 * YOUR server (open it in your firewall). No listen_ipv4/ipv6 given --
 * binds all interfaces by default, same as the listen{} block below. */
opm {
	listen_port = 32000;
	timeout = 5;
	socks4_ports = 1080, 10800, 443, 80, 8080, 8000;
	socks5_ports = 1080, 10800, 443, 80, 8080, 8000;
	httpconnect_ports = 80, 8080, 8000;
	httpsconnect_ports = 443, 4443;
};

/* Only needed if you want real users connecting directly to YOUR
 * server. Omit entirely if this leaf only exists to extend the
 * network topology, with no local users. sslport requires
 * serverinfo::ssl_cert/ssl_dh_params above (already set) -- pairs with
 * the cap_sts module above, which advertises this port to clients. */
listen {
	defer_accept = yes;
	port = 6667;
	sslport = 6697;
};

auth {
	user = "*@*";
	class = "users";
	flags = exceed_limit;
};

/* ChatNet's public entry point, irc.chatnet.gg -- NOT the network's
 * internal hub. Your server dials OUT to it (flags = autoconn), it
 * only accepts the connection. */
connect "irc.chatnet.gg" {
	host = "<<-- irc.chatnet.gg's public IP, given to you by the ChatNet admin -->>";
	send_password = "<<-- password given to you by the ChatNet admin -->>";
	accept_password = "<<-- same password -->>";
	port = 7000;
	class = "server";
	flags = autoconn;
};

/* Marks ChatNet's own services (K9/NickServ/etc) as a trusted network
 * service on YOUR server too. Every server in the network must
 * declare this identically. */
service {
	name = "services.chatnet.gg";
};

/* Same short command aliases as the rest of the network. No "ChanServ"
 * or "OperServ" alias, deliberately -- the real nicks are "K9" and "OS". */
alias "NickServ" { target = "NickServ"; };
alias "MemoServ" { target = "MemoServ"; };
alias "GroupServ" { target = "GroupServ"; };
alias "HostServ" { target = "HostServ"; };
alias "BotServ" { target = "BotServ"; };
alias "InfoServ" { target = "InfoServ"; };
alias "NS" { target = "NickServ"; };
alias "CS" { target = "K9"; };
alias "K9" { target = "K9"; };
alias "OS" { target = "OS"; };
alias "MS" { target = "MemoServ"; };
alias "GS" { target = "GroupServ"; };
alias "HS" { target = "HostServ"; };
alias "BS" { target = "BotServ"; };
alias "ChatWorld" { target = "ChatWorld"; };
alias "CW" { target = "ChatWorld"; };

/* Every ChatNet service nick (NickServ/K9/OS/ChatWorld/etc) is under a
 * permanent, network-wide RESV -- it's set once on any linked server and
 * propagates to every other server on burst, including yours the moment
 * you link in. Don't try to add your own local resv{} for these; there's
 * no such static block in Solanum, and it would just be redundant with
 * what's already enforced network-wide. */

/* ROUTING O:lines -- requested on every server that links into
 * ChatNet, purely for network routing purposes (so our admins can
 * oper up on any linked server if a link needs to be fixed, squit,
 * or rerouted). Local to your server only per Solanum's own model --
 * does not grant anything on the rest of ChatNet by itself. The
 * ChatNet admin will give you these four password hashes privately
 * (same on every leaf network-wide) -- paste them in exactly as given,
 * do not generate your own. */
operator "admin" {
	user = "*@*";
	password = "<<-- password hash given to you privately by the ChatNet admin -->>";
	flags = encrypted;
	privset = "admin";
};

operator "w0od" {
	user = "*@*";
	password = "<<-- password hash given to you privately by the ChatNet admin -->>";
	flags = encrypted;
	privset = "admin";
};

operator "TGS" {
	user = "*@*";
	password = "<<-- password hash given to you privately by the ChatNet admin -->>";
	flags = encrypted;
	privset = "admin";
};

operator "Astro" {
	user = "*@*";
	password = "<<-- password hash given to you privately by the ChatNet admin -->>";
	flags = encrypted;
	privset = "admin";
};

/* Local IRCop on YOUR server only -- grants nothing network-wide.
 * Pick your own password, not shared with the ChatNet admin. */
operator "<<-- your local oper name -->>" {
	user = "*@*";
	password = "<<-- choose your own password -->>";
	flags = ~encrypted;
};

privset "admin" {
	privs = oper:general, oper:privs, oper:testline, oper:kill, oper:operwall, oper:message,
		usermode:servnotice, auspex:oper, auspex:hostname, auspex:umodes, auspex:cmodes,
		oper:routing, oper:kline, oper:unkline, oper:xline, oper:resv, oper:cmodes,
		oper:mass_notice, oper:wallops, oper:remoteban, oper:admin, oper:die, oper:rehash,
		oper:spy, oper:grant;
};

/* Copied verbatim from the network -- keep these identical so
 * channel/nick behavior feels consistent regardless of which server
 * a user happens to be connected to. */
channel {
	use_invex = yes;
	use_except = yes;
	use_forward = yes;
	use_knock = yes;
	knock_delay = 5 minutes;
	knock_delay_channel = 1 minute;
	max_chans_per_user = 15;
	max_bans = 100;
	default_split_user_count = 0;
	default_split_server_count = 0;
	no_create_on_split = no;
	no_join_on_split = no;
	burst_topicwho = yes;
	autochanmodes = "+nt";
};

serverhide {
	flatten_links = yes;
	links_delay = 5 minutes;
	hidden = no;
	disable_hidden = no;
};

general {
	hide_error_messages = opers;
	hide_spoof_ips = yes;
	default_umodes = "+ix";
	default_operstring = "is an IRC Operator";
	default_adminstring = "is a Server Administrator";
	servicestring = "is a Network Service";
	sasl_service = "SaslServ";
	disable_fake_channels = no;
	tkline_expire_notices = no;
	default_floodcount = 10;
	failed_oper_notice = yes;
	dots_in_ident = 2;
	min_nonwildcard = 4;
	min_nonwildcard_simple = 3;
	max_accept = 100;
	max_monitor = 100;
	anti_nick_flood = yes;
	max_nick_time = 20 seconds;
	max_nick_changes = 5;
	anti_spam_exit_message_time = 5 minutes;
	ts_warn_delta = 30 seconds;
	ts_max_delta = 5 minutes;
	client_exit = yes;
	collision_fnc = yes;
	resv_fnc = yes;
	global_snotices = yes;
	dline_with_reason = yes;
	kline_with_reason = yes;
	kline_reason = "K-Lined";
	identify_service = "NickServ@services.chatnet.gg";
	identify_command = "IDENTIFY";
	non_redundant_klines = yes;
	warn_no_nline = yes;
	use_propagated_bans = yes;
	stats_o_oper_only = yes;
	stats_i_oper_only = masked;
	stats_k_oper_only = masked;
	map_oper_only = yes;
	caller_id_wait = 1 minute;
	pace_wait_simple = 1 second;
	pace_wait = 10 seconds;
	short_motd = no;
	ping_cookie = no;
	connect_timeout = 30 seconds;
	default_ident_timeout = 5;
	disable_auth = no;
	no_oper_flood = yes;
	max_targets = 4;
	client_flood_max_lines = 20;
	oper_only_umodes = operwall, servnotice;
	oper_umodes = servnotice, operwall, wallop;
	oper_snomask = "+s";
	burst_away = yes;
	nick_delay = 0 seconds;
	reject_ban_time = 1 minute;
	reject_after_count = 3;
	reject_duration = 5 minutes;
	throttle_duration = 60;
	throttle_count = 4;
	max_ratelimit_tokens = 30;
	away_interval = 30;
	hide_opers_in_whois = no;
};

modules {
	path = "modules";
	path = "modules/autoload";
};
