UnrealIRCD Configuration

This contains all information on the UnrealIRCd configuration file (unrealircd.conf and other *.conf files). Be sure to read the #Configuration file syntax. Other than that, it is mostly meant for reference as reading everything would be too long to read.


Configuration file syntax

Other languages:

UnrealIRCd configuration files use a block-based format. Each entry or block has a specific format. The format works like:

<block-name> <block-value> {
	<block-directive> <directive-value>;

<block-name> is the type of block, such as me for the Me block, or admin for the Admin block.

<block-value> may not always be present, but if it is then it may have two meanings: 1) sometimes it specifies a value, such as bobsmith in oper bobsmith {, 2) other times it defines a sub-type, like with deny dcc {.

<block-directive> is an individual variable specific to the block. <directive-value> is the associated value (if any). If <directive-value> contains spaces or characters that represents a comment it must be contained in double quotes like somevar "some value with spaces in it";. (By the way, if you want to use a quote character inside a quoted string then use \" and it will be understood as a quote character).

Finally, a <block-directive> may also have directives in it, and so on and so on.

Note: the configuration file is currently case sensitive so BLOCK-NAME is not the same as block-name.

IMPORTANT: You must terminate each line with a ; and terminate each block with a };. Only the start of the block (eg: me {) has no terminating ; character. If you forget a } or ; somewhere then UnrealIRCd will fail to read your configuration file correctly and will not boot!

Examples (correct):

me {
        name "";
        sid 001;
        info "Some nice server";
log ircd.log {
        flags {
set {
        maxchannelsperuser 10;

        options {
        hosts {
                admin "";
                netadmin "";

Important: there is a special notation used to talk about entries in the config file and we use it throughout the UnrealIRCd documentation. Take the first example from above (the me block), the name is set to, we call this variable set::name. Similarly, in the last example we would refer to the netadmin directive as set::hosts::netadmin, and we call that block the set::hosts block.

You can also put comments in the configuration file. Comments are text that isn't interpreted by UnrealIRCd and it's entirely up to you if you use it and what you write. UnrealIRCd supports 3 types of comments:

# This is a single line comment (type 1)
// This is also a single line comment (type 2)
/* This is a
   multi line
   comment */

Now that you know how the configuration file works in principle, copy conf/examples/example.conf to conf/ and rename it to unrealircd.conf. Walk through it block per block, line by line. If you want to know more about a specific section then see the top of the Configuration article for all the available blocks and directives.

Sharing settings between servers

Other languages:

When you run multiple IRC servers (in the same IRC network) then it makes sense to put these "shared settings" in a separate configuration file(s) and only put server-specific settings directly in the unrealircd.conf directly.

For example, you could put all the shared settings in a file called network.conf, copy it to all your servers and include it from your unrealircd.conf. Or maybe you want to split them up like link.conf, class.conf, settings.conf, etc.

Even better: use Remote includes so your servers fetch a copy of it by HTTP(S) upon start and /REHASH.. then you only have to update one file, rehash your servers, and the settings are active network-wide.

Many settings can be shared among servers. Only the Me block and possibly the Listen block and some other settings are unique for each server.

Me block

The me block defines the identity of the server.


me {
	name <name-of-server>;
	info "<server-description>";
	sid <server-id>;

The item name specifies the name of the server, info specifies the server's info line, sid is an unique server id which is a digit followed by two digits/letters. This is an unique server value meaning NO other servers on the network may have the same sid.


me {
	name "";
	info "FooNet Server";
	sid 001;

Admin block

The admin block defines the text displayed in a /admin request. You can specify as many lines as you want and they can contain whatever information you choose, but it is standard to include the admins nickname and email address at a minimum. Other information may include any other contact information you wish to give.


admin {


admin {
	"Bob Smith";
	"[email protected]";

Class block

Class blocks are classes in which connections will be placed, for example clients from allow blocks and servers from link blocks. You generally have multiple class blocks: one for servers, one for regular clients and one for IRCOps (the latter is optional).


class <name> {
	pingfreq <ping-frequency>;
	connfreq <connect-frequency>;
	maxclients <maximum-clients>;
	sendq <send-queue>;
	recvq <recv-queue>;
	//options { nofakelag; };

name is the descriptive name, like "clients" or "servers", this name is used for referring to this class from allow/link/oper/etc blocks

pingfreq is the number of seconds between PINGs from the server (something between 90 and 180 is recommended).

connfreq is used only for servers and is the number of seconds between connection attempts if autoconnect is enabled

maxclients specifies the maximum (total) number of clients/servers which can be in this class

sendq specifies the amount of data which can be in the send queue (very high for servers with low bandwidth, medium for clients)

recvq specifies the amount of data which can be in the receive queue and is used for flood control (this only applies to normal users, try experimenting with values 3000-8000, 8000 is the default).

options::nofakelag allows this particular class to bypass the fake lag protection. Requires you to modify a core source file and recompile first, though.


class clients {
	pingfreq 90;
	maxclients 500;
	sendq 100000;
	recvq 8000;
class servers {
	pingfreq 90;
	maxclients 10; /* Max servers we can have linked at a time */
	sendq 1000000;
	connfreq 30; /* How many seconds between each connection attempt */

Allow block

Allow blocks specify who may connect to this server. You can have multiple allow blocks.


allow {
        /* NOTE THAT YOU MUST SPECIFY EITHER 'ip' OR 'hostname', BUT NOT BOTH */
        ip <[email protected]>;
        hostname <[email protected]>;

        /* Other mandatory options: */
        class <connection-class>;
        maxperip <max-connections-per-ip>;

        /* All the rest is optional: */
        password <connection-password> { <auth-type>; }; /* OPTIONAL */
        ipv6-clone-mask <number-of-bits>; /* OPTIONAL */
        redirect-server <server-to-forward-to>; /* OPTIONAL */
        redirect-port <port-to-forward-to>; /* OPTIONAL */
        options {

Do you have multiple allow blocks? Then note that they will be read upside down, so you need specific host/ip allow blocks AFTER your general *@* allow blocks.

If a client does not match any allow block then the client is rejected with the message from set::reject-message.

required items

ip & hostname

You need to specify either ip or hostname which will be matched against the IP or hostname (DNS) of the user who is connecting. For example ip *; will match everyone and hostname *.uk; will match only people with a host ending in ".uk".

IMPORTANT: If you simply want to match any user, then use ip *;. You should not use hostname *; as this will match only users with a hostname, and not everyone may have a hostname (unresolvable IP).


Specifies the class name that connections using this allow block will be placed into.


With maxperip you specify how many connections may come from each IP. For example maxperip 4; means that only 4 clients may connect per-IP to this server.

optional items


If you set a password then everyone who connects to your server will need to use this password to connect (the ones matching allow::ip / allow::hostname anyway). This can be used if you have some sort of private server.


This option controls clone detection and is basically IPv6's variant of maxperip. If you don't have IPv6 enabled then this option has no effect. If two clients connect from different IPv6 addresses but only the last few bits are different, there is almost a guarantee that both clients are really one person. This option only affects the enforcement of allow::maxperip. For example, if you set this option to 128, then each IPv6 address will be considered unique. Because of current IP allocation policies, it is recommended that your most general allow block use a value of 64. Since 64 is already the default in set::default-ipv6-clone-mask you probably don't need to change this.

redirect-server & redirect-port

When the class is full (class::maxclients) we will redirect new users to this server. This requires support from the IRC client side, popular clients like mIRC support this.

redirect-server specifies the server name and redirect-port the port (6667 by default).


One option gives you additional flexibility for matching:

  • ssl: Only match if this client is connected via SSL.

Meaning, if this doesn't match, UnrealIRCd jumps to next allow block.

There are also two other options that don't have anything to do with matching but will affect the user/host:

  • useip: Always display IP instead of hostname.
  • noident: Don't use ident but use username specified by client.

And, finally, there's one special option that is rarely used:

  • nopasscont: Continue matching if no password was given. This so you can use allow::password for a special allow block with a different class and higher maxperip. Together with allow::options::nopasscont you can then have clients without password jump to next allow block (which may be a generic one without password). Such a setup is not recommended because clients may connect with their services password. Such a setup will then refuse such clients because of a password mismatch.

NOTE: The option allow::options::sasl has been removed. If you want to force SASL for users on a specific IP range or host, use a Require sasl block instead.


Example 1: generic block and specific block

allow {
	ip *;
	class clients;
	maxperip 3;

allow {
	ip *@1.2.3.*;
	class clients;
	password "f00Ness";
	maxperip 25;

Listen block

The listen block defines the TCP/IP ports that the IRCd will listen on.


listen {
        ip <ip>;
        port <port>;
	options {
	ssl-options {


Simply set ip to * (an asterisk) to bind to all available IP's on the machine, OR specify an IP to only bind to that IP address (this latter is usually required at shell providers).


This is the port you want to listen on, like 6667. You can also specify a port range, like 6667-6669.

options block (optional)

You can specify options for the port. Valid options are:

  • ssl: TLS/SSL encrypted port
  • clientsonly: port is only for clients
  • serversonly: port is only for servers
  • websocket: in UnrealIRCd 5 you open up a port for WebSocket support via this. You also need to specify a type, like: options { websocket { type text; } }

ssl-options block (optional)

Valid options are all the SSL/TLS settings that also exist in set::ssl. For example you may want to use an Lets Encrypt certificate/key on all normal client ports (via set::ssl::certificate). But for this port you want to use another SSL certificate/key:

listen {
        ssl-options {
                certificate "ssl/server.cert.pem";
                key "ssl/server.key.pem";


listen {
        ip *;
        port 6667;
listen {
        ip *;
        port 6697;
	options {

Oper block

In oper blocks you define all the IRC Operators accounts. Once defined you use the /OPER command on IRC to become IRCOp.


oper <name> {
        /* Required items: */
        mask <hostmask>;
        password <password>;
        class <class-name>;
        operclass <operclass-name>;
        /* Optional items to further limit who can /OPER */
        require-modes <modes>
        maxlogins <num>;
        /* Optional items to define what will be set upon successful /OPER */
        vhost <new virtual hostname>;
        swhois <whois info>;
        modes <modes>;
        snomask <snomask>;

Required items


The name in the oper name { block defines which name to use in the OPER command on IRC (/OPER name password). This name is case sensitive!

Most people use their nick name here. You can use latin characters (A-Z a-z), numbers and _-[]. Do not use special characters like ö (as in Björn) or Arabic/Greek/etc. Such characters may cause you problems with /OPER'ing due to character set differences.


The password item defines the password to use. Passwords are case sensitive. Instead of using a plaintext password here, we highly recommend you to use Hashed passwords or SSL certificate fingerprints, see Authentication types.


The mask defines from which host/IP this oper block may be used, this can be used for increased security. Set this to mask *; if you want to permit any IP. You may also use multiple masks, in which case the syntax becomes like: mask { 1.2.3.*; 55.66.*; 11.22.*; *; };


After a successful /OPER attempt the user will be put in the class you specify here. This can be the same as any other clients (eg: class clients;) or some special class you created for IRCOps (eg: class ircops;)


This defines which Operclass block to use. The operclass block configures which privileges this IRCOp will have (which IRCOp commands you may use, etc..).

Optional items


This lets one specify modes (such as 'z') that a user must have acquired before being allowed to OPER. This can be used, for example, to require opers to be on secure connections (user mode +z) before being able to become operators.


This allows you to restrict the number of concurrent oper logins from this host, for example if you set it to 1 then only 1 person can be oper'ed via this block at any time.


This hostname (virtual host) will be set after you successfully oper up.


Allows you to add one or more extra lines to the /WHOIS information for this oper. For example:

swhois "a Network Administrator";


Set these user modes after successful oper up.


By default an IRCOp gets the Snomasks from set::snomask-on-oper. You can use this oper::snomask to specify a different set of snomasks. See Snomasks for a full list.


oper bobsmith {
	class clients;
	mask {; *; };
	password "f00";
        operclass netadmin;
	swhois "a Network Administrator";
	snomask cFfkoSsqNG;

Some little information about OperOverride

OperOverride are things like: joining a +ikl channel and going through bans, op'ing yourself in a channel, etc. See the OperOverride article for all information on this.

Operclass block

The operclass block is used to define ircop permissions. It is referred to from oper::operclass in the Oper block.

The operclass block allows you to define permissions in a very fine-grained manner. If you just want to use some good defaults, then see the default oper classses at the end of this article.

Syntax & Examples

operclass name {
        parent xyz; /* OPTIONAL: can be used to inherit permissions from another operclass block */
        permissions {
                .....permissions to grant to this oper class......

Each operclass has a name. You define the privileges in operclass::permissions. Optionally you can use operclass::parent to have this operclass inherit all permissions from another operclass.

How permissions work

By default the oper using an operclass does not have special powers (this is not entirely true, actually). You must grant each privilege via operclass::permissions.

For example to grant the right to /KILL users:

operclass name {
        permissions {

This would be the same as:

operclass name {
        permissions {
                kill {

Many permissions allow you to define even more options, which go in a sub-block, like:

operclass name {
        permissions {
                kill {
                        allow { local yes; }; /* only allow KILL on local users, not remote */

You can also have multiple allow blocks. The following would permit SPAMFILTER, but only in a limited matter:

operclass name {
        permissions {
                spamfilter {
                        /* May delete ANY spamfilter */
                        allow {
                                what del;
                        /* May add spamfilter with action 'block' */
                        allow {
                                action block;
                        /* (all the rest is denied) */


See the Operclass permissions article for an overview and the full list of 100+ permissions that are available.

Default oper classes

UnrealIRCd ships with a number of operclass blocks, these are in the file operclass.default.conf. You can use these for inspiration or just use them directly from your Oper block.

The default operclass blocks consist of:

  • locop: this has the least amount of privileges. The powers of this IRCOp type are (mostly) limited to the local server, for example it can /KILL and /KLINE local users but not remote users. This IRCOp does not have any special privileges in channels nor can it "see" much additional information of users. For example, they can see the IP of users (so they can /KLINE properly) but they cannot see if a user is in a secret channel (+s).
  • globop: Global IRC Operator. Has a good set of privileges. Can for example /KILL and /GLINE users on all servers. Can "see" extra things (override::see) such as secret channels in /LIST and /WHOIS.
  • admin: Server administrator. Similar to globop but includes the ability to use a few more potentially dangerous but powerful commands such as /SPAMFILTER.
  • services-admin: This level adds the ability to use /SAJOIN, /SAPART and /SAMODE.
  • netadmin: This is the highest level. Compared to services-admin it also includes the ability to deop or kill services bots and some other unusual things.

In addition to the above we also have globop-with-override, admin-with-override, services-admin-with-override and netadmin-with-override: these operclasses are the same as above but add the ability to use OperOverride. In other words: to walk through bans, changes modes without being op'ed, and so on. See OperOverride for more information.

Customizing oper classes

If you want to tweak an operclass, change a few permissions, then you can do so in two ways:

  • By copy-pasting the block(s) from operclass.default.conf
  • By creating a new operclass and using 'inheritance'. You set operclass::parent to an operclass to use as a base and then extend the operclass by adding / removing permissions.

We highly suggest you read below about both methods and only after that decide which one to use.


NOTE: You should never edit operclass.default.conf directly as it will be overwritten upon each upgrade! (hence the name operclass.default.conf)

This method is easy:

  • Copy the relevant block(s) to your own configuration file
  • Give the operclass block(s) a different name
  • Edit the block to add/remove permissions

The downside of this method is that when we add new permissions in later UnrealIRCd versions then your (custom) IRCOp classes won't have these rights by default. You would have to edit your operclass and add the new permissions manually (or not). This can happen when we move existing permissions that are currently granted to all IRCOps to a new privilege flag, or when we split existing permissions into 2 separate permissions. Since the operclass system is relatively new this is likely to happen (almost) every UnrealIRCd release. Of course, if you understand this downside and find it acceptable, then it's perfectly fine if you use this method.

Using inheritance

Inheritance works better than copy-paste (for small changes, anyway) and requires less maintenance on your side. This is because when we add new rights in UnrealIRCd in later versions we will add them to the default blocks and your customized block would automatically inherit them.

Inheritance should work well in the majority of the cases. However if you have a lot of changes then it may be better to just go for the copy-pasting method explained earlier.

Example 1: limit rights

Say you like the locop operclass but want a few things changed:

  • You want the ircop to be able to 'see' extra things such as secret channels.
  • The locop class allows /ZLINE and /KLINE, but you want to only allow /KLINE.
operclass special {
       parent locop; /* we inherit the settings from 'locop' and then tweak them below.. */
       permissions {
                /* we add a 'tkl' block with only 'kline', this means: only allow kline (and not zline too) */
                tkl {

                override { see; }; /* add the override::see capability */

                /* all the other permissions are inherited from the 'locop' operclass */

Example 2: super-netadmin

In this example we will extend the netadmin IRCOp to also restart the server (via the /RESTART command).

The restart privilege is called server::restart. So we need to override the server privilege. First, you should have a look at which server permissions are there in the netadmin class. You should check out operclass.default.conf, but at the time of writing this article it is:

server { opermotd; info; close; remote; module; dns; addline; rehash; description; addmotd; addomotd; tsctl; };

So we will need to add restart; to that.

This is the complete block you will use:

operclass super-netadmin {
       parent netadmin; /* we inherit the settings from 'netadmin' and then tweak them below.. */
       permissions {
                /* we are going to change the 'server' block. We need to copy the rights from
                 * the 'netadmin' operclass and add 'restart' to it:
                server {
                        opermotd; info; close; remote; module; dns; addline; rehash; description; addmotd; addomotd; tsctl; restart;
                /* all the other permissions are inherited from the 'netadmin' operclass */

DRpass block

IRCOp's who have restart/die rights can restart the IRC Server through /RESTART and kill the server with the /DIE command.

This block allows you to set a password for these commands so IRCOp's need to use /DIE password and /RESTART password.


drpass {
	restart <restart-password>;
	die <die-password>;


drpass {
	restart "I-love-to-restart";
	die "die-you-stupid";

Include directive

The include directive allows you to include other configuration files. This way you can split up your configuration instead of having one large unrealircd.conf.


include "<file-name-or-URL>";

Commonly included files

UnrealIRCd ships with a number of configuration files out-of-the-box that you can choose to include:

  • modules.full.conf: these contain all the modules, you almost always want to load this file
  • badwords.conf: needed to make channel mode +G and user mode +G work ("bad words filter")
  • spamfilter.conf: spamfilter (example) configuration
  • aliases/anope.conf: recommended if you use anope services, provides a number of commands including: /NS, /NICKSERV, /CS, /CHANSERV, etc.
  • aliases/atheme.conf: similar file if you use atheme services


include "modules.default.conf"; /* Load all modules */
include "operclass.default.conf"; /* Default operclass blocks */
include "spamfilter.conf"; /* Spamfilter configuration */
include "badwords.conf";
include "help.conf";
/* CUSTOM example */
include "opers.conf"; /* Oper blocks are all in this file*/
include "links.conf"; /* All link blocks */

If you have enabled "Remote includes" (this is the default on Windows) then you can also use URL's:

include ""; /* HTTP example */
include "https://user:[email protected]/network/opers.conf"; /* HTTPS example WITH username/password (HTTP Basic Auth) */

If you use remote includes then we recommend to use HTTPS and not HTTP, as with HTTP your included configuration file go over the wire in plaintext and may be read by 3rd parties.

Loadmodule directive

With loadmodule you tell UnrealIRCd to load a particular module. See Modules for more information.

Normally you put include "modules.default.conf"; in your unrealircd.conf and only use loadmodule directly for loading 3rd party modules (if any).


loadmodule <file-name-without-suffix>;

UnrealIRCd automatically adds the correct suffix (.DLL or .so) and will also automatically deal with modules/ vs src/modules/ directories.


/* Just load all of UnrealIRCd's functionality (all 150+ modules) */
include "modules.default.conf";
/* If you want to load modules\m_something.dll */
loadmodule "m_something";
/* If you want to load modules/ */
loadmodule "whatever";

Note that for both examples UnrealIRCd will take care of any prefixing of the modules directory (modules/) and suffixing (.so or .dll).

/* If you want to load modules/third/ */
loadmodule "third/something";

Disabling modules

To disable certain functionality that is automatically loaded by modules.default.conf you could manually edit that file and comment the modules out (or delete the lines). However, these changes are overwritten on each upgrade!

A better option is to use the Blacklist-module directive which allows you to disable specific modules (any loadmodule lines for the module are ignored).

Blacklist-module directive

NOTE: Do not confuse this with the Blacklist block, which allows you to ban users based on DNSBL (DNS Blacklists)

With blacklist-module you can tell UnrealIRCd to never load a particular module. Any loadmodule lines for the module are ignored.

This can be used by advanced users to selectively disable modules that would otherwise be automatically loaded through conf/modules.default.conf. See under Example below for more information.


blacklist-module <file-name-without-suffix>;

UnrealIRCd automatically adds the correct suffix (.DLL or .so) and will also automatically deal with modules/ vs src/modules/ directories.


/* Just load all of UnrealIRCd's functionality (all 150+ modules) */
include "modules.default.conf";

/* Now selectively disable /ADMIN (m_admin) and usermode +B (usermodes/bot) */
blacklist-module "m_admin";
blacklist-module "usermodes/bot";

Note that disabling certain basic modules can have undesired effects. Carefully read the comments in conf/modules.default.conf. As an example, it would not be wise to disable m_quit.

See also

Log block

The log block allows you to configure log files. You may have multiple log blocks.

If you have no log block at all then UnrealIRCd will use a default log block that only logs errors to ircd.log.


log "<filename>" {
        flags {
        maxsize <max-file-size>; /* OPTIONAL */


The filename of your log "<filename>" { block specifies the name of the log file that will be used for logging.


The log::flags specifies which types of information will be in this log.

  • errors: self explanatory
  • kills: logs /kill notices
  • tkl: logs info on *lines (/kline, /zline, etc), shuns and spamfilters (adding/removing/expire)
  • connects: logs user connects/disconnects
  • server-connects: logs server connects/squits
  • oper: logs oper attempts (both failed and successful)
  • sadmin-commands: logs /sa* (samode, sajoin, sapart, etc.) usage
  • chg-commands: logs /chg* (chghost, chgname, chgident, etc.) usage
  • oper-override: logs operoverride usage
  • spamfilter: logs spamfilter matches

maxsize (Optional)

When the log file reaches a file size of maxsize the log file will be renamed to name-of-log-file.old (overwriting any previous such .old file). You can use K/M/G to specify kilobytes/megabytes/gigabytes.


log ircd.log {
        flags {
        maxsize 10M;

log users.log {
        flags {
        maxsize 10M;

TLD block

By default everyone gets to see the same MOTD (ircd.motd file), rules (ircd.rules file), opermotd, etc... With the tld block you can show different files to a user depending on their hostname or IP. This is for example useful if you want different motds for different languages.


tld {
	mask <hostmask>;
	motd <motd-file>;
	rules <rules-file>;
	shortmotd <shortmotd-file>;
	opermotd <opermotd-file>;
	botmotd <botmotd-file>;
	channel <channel-name>;
	options {

The tld::mask is a [email protected] mask that the user's username and hostname must match. The tld::motd, tld::shortmotd, tld::opermotd, tld::botmotd, and tld::rules specify the motd, shortmotd, opermotd, botmotd, and rules file, respectively, to be displayed to this hostmask. The tld::shortmotd, tld::opermotd, and tld::botmotd are optional. tld::channel is optional as well, it allows you to specify a channel that this user will be forced to join on connect. If this exists it will override the default auto join channel. The tld::options block allows you to define additional requirements, currently only tld::options::ssl which only displays the file for SSL users, and tld::options::remote which only displays the file for remote users, exists.

TLD entries are matched upside down


tld {
	mask *@*.fr;
	motd "";
	rules "";

Ban nick block

The ban nick block allows you to disable use of a nickname on the server.


ban nick {

	mask <nickname>;
	reason <reason-for-ban>;

The ban::mask allows wildcard masks to match multiple nicks, and ban::reason allows you to specify the reason for which this ban is placed. Most commonly these blocks are used to ban usage of the nicknames commonly used for network services.


ban nick {
	mask "*C*h*a*n*S*e*r*v*";
	reason "Reserved for Services";

Ban user block

This block allows you to ban a [email protected] mask from connecting to the server. This is the same as adding a /KLINE on IRC.


ban user {
	mask <hostmask>;
	reason <reason-for-ban>;

The ban::mask is a wildcard string of a [email protected] to ban, and ban::reason is the reason for a ban being placed. Note, this is only a local ban and therefore the user may connect to other servers on the network.


ban user {
	mask *[email protected]*;
	reason "Idiot";

Ban IP block

This block bans an IP from accessing the server. This is the same as adding a /ZLINE on IRC.


ban ip {
	mask <ipmask>;
	reason <reason-for-ban>;

The ban::mask parameter is an IP which may contain wildcard characters, and ban::reason is the reason why this ban is being placed.

Since this ban affects servers it should be used very carefully.


ban ip {
	mask 192.168.1.*;
	reason "Get a real ip u lamer!";

Ban server block

This block disables a server's ability to connect to the network. If the server links directly to your server, the link is denied. If the server links to a remote server, the local server will disconnect from the network.


ban server {
	mask <server-name>;
	reason <reason-for-ban>;

The ban::mask field specifies a wildcard mask to match against the server attempting to connect's name, and ban::reason specifies the reason for which this ban has been placed.


ban server {
	reason "Its broken!";

Ban realname block

The ban realname block allows you to ban a client based on the GECOS (realname) field. This is useful to stop clone floods because often clone bots use the same realname.


ban realname {
	mask <realname-mask>;
	reason <reason-for-ban>;

The ban::mask specifies the realname which should be banned. The mask may contain wildcards. The ban::reason specifies the reason why this ban is being placed.


ban realname {
	mask "Bob*";
	reason "Bob sucks!";

Ban version block

The ban version block allows you to ban a client based on the IRC client software they use. This makes use of the clients CTCP version reply. Therefore if a client does not send out a CTCP version, the ban will not work. This feature is intended to allow you to block malicious scripts.


ban version {
	mask <version-mask>;
	reason <reason-for-ban>;
	action [kill|tempshun|shun|kline|zline|gline|gzline];

The ban::mask specifies the version which should be banned. The mask may contain wildcards. The ban::reason specifies the reason why this ban is being placed. You can also specify ban::action, kill is the default, tempshun will shun the specific user connection only and would work very effective against zombies/bots at dynamic IPs because it won't affect innocent users. shun/kline/zline/gline/gzline will place a ban of that type on the ip (*@IPADDR), the duration of these bans can be configured with set::ban-version-tkl-time and defaults to 1 day.


ban version {
	mask "*SomeLameScript*";
	reason "SomeLameScript contains backdoors";
ban version {
	mask "*w00tZombie*";
	reason "I hate those hundreds of zombies";
	action zline;

Except ban block

The except ban block allows you to exempt users from KLINEs and other *LINES. This is useful when you want an ISP banned, but still want specific users to be able to connect. Also, IRCOps often add their own ip to except ban to make sure they are never accidentally banned.

There's a difference between how UnrealIRCd 4 and UnrealIRCd 5 process the except ban blocks so be sure to read the right section below!

UnrealIRCd 4

In UnrealIRCd 4 the except ban { } block only exempts from KLINE and ZLINE. You need to add an Except tkl block for the same [email protected] as well if you want to exempt from other ban types.


except ban {
	mask <hostmask>;

The except::mask directive specifies the [email protected] mask of the client who will be allowed to connect.


except ban {
	mask *;

UnrealIRCd 5

In UnrealIRCd 5 you can exempt hosts/IPs from nearly all possible bans in one block:


except ban {
	mask <host-or-ipmask>;
	type { .... }; /* this is optional */

The mask specifies the mask to be exempt from banning. It is recommended to use IP addresses in the mask if possible (eg: *@192.168.*) rather than hostnames (eg: *@*.someisp.xx). Although both are permitted, do note that if you use a hostname then the except ban { } will be ineffective against exempting from ZLINE and GZLINE for technical reasons (when bans and except ban { } blocks are processed no DNS lookup and no ident lookup has been done yet).

Valid types are:

Type Meaning
kline Exempt from K-Line (KLINE)
gline Exempt from G-Line (GLINE)
zline Exempt from Z-Line (ZLINE)
gzline Exempt from Global Z-Line (GZLINE)
shun Exempt from Shun (SHUN)
spamfilter Can bypass spamfilters
qline Can bypass banned nick restrictions (QLINE)
blacklist Don't do any blacklist checking
connect-flood Exempt from set::anti-flood::connect-flood
unknown-data-flood Do not place ZLINE when client is flooding before registration phase
antirandom Bypass antirandom module
antimixedutf8 Bypass antimixedutf8 module
ban-version Bypass ban version { } blocks
all All of the above, except qline

If you do not specify any type, then the exception defaults to: kline + gline + zline + gzline + shun.


except ban {
	mask *@192.168.*;
	mask *@;

Except TKL block

The except tkl block allows you to specify a [email protected] that will override a tkl ban placed on a broader host. This is useful when you want an ISP banned, but still want specific users to be able to connect.

NOTE: In UnrealIRCd 5 this block no longer exists, see Except ban block instead


except tkl {
	mask <hostmask>;
	type <type>;
	type { 

The except::mask directive specifies the [email protected] mask of the client who will be allowed to connect. The except::type specifies which type of ban this should override. Valid types are gline, gzline, qline, gqline, shun, and all, which make an exception from Glines, Global Zlines, Qlines, Global Qlines, shuns, and all bans except KLINE/ZLINE. If the type {} format is used, multiple types may be specified.

NOTE: If you want to exempt a host completely from all possible bans (except spamfilter), then you need both an 'except ban' and an 'except tkl' block


except tkl {
	mask [email protected];
	type gline;

Except throttle block

The except throttle block allows you to specify an IP mask that will not be affected by set::anti-flood::connect-flood (the throttling system).

Note that connection throttling is an important security measure. It provides primary and secondary protection against DoS, flood and brute force attacks, both for handshake and fully registered connections. If you exempt connections from this then you severely degrade these protections. You should only do so for IP's you trust.


except throttle {
	mask <ipmask>;

The except::mask specifies an IP mask that will not be banned because of throttling.


except throttle {
	mask 192.168.1.*;

Deny DCC block

The deny dcc block allows you to specify a filename which will not be allowed to be sent via DCC over the server. This can be useful in helping stop distribution of trojans and viruses.


deny dcc {
	filename <file-to-block>;
	reason <reason-for-ban>;
	soft [yes|no];

The deny::filename parameter specifies a wildcard mask of the filename to reject sends of, and deny::reason specifies the reason why this file is blocked.

There's also a deny::soft option, if set to 'yes' the dcc is blocked unless the user explicitly allows it via /DCCALLOW +nickname-trying-to-send. See dccallow.conf for a good example configuration for dccallow.


deny dcc {
	filename virus.exe;
	reason "This is a GD Virus";
deny dcc {
	filename "*.exe";
	reason "Executable content";
	soft yes;

Allow DCC block

The allow dcc blocks allows you to specify exceptions over the Deny DCC block.


allow dcc {
	filename "<filename-mask>";
	soft [yes|no];

The filename specifies the name of the file, wildcards are permitted. If allow dcc::soft is set to 'yes' it applies to 'soft dcc bans' list, if set to 'no' it applies to the normal ('hard') dcc bans.


allow dcc {
	filename "*.jpg"; /* Images are usually safe */
	soft yes;

Deny version block

This block allows you to deny a server from linking in, based on the version of Unreal it is running and what compile time options it has.

Not to be confused with the Ban version block (which bans clients based on their CTCP VERSION reply!)


deny version {
	mask <server-name>;
	version <version-number>;
	flags <compile-flags>;

The format for this block is somewhat complex but isn't too hard to figure out. The deny::mask directive specifies a wildcard mask of the server name this applies to. The deny::version specifies the protocol number of the version this refers to.

For example, 3.0 is 2301, 3.1.1/3.1.2 is 2302, 3.2 is 2303. The first character of this parameter can be one of the following >, <, =, !. This character tells the IRCd how to interpret the version. If the first character is a > then all version greater than the specified version are denied, if it is a < all versions lower are denied, if it is an = only that version is denied, and if it is a ! then all versions except the specified are denied. The deny::flags directive allows you to specify what compile time flags the server may or may not have. The flags are arranged one after the other with no separation between, if a character is prefixed by a ! then it means the server may not have this flag compiled into it, if it does not have a ! prefix, then it means the server must have this flag compiled.

Deny link block

This block allows you to use specific rules to deny a server from linking. It's slightly complex and typically only used on networks with 3 or more servers.


deny link {
	mask <server-name>;
	rule <crule-expression>;
	type <type-of-denial>;

The deny::mask specifies a wildcard mask of the server name to apply this rule to. The deny::rule directive is very complex. A crule expression allows you to control the link in great detail, and it is set up like a programming expression. Four operators are supported, connected(<servermask>), returns true if a server matching servermask is connected, directcon(<servermask>), returns true if the server matching servermask is directly connected to this server, via(<viamask>,<servermask>), returns true if a server matching servermask is connected by a server matching viamask, and directop(), which returns true if the operator issuing a /connect is directly connected to this server. These operators can be combined using && (and) and || (or), items may also be enclosed in parenthesis to allow grouping. In addition, an operator preceded with a ! checks if the operator returned false. If the entire expression evaluates to true, then the link is denied. The deny::type allows two different values, auto (only applies to autoconnects, /connect will still work), and all (applies to all connection attempts).

Deny channel block

The deny channel block allows you to disallow users from joining specific channels.


deny channel {
	channel "<channel-mask>";
	reason <reason-for-ban>;
	redirect "<channel-name>"; // optional
        mask "<ip/hostmask>"; // optional
	warn [on|off]; // optional

There are two required items: channel is a wildcard mask matching channels the users may not join and reason specifies the reason why the channel may not be joined.

Optionally, you may specify redirect. If this is specified, when a user tries to join a channel that matches deny::channel, he/she will be redirected to the redirect channel.
mask makes this deny channel block only apply to users matching the specified ip/hostmask (eg: 192.168.*).
Finally, there is warn which defaults to off. When set to on an opernotice will be generated (to the EYES snomask) if the user tries to join the denied channel.


deny channel {
	channel "#unrealsucks";
	reason "No it doesn't!";

deny channel {
	channel "#*teen*sex*";
	reason "You == dead";
	warn on;

deny channel {
	channel "#operhelp";
	reason "Our network help channel is #help, not #operhelp";
	redirect "#help";

Allow channel block

The allow channel block allows you to specify specific channels that users may join. It is used to exempt channels that were banned through the Deny channel block.


allow channel {
	channel "<channel-mask>";
        mask "ip/hostmask"; // optional!

channel specifies the wildcard mask of the channels which may be joined.

The optional mask makes it possibly to apply this block only to certain users. It's rarely used since bans are a better method of handling channel access.


/* Deny joining all channels with 'help' in it */
deny channel {
        channel "#*help*";
        reason "We only have one official help channel. Please join #help instead.";

/* Allow #help */
allow channel {
	channel "#help";

/* Allow #lanhelp only to 192.168.* users */
allow channel {
	channel "#lanhelp";
        mask 192.168.*;

Vhost block

The vhost block allows you to specify a login/password that can be used with the /VHOST command on IRC to obtain a fake hostname.

NOTE: Most people use Services instead, which often provide a HostServ bot or capability. This basically allows you to centrally manage vhosts.


vhost {
	vhost <vhost>;
	mask {
	login <login-name>;
	password <password> { <auth-type>; };
	swhois "<swhois info>";

The vhost::vhost parameter can be either a [email protected] or just a host that the user will receive upon successful /vhost. The vhost::mask block contains a [email protected] that the user must match to be eligible for the vhost. You may specify more than one hostmask. The vhost::login in the login name the user must enter and vhost::password is the password that must be entered. The vhost::password:: allows you to specify the type of authentication used by this item. See Authentication Types for a list of available types. Lastly vhost::swhois allows you to add an extra line to a users whois, exactly as it does in the Oper Block oper::swhois.


vhost {
	mask { *; 192.168.*; 127.*; };
	login mynick;
	password mypassword;
	swhois "Im Special";

Badword block

The badword block allows you to manipulate the list used for user and channel mode +G to strip "bad words".


badword <type> {
	word <text-to-match>;
	replace <replace-with>;
	action <replace|block>;

The badword:: specifies the type, which decides what messages this badword filter applies to. The valid types are:

  • channel: applies to channels with mode +G.
  • message: applies to private messages (not in-channel messages) sent by a user with the +G usermode.
  • all: applies to both channel and message

The badword::word can be a simple word or a regular expression we should search for. The badword::replace is what we should replace this match with. If badword::replace is left out, the word is replaced with <censored>. The badword::action defines what action should be taken if this badword is found. If you specify replace, then the badword is replaced, if you specify block, then the entire message is blocked. If you do not specify a badword::action, replace is assumed.


badword channel {
	word shit;
	replace shoot;

ULines block

The ulines block lets you define certain servers as having extra abilities. This should only be used for servers such as services and should never match a regular UnrealIRCd server (otherwise you'll create security issues).


ulines {

Each entry is the name of the server which will receive the extra abilities.


ulines {;;

Link block

If you are linking servers we recommend you to follow our Tutorial: Linking servers instead. The link block is, however, shown below for reference.


link <server-name> {
    /* Below, often you will have both an incoming { } and outcoming { } sub-block.
     * However you may also choose to have only 1 of them if you always link in the same direction.
    incoming {
        mask 1.2.3.*;
    outgoing {
        bind-ip <ip-to-bind-to>; /* optional now */
        hostname; /* may also be an IP */
        port 6697;
        options { ssl; autoconnect; }; /* optional, but recommended */
        ssl-options { protocols "TLSv1.2"; }; /* optional, only set this if you know what you are doing. */
    password "some-password"; /* either a plaintext password that's the same for both sides or an SSL fingerprint (or certificate) */
    verify-certificate [yes|no]; /* optional, default is 'no' but is less secure */
    hub <hub-mask>; /* optional */
    leaf <leaf-mask>; /* optional */
    leaf-depth <depth>; /* optional */
    class <class-name>;
    ciphers <ssl-ciphers>; /* optional */
    options {
        quarantine; /* is a generic option. optional. */

Required items

Note that you need link::incoming and/or link::outgoing. So at least one of them is required.


The server-name in your link <server-name> { block specifies the name of the server, that is the name you have specified in me::name on the other side of the link.



Only servers matching this (IP) mask may use this link block.



Hostname of the server to connect. This could be the same as the server-name, but it may also be an IP or a different DNS name.


Port of the other server to connect to

outgoing::options (optional)

The following two options are available:

  • insecure: by default UnrealIRCd will attempt to 'upgrade' a connection to use SSL/TLS in order to get encrypted server links. An alternative is to use the ssl option below which will also ensure SSL/TLS. If both of these methods fail then we reject the link. You can use this option, insecure, to still allow linking with non-SSL/TLS servers, but we do not recommend it.
  • ssl: connect to an SSL/TLS-only-port. If you use this, then be sure that the outgoing::port you specify is in fact a SSL-only port. Meaning: the server on the other side of the link must have listen::options::ssl turned on for that port.
  • autoconnect: automatically connect to the server (or try to every XX seconds, anyway)
outgoing::ssl-options (optional)

Valid options are all the SSL settings that also exist in set::ssl. For example you can set the permitted SSL protocols and ciphers:

link xyz {
        outgoing {
                ssl-options {
                        protocols "TLSv1.2";
                        ciphers "AES256";
outgoing::bind-ip (optional)

Bind to this IP before connecting to the other server. The IP to bind to must be available on the machine (must not be an IP of another machine).


Password or other method to use to verify the authenticity of the link. This must be either: 1) a plaintext password that must be the same on both sides of the link, OR 2) an SSL fingerprint, which is our recommended and safest way to link, see our Tutorial.


When set to 'yes' this will enable SSL certificate checking to make sure that:

  • The SSL certificate of the server you are linking with is valid and issued by a trusted Certificate Authority (eg: Let's Encrypt or some bought certificate)
  • The name in the link block matches the name(s) in the certificate (eg: if you're linking with and it presents a certificate for it will fail)

Enable this if you (can) meet these criteria. It will protect you from active traffic interception attacks.


The value is a mask of what servers this hub may connect (ex: *


The value is a mask of what servers this hub may not connect.


The value specifies the depth (number of hops) this server may have beneath it. For example, 1 means the server can't have any links under it (a leaf), 2 means it can link servers but those servers can't link anything under them (that is, this hub can only link leaves). A value of 0 means no limit, and is the default.


The class this server is put into (see Class block), often a separate server class is used for this.


There's only one generic option:

  • quarantine: This link may have no IRC Operators on it. If someone attempts te become OPER on the link they are de-oper'ed. Note that this does not provide true security: a person controlling a server can still modify the source and load any modules they want, thus still 'be able to do anything' if they have bad intentions.

For other link options see the link::outgoing block.


See Tutorial: Linking servers

Alias block


Standard alias

alias <name> {
	target <nick-to-forward-to>;
	type <type-of-alias>;
	spamfilter <yes|no>;

(Note that <name> is referred to using "alias::")

(Note: see a description of the standard alias files UnrealIRCd has)

The alias block [standard alias] allows you to forward a command to a user, for example /chanserv sends a message to the user chanserv.

alias:: specifies the name of the command that will be the alias (eg: chanserv)

alias::target is the nickname or channel it will forward to. If alias:: would be the same as the target, alias::target may be left out.

alias::type specifies the type of alias, valid types are

  • services (the user is on the services server),
  • stats (the user is on the stats server),
  • normal (the user is a normal user on any server),
  • channel (the target is a channel name), and
  • command (this is not a "standard alias", see below).

alias::spamfilter (optional) causes the spamfilters will be checked if set to "yes" (default is 'no').

Command alias

alias <name> {
	/* For aliases to be sent to users/channels */
	format <regex-expression> {
		target <nick-to-forward-to>;
		type <type-of-alias>;
		parameters <parameter-string>;
	/* For 'real aliases' */
	format <regex-expression> {
		command <command>;
		type real;
		parameters <parameter-string>;
	/* Etc... You can have as many format blocks as you wish.. */
	format <regex-expression> {
	type command;
	spamfilter <yes|no>;

When an alias block has alias::type set to command, as shown above, it becomes a command alias. When the alias block is used in this format, it is much more flexible. For example, you could create an /identify alias.

alias:: is the name of the alias command as in standard alias block form (above).

alias::format specifies a regular expression which is matched against the text sent to the alias command. The sub-entries of the first matching alias::format will be used. Thus, you may have multiple alias::formats to make a command do different things depending on the text sent to it.

alias::format::target is the target to forward this alias to. This value is not used if alias::format::type is "real".

alias::format::type specifies the type of the alias that the message should be forwarded to. In addition to the types mentioned previously in "Syntax [standard alias]", "real" may be specified here for a "real alias" (a "real alias" is an alias that may be rewritten to something other than a PRIVMSG).

alias::format::parameters (for "real aliases") is what will be sent as the parameters to this alias. To specify one of the parameters given to the command alias specify % followed by a number. For example, %1 is the first parameter. To specify all parameters from a given parameter to the end, use % followed by the number and a -. For example, %2- returns all parameters from the second through the last. Additionally, you may specify %n which will be replaced by the nickname of the user who executed the command.

For examples of using the alias block in the command format, see aliases/*.conf.

Help block

The help block allows you to create entries for use with the /HELPOP command.


help <name> {

The help:: is the value that must be passed to /helpop as a parameter, if the help:: is left out, then it will be used when no parameter is passed to /helpop. The entries for the help block are the text that will be displayed to the user when requesting the /helpop.

Default help

Pretty much everyone would want to just include the help.conf included in UnrealIRCd:

include "help.conf";


help something {
        "This is some really useful text.";
        "I don't know what to say...";

Official-channels block

Official channels are shown in /LIST even if no users are in the channel.


official-channels {
	"#channel" { topic "The default topic"; };

The topic is optional and is only shown in /LIST if the channel has 0 users.


official-channels {
	"#Help" { topic "The official help channel, if nobody is present type /helpop helpme"; };
	"#Main" { topic "The main channel"; };

Spamfilter block

The spamfilter block allows you to add local spam filters (not network-wide). See the Spamfilter article for more information about spamfilters.


spamfilter {
        match-type [simple|regex|posix];
	match <text>;
	target { <target(s)> };
	action <action>;
	reason <reason>;
	ban-time <time>;

Please see the Spamfilter article for an explanation on all these fields. They are exactly the same as the /SPAMFILTER command. See also the examples in the same article.

For even more examples have a look at spamfilter.conf in UnrealIRCd.

Blacklist block

Other languages:

<translate> The blacklist block allows you to use a DNS blacklist (DNSBL). Every user that connects to your server will be checked against the blacklists specified.


blacklist <name> {
        dns {
                name <blacklist hostname>;
                type <record|bitmask>;
                reply { <permitted replies> };
        action <action>;
        reason <reason>;
        ban-time <time>;

First of all, each blacklist has a <name>, which is just a short name for the blacklist block.

Currently the only supported type of blacklists are DNS blacklists. This is configured via blacklist::dns which consists of three items: blacklist::dns::name specifies the blacklist to use (eg: blacklist::dns::type defines if the blacklist is of type record or bitmask, your blacklist should provide this info, if in doubts then use record. Finally, blacklist::dns::reply configures which DNS replies are considered a 'match'. Consult the documentation of the blacklist you use, as they are blacklist-specific!

The remainder of the blacklist block defines what should be done upon a match: blacklist::action specifies an action, such as kline (see Actions for a full list). blacklist::ban-time defines after how much time the *LINE (if any) should be removed. blacklist::reason specifies the kill/ban reason shown to the user. You can use the variables $ip and $server in this field, which will be replaced with the IP address of the banned user and the name of the IRC server respectively.


These are the two most common blacklists that users use:

blacklist efnetrbl {
        dns {
                type record;
                reply { 1; 4; 5; };
        action gline;
        ban-time 24h;
        reason "Proxy/Drone/TOR detected. Check$ip for details.";

blacklist dronebl {
        dns {
                type record;
                reply { 3; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; };
        action gline;
        ban-time 24h;
        reason "Proxy/Drone detected. Check$ip for details.";

See also


WebIRC block

The webirc block allows you to configure host spoofing for WebIRC / CGI:IRC gateways you trust, see WebIRC Support

This block was previously called cgiirc { }


webirc {
        mask; /* ip or host mask */
	type <webirc|old>; /* optional, webirc is the default */
	password <password>;

type is 'webirc' by default, 'old' is really really old and this method will be removed soon, so don't use it.

mask is checked against the client (the WebIRC or CGI:IRC gateway) that is trying to connect.

password is the webirc password

How to configure with method 'webirc' (recommended method)

In both your web IRC client software and UnrealIRCd you have to set the same webirc password.

Example with KiwiIRC

The example below configures KiwiIRC and UnrealIRCd. Note that this is just an example, if you use something other than KiwiIRC you edit that instead of the KiwiIRC-side.


Edit kiwiirc's config.js as follows (note: this is NOT a complete configuration file, it just shows 3 important sections):

// WebIRC passwords enabled for this server
conf.webirc_pass = {
    "":        "ThisIsMySecretWebIRCPassword"

// Default settings for the client. These may be changed in the browser
conf.client = {
    server: '',
    port:    6697,
    ssl:     true,
    channel: '#test',
    nick:    'kiwi_?'
// or use conf.restrict_server etc... to achieve the same effect (see example config.js file).

// What matters is that the server name in conf.client or conf.restrict_server
// match the server name in conf.webirc_pass (and use the right password).
// So be sure to replace BOTH the instances with the same server name.

// Now something else... "send ip as username"....
// Be sure *NOT* to list your server here !!!!
// If you add it here, then the IP will show up in the ident. This is NOT what you want
// as the IP is already sent via WEBIRC. Doing so would reveal the users' IP to everyone which is bad.
conf.ip_as_username = [


Then, in your unrealircd.conf you add a webirc block:

webirc {
	password "ThisIsMySecretWebIRCPassword";

except throttle {

The Except throttle block block is highly recommended, so your webirc server is not seen as connection flooding. Without it, users may not be able to connect during peaks or after a server restart.

How to configure with method 'old'

IMPORTANT: This is a really old method and it will be removed soon. Don't use it.

NOTE: This is not the recommended method since it has two disadvantages: this method will send the IP/host to spoof as a server password, meaning you cannot specify a server password as a CGI:IRC user. Additionally, access control is only IP-based and does not require an extra password like the 'webirc' method. In short, you probably should not be using this method unless you have a good reason to do so.

In your CGI:IRC configuration file (cgiirc.conf) you set realhost_as_password to 1. Then, in your unrealircd.conf you add a cgiirc block to allow this host.


In your CGI:IRC configuration file (cgiirc.conf) you add:

realhost_as_password = 1

Then, in your unrealircd.conf you add a webirc block:

webirc {
	type old;

Set block

Other languages:

<translate> The set block is used to tweak and configure the server settings.

Sharing settings

If you (already) run multiple IRC servers then have a look at Sharing settings between servers to ease the burden when updating settings. The set block is an ideal candidate to be shared.

Syntax used in this documentation

As described in Configuration file syntax we will refer to settings like set::options::hide-ulines or set::auto-join. When we mention these we don't mean that you should really write set::options::hide-ulines as-is! It's just a shorthand. What we actually mean is you should write them out like this:

set {
        options {
        auto-join "#something";

Or you could put them in separate set blocks like this:

set {
        auto-join "#something";

set {
        options {

Or even just:

set { options { hide-ulines; }; };
set { auto-join "#something"; };

If the above is unclear, then maybe have another read at the Configuration file syntax article.

As you can see from above it's perfectly fine to have multiple set { } blocks! In fact it's quite normal to have one block with network-wide settings and one with server-specific settings. We generally don't recommend having much more separate set blocks as it's easy to loose track of them (and what settings is where), but it is perfectly possible.

Available settings


Syntax: set::kline-address <email-address>

The email address that K:line questions should be sent to. This value must be specified. See also set::reject-message::kline if you want a more custom disconnect message on KLINE/ZLINE.


Syntax: set::gline-address <email-address>

The email address that G:line questions should be sent to. See also set::reject-message::gline if you want a more custom disconnect message on GLINE/GZLINE.


Syntax: set::modes-on-connect <+modes>

The modes that will be set on a user at connection.


Syntax: set::modes-on-oper <+modes>

The modes that will be set on a user when they /oper.


Syntax: set::snomask-on-oper <+modes>

The snomask that will be set on a user when they /oper.


Syntax: set::modes-on-join <+modes>

The modes that will be set on a channel when it is first created. Not all modes can be set using this command.


Syntax: set::level-on-join <none|voice|halfop|op|protect|owner>

The mode that a user will get when he's the first to join a channel. The default is 'op' (channel operator).


Syntax: set::restrict-usermodes <modes>

Restrict users to set/unset the modes listed here (don't use + or -). For example you can set +G in modes-on-connect and G in restrict-usermodes, that way you can force all users to be +G and unable to do -G.


Syntax: set::restrict-channelmodes <modes>

Restrict users to set/unset the channelmodes listed here (don't use + or -). For example you can set +G in modes-on-join and G in restrict-channelmodes, that way you can force all (new) channels to be +G and unable to do -G. NOTE: it may still be possible to use these channelmodes through services by using MLOCK. Unfortunately we can't do much about that, you would have to ask the services coders to implement a restrict-channelmodes feature too.


Syntax: set::restrict-extendedbans <types|*>

Don't allow users to use any extended bans ("*") or disallow only certain ones (eg: "qc").


This allows you to restrict a certain command to users depending on: how long they are connected, if they are identified to Services, and their reputation. IRCOps can always bypass any restrictions.

Important: this feature only exists in UnrealIRCd 5

You can restrict any command, simply by specifying the command, and there are also 4 special types: "private-message", "private-notice", "channel-message" and "channel-notice" (that under the hood will restrict PRIVMSG and NOTICE).

Example configuration:

set {
        restrict-commands {
                list {
                        connect-delay 60;
                        exempt-identified yes;
                        exempt-reputation-score 24;
                invite {
                        connect-delay 120;
                private-message {
                        connect-delay 10;
                somecommand {
                        disable yes;

The option connect-delay will impose the restriction for the specified time (eg: 60 meaning 60 seconds). This can be useful against spammers since they usually spam quickly after connecting (before they are catched by opers or channel operators).

The option exempt-identified will exempt the restrictions to users who are identified to Services, in other words: are authenticated users. These users normally went through a registration procedure that provides sufficient (but minimal) trust that they can use the command straight away, without without any connect delay restrictions.

The option exempt-reputation-score means that if the reputation score is equal or above this number then the user bypasses this restriction. The reputation score is assigned by the reputation module. More about it can be read in the Connthrottle module.

Finally, the simple option disable will disable the command for all users. As with all restrictions, IRCOps can still use the command.


Syntax: set::auto-join "<channels>"

The channel(s) a user will be forced to join at connection. To specify more than one channel use a comma separated list. [Note: don't forget to add quotes, like: auto-join "#chan"]


Syntax: set::oper-auto-join "<channels>"

The channel(s) a user will be forced to join when they /oper. To specify more than one channel use a comma separated list. [Note: don't forget to add quotes, like: oper-auto-join "#chan"]


Syntax: set::anti-spam-quit-message-time <timevalue>

A time value specifying the length of time a user must be connected for before a /quit message will be displayed. Used to prevent spam. A time value is a numeric string with d meaning days, h meaning hours, m meaning minutes, and s meaning seconds, for example 1d2h3m means 1 day, 2 hours, 3 minutes.


Syntax: set::prefix-quit <text-to-prefix-quit>

Sets the text that will be used to prefix a quit message. If this value is set to 0 then the standard "Quit:" is used.


Syntax: set::static-quit <quit message>

Sets a static quit message that will be sent whenever a client logs off the network. This eliminates the need for anti-spam-quit-message-time, as well as the set::prefix-quit. It will NOT replace ERRORS with the static-quit message.


Syntax: set::static-part <no|yes|part message>

A value of 'yes' strips all part comments, a value of 'no' makes part just work as usual, anything else will be used as a part comment (eg: static-part "Bye!") but this can be quite annoying, so use with care.


Syntax: set::who-limit <limit>

Sets the limit for the maximum number of matches that will be returned for a /who. If this option is left out, no limit is enforced.


Syntax: set::silence-limit <limit>

Sets the limit on the maximum SILENCE list entries. If this directive is not specified, a limit of 15 is set.


Syntax: set::maxbans <limit>

Sets the limit on the maximum amount of bans (+b) allowed per channel. The default is 60. The same limit is applied to exempts (+e) and invex (+I) as well. If you change this, be sure to also take a look at maxbanlength (see next)!


Syntax: set::maxbanlength <limit>

Similar to above, but sets the maximum amount of characters for all bans added up together, so basically this puts up a limit on the (semi-)maximum amount of memory all channel bans on a channel can take. The default is 2048 (bytes). With the default set::maxbans of 60 this allows 2048:60=34 characters per ban on average. Note that if you change this, the same limit is also applied to excepts (+e) and invex (+I).


Syntax 1: set::oper-only-stats <stats-list-in-letters>
Syntax 2: set::oper-only-stats {<long-stats-flag1> <long-stats-flag2>}

NOTE: This setting only exists in UnrealIRCd 4.x.

Specifies a list of /STATS flags that only IRC Operators may see. The default is "*" which will prevent any regular user from using /STATS.

Be careful if you tweak this, some stats are not meant to be exposed to regular users and the information contained in them will often aid attackers / "bad guys".


Syntax 1: set::allow-user-stats <stats-list-in-letters>
Syntax 2: set::allow-user-stats {<long-stats-flag1> <long-stats-flag2>}

NOTE: This setting only exists in UnrealIRCd 5.x.

Specifies a list of /STATS flags that users may also see (non-IRCOps). The default is "" (empty), which means regular users may not see any /STATS.

Be careful if you tweak this, some stats are not meant to be exposed to regular users and the information contained in them will often aid attackers / "bad guys".


Syntax: set::min-nick-length <length>
Important: this setting only exists in UnrealIRCd 5

Specifies the minimum required length of a nick name. This defaults to 0 which means there's no minimum. The maximum is 30 (NICKLEN) but it should still be smaller than (or equal to) set::nick-length.


Syntax: set::nick-length <length>

Specifies the maximum length of a nick name. This default and maximum is 30 (NICKLEN). This setting can only be used to impose a shorter nick length than that.


Syntax: set::topic-length <length>

Specifies the maximum length of a channel topic. This default and maximum is 360, or 340 if set::topic-setter is set to 'nick-user-host'. This setting can only be used to impose a shorter length.

Until UnrealIRCd 4.2.1 the default was 307.


Syntax: set::away-length <length>

Specifies the maximum length of the away reason in /AWAY. The default is 307 and the maximum is 360.


Syntax: set::quit-length <length>

Specifies the maximum length of the quit reason in /QUIT. The default is 307 and the maximum is 395.


Syntax: set::kick-length <length>

Specifies the maximum length of the kick reason in /KICK. The default is 307 and the maximum is 360.


Syntax: set::maxchannelsperuser <amount-of-channels>

Specifies the number of channels a single user may be in at any one time. IRCOps are exempt from this restriction.


Syntax: set::maxdccallow <amount-of-entries>

Specifies the maximum number of entries a user can have on his/her DCCALLOW list.


Syntax: set::channel-command-prefix <command-prefixes>

Specifies the prefix characters for services "in channel commands". Messages starting with any of the specified characters will still be sent even if the client is +d ("deaf"). The default value is "`!." which is normally a good setting.


Syntax: set::allowed-nickchars { <list> }

Character sets / languages to allow in nick names, see Nick Character Sets.


Syntax: set::allowed-channelchars [utf8|ascii|any]

Which characters to allow in channel names. This setting must be the same on all servers. This setting is new in UnrealIRCd 5.

There are 3 possible settings (utf8, ascii and any):

Setting Allowed characters Comment
utf8 All valid UTF8 characters This is the new default as of UnrealIRCd 5. It should be suitable for nearly everyone since UTF8 is the de-facto standard on IRC nowadays.
ascii Only a-z/A-Z/0-9 and a few other ASCII characters This is a strict setting. It can be used if you don't want any confusion with channel names, no UTF8, etc. Technically this would be safest. Freenode uses this in their software.
any Almost all characters are permitted This is a very loose setting and was the default in UnrealIRCd 4.x. The problem is that this breaks text websocket clients. It is NOT a recommended setting.

The following characters are ALWAYS REJECTED: ASCII values below 32 (control characters), the space character, comma, colon.

Note that if you mix UnrealIRCd 4 and UnrealIRCd 5 servers on your network, then some channels which are considered illegal by this setting will be unjoinable on the UnrealIRCd 5 side. This will be especially noticeable if you use a strict setting like ascii, but may also happen for some channels if you use utf8. This problem will disappear once all of your servers are on UnrealIRCd 5. The alternative is to run with a setting of any during the transition, and then once everything is on UnrealIRCd 5, switch over to utf8. However, it is easy to forget about that last step.


Syntax: set::allow-userhost-change [never|always|not-on-channels|force-rejoin]

Specifies what happens when the [email protected] changes (+x/-x/chghost/chgident/setident/vhost/etc). never disables all the commands, always does always allow it even when in channels (may cause client desyncs) [default], not-on-channels means it's only allowed when the user is not on any channel, force-rejoin will force a rejoin in all channels and re-op/voice/etc if needed.


Syntax: set::topic-setter [nick|nick-user-host]

You can see who set the TOPIC by doing /TOPIC #channel. By default this only shows the nick of the person who set the topic. If you set this option to nick-user-host then it will show the [email protected] instead.


Syntax: set::ban-setter [nick|nick-user-host]

You can see who set a ban/exempt/invex (+beI) by doing /MODE #channel b (or similar). By default this only shows the nick of the person who set the topic. If you set this option to nick-user-host then it will show the [email protected] instead.


Syntax: set::options::hide-ulines

If this is present, Ulined servers will be hidden in /MAP and /LINKS for regular users (non-ircops). This is a very common thing to do.


Syntax: set::options::flat-map

If this is present, all servers will appear as directly linked in /map and /links, thus you can no longer see which server is linked to which. This is a little help against (D)DoS attacks because evil people now no longer can easily see the 'weak points'.


Syntax: set::options::show-opermotd

If present the opermotd will be shown to users once they successfully /oper.


Syntax: set::options::identd-check

If present the presence of an identd server will be checked and the returned value will be used for the username. If no ident request is returned or the identd server doesn't exist, the user's specified username will be prefixed with a ~. If this value is omitted no such check is made.


Syntax: set::options::show-connect-info

If present notices showing "ident request", "hostname lookup", etc. will be displayed when a user connects.


Syntax: set::options::dont-resolve

If present hosts of incoming users are not resolved, can be useful if many of your users don't have a host to speed up connecting. Note that since no resolving is done you also can't have host based allow blocks.


Syntax: set::options::mkpasswd-for-everyone

Makes it so the /mkpasswd can be used by anyone instead of oper-only, usage of the command by non-opers is sent to the EYES snomask.


Syntax: set::options::allow-part-if-shunned

Allow shunned user to use /part.


Syntax: set::options::fail-oper-warn

If present, a user will be notified that his/her failed /oper attempt has been logged.


Syntax: set::options::allow-insane-bans

Allow insane broad bans like /GLINE *@*.xx. This makes it very easy to accidentally ban everyone on your network, so use with great care!


Syntax: set::options::disable-cap

Disable IRC Client Capabilities Extensions (CAP). Note that this makes SASL and various other features unavailable or harder for clients to use.


Syntax: set::nopost::ban-action (requires m_nopost)

Action to take on a user if he tries to perform an HTTP POST command. The allowed values are: kill, gline, gzline, kline, zline, shun, and tempshun. The default value is kill. If you use a *line value or shun, then note that if gullible user who is tricked into visiting a website exhibiting the XPS IRC spamming attack will experience the shun or *line on his existing connections. The default value of kill protects against such user accidents, but use of *line and especially gzline may be needed in some situations.


Syntax: set::nopost::ban-reason (requires m_nopost)

The ban reason to set when m_nopost kills or bans a user.


Syntax: set::nopost::ban-time (requires m_nopost)

The duration for shuns, glines, gzlines, klines, and zlines set by m_nopost. Default is 4h.


Syntax: set::nopost::except-hosts (requires m_nopost)

A list of hostmasks to exempt from m_nopost's killing or *-lining. You should never need to place any hostmasks in this option.


Syntax: set::dns::bind-ip <ip>

Specifies the IP to bind to for the resolver, rarely ever needed.


Syntax: set::network-name <name-of-network>

Specifies the name of the network on which this server is run. This value should be exactly the same on all servers on a network.


Syntax: set::default-server <server-name>

Defines the name of the default server to tell users to connect to if this server is full.


Syntax: set::default-ipv6-clone-mask

The default IPv6 clone detection mask. See allow::ipv6-clone-mask. The default value for this setting is 64.


Syntax: set::services-server <server-name>

Specifies the name of the server that the services bots are connected to. See also Services.


Syntax: set::stats-server <server-name>

Sets the name of the server on which the stats bot is located. If stats are not run this value may be left out.


Syntax: set::sasl-server <server-name>

Sets the name of the server to which SASL authenticate messages should be sent.


Syntax: set::help-channel <network-help-channel>

Sets the name of the help channel for this network.


Syntax: set::cloak-method [ip|host]

This sets the method to use when cloaking a user. The default is host which will use hostname-based cloaking (and fallback to IP-based if no host is available). The alternative is to set this to ip which will make UnrealIRCd always do IP-based cloaking. This results in a XX.YY.ZZ.IP cloaked host which provides more anonymity. IRCOps can still see the real hostname of the user and GLINEs and such still work as well.


Syntax: set::cloak-keys { "key1"; "key2"; "key3"; }

UnrealIRCd has a feature called Cloaking. The keys you specify here are used to generate such a +x host. ALL servers on the same network must use the same keys and they must be kept secret.

Each key consists of 50-100 characters, the characters should contain a mixture of: lowercase (a-z), uppercase (A-Z) and digits.

On *NIX you can use ./unrealircd gencloak to generate 3 random keys.


/* This is just an example, don't actually use these keys yourself!! */
set {
    cloak-keys {

Syntax: set::hiddenhost-prefix <prefix-value>

Defines the prefix that will be used on hiddenhosts (+x). This is usually three or four letters representing the network name. Linked servers must have the same hidden-host prefix for channel bans to function properly.


Syntax: set::ssl::certificate <filename>

Specifies the filename where the server's SSL certificate is located. The default is server.cert.pem.


Syntax: set::ssl::key <filename>

Specifies the filename where the server's SSL private key is located. The default is server.key.pem.


Syntax: set::ssl::trusted-ca-file <filename>

Specifies the filename where the certificates of the trusted CAs are located. The default is curl-ca-bundle.crt (shipped with UnrealIRCd)


Syntax: set::ssl::protocols <list-of-protocols>

Specifies which SSL/TLS protocols are permitted. Available options are: All, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3 (the latter when it becomes available). Prefix the protocol with a - (minus sign) to remove it.

Example: set { ssl { protocols "All,-TLSv1,-TLSv1.1"; /* permit only TLSv1.2 and up */ }; };

See SSL Ciphers and protocols for more information and suggestions on a good setting.


Syntax: set::ssl::ciphers <cipherlist>

Specifies which ciphers to be allowed for TLSv1.0, TLSv1.1 and TLSv1.2. See SSL Ciphers and protocols for more information and suggestions on a good setting.


Syntax: set::ssl::ciphersuites <ciphersuitelist>

Specifies which ciphersuites to allow for TLSv1.3. See SSL Ciphers and protocols for more information.


Syntax: set::ssl::ecdh-curves <curvelist>

Specifies which ECDH(E) curves to be allowed. See SSL Ciphers and protocols for more information and suggestions on a good setting.


Syntax: set::ssl::renegotiate-bytes <value>

Specifies after how many bytes an SSL session should be renegotiated (eg: 20m for 20 megabytes).


Syntax: set::ssl::renegotiate-timeout <timevalue>

Specifies after how much time an SSL session should be renegotiated (eg: 1h for 1 hour).


Syntax: set::ssl::options::fail-if-no-clientcert

Forces clients that do not have a certificate to be denied. This would be an unusual setting to enable.

This option does not provide any security. A user can simply generate a client certificate and use it to connect, no verification is done.


Syntax: set::ssl::options::no-starttls

Disable STARTTLS. STARTTLS allows clients to use SSL/TLS on regular (non-SSL) ports, which is normally a good thing.


This sets the outdated SSL/TLS protocols. It is used for set::outdated-tls-policy.

The default setting is "TLSv1.0,TLSv1.1" which marks TLSv1.0 and TLSv1.1 as outdated. In case you wonder, SSLv3 is not listed here because UnrealIRCd never allows such connections anyway.


This sets the outdated SSL/TLS ciphers. It is used for set::outdated-tls-policy.

The default setting is "AES*" which requires some explanation: This effectively marks all ciphersuites without Forward Secrecy as outdated. It stills allows AES perfectly fine, but only in combination with ECDHE/EECDH, which provides Forward Secrecy. For example AES128-SHA256 would be considered outdated and ECDHE-RSA-AES128-GCM-SHA256 is not.

If you use a weird ::ciphers setting, for example one that allows CAMELLIA, then you may have to tweak ::outdated-ciphers also. This is, however, an extremely uncommon configuration.


This configures Strict Transport Security in UnrealIRCd.

Read SSL/TLS - Strict Transport Security for information on how to deploy this.


/* Read
 * before deploying this.
set {
        ssl {
                sts-policy {
                        port 6697;
                        duration 5m;

IMPORTANT: Invalid/untrusted SSL/TLS certificates or a non-working TLS port WILL LOCK YOUR USERS OUT if you use sts-policy!


The plaintext-policy block allows you to configure what UnrealIRCd should do with users/opers/server who are not connected via SSL/TLS.

set {
    plaintext-policy {
        user allow; /* must be one of: allow, warn, deny */
        oper warn; /* must be one of: allow, warn, deny */
        server deny; /* must be one of: allow, warn, deny */

An action of allow will allow the operation. The warn action will make the server send a warning notice. The deny action will reject the user/oper/server, in this case the user cannot connect, the IRCOp cannot /OPER and the server may not link.

The following prevents an IRCOp from /OPER'ing up via a non-SSL/TLS connection, it is the default in UnrealIRCd 5.0.0 and higher:

set {
    plaintext-policy {
        user allow;
        oper deny;
        server deny;

Optionally you can set a set::plaintext-policy::user-message and set::plaintext-policy::oper-message to change the default UnrealIRCd warn/deny text the user/ircop will receive.


The outdated-tls-policy block allows you to configure what UnrealIRCd should do with users/opers/server connecting with an outdated SSL/TLS protocol or cipher.

set {
    outdated-tls-policy {
        user warn; /* must be one of: allow, warn, deny */
        oper warn; /* must be one of: allow, warn, deny */
        server warn; /* must be one of: allow, warn, deny */

An action of allow will allow the operation. The warn action will make the server send a warning notice. The deny action will reject the user/oper/server, in this case the user cannot connect, the IRCOp cannot /OPER and the server may not link.

To decide which protocol and ciphers are considered outdated, the set::ssl::outdated-protocols and set::ssl::outdated-ciphers settings are used.

The defaults as of UnrealIRCd 4.2.2 are very liberal. A safer choice would be to deny IRCOp's and servers:

set {
    outdated-tls-policy {
        user warn;
        oper deny;
        server deny;

Optionally you can set a set::outdated-tls-policy::user-message and set::outdated-tls-policy::oper-message to change the default UnrealIRCd warn/deny text the user/ircop will receive.


Syntax: set::ident::connect-timeout <amount>

Amount of seconds after which to give up connecting to the ident server (default: 3s).


Syntax: set::ident::read-timeout <amount>

Amount of seconds after which to give up waiting for a reply (default: 15s).


Syntax: set::handshake-timeout <amount>

Amount of seconds that a connection may be in the "handshake state", that is: the period between a TCP/IP connection accept() and the user getting online after NICK/USER have been received and DNS and ident lookups have completed (if those are enabled).

The default is 30 which is a safe value for everyone. Be careful if drastically lower this. DNS lookups, ident lookups and the handshake may take more time than you may think in some cases. You can probably set this to a value like 20 if you like. However, if you set this setting too low then you risk locking everyone out when for example your DNS server is a little slow (eg: under attack).


Syntax: set::sasl-timeout <amount>

The maximum time for SASL to take place. Time starts at the AUTHENTICATE command. The default is 15 seconds.

This protects against misbehaving or extremely laggy SASL servers (Services). Otherwise, a misbehaving server could lead to people no longer being able to connect.


Syntax: set::anti-flood::connect-flood <count>:<period>

Connection flood protection: limits the number of connection attempts from each IP to 'count' per 'period' seconds. Default is 3 per 60. This feature is also referred to as connection throttling.

UnrealIRCd also has Connthrottle which will rate limit the number of connection attempts in total (so not per-IP).

Note that connection throttling is an important security measure. It provides primary and secondary protection against DoS, flood and brute force attacks, both for handshake and fully registered connections. If you disable it or set it very permissive (eg 6 per 60 seconds) then you severely degrade these protections.


Syntax: set::anti-flood::nick-flood <count>:<period>

Nickflood protection: limits nickchanges to 'count' per 'period' seconds. For example nick-flood 4:90 means 4 per 90 seconds, the default is 3 per 60.


Syntax: set::anti-flood::join-flood <count>:<period>

Join flood protection: limits joins (to the same channel) to 'count' per 'period' seconds. For example join-flood 4:90 means 4 per 90 seconds, the default is 3 per 90. Previously this was configured through channel mode +j.


Syntax: set::anti-flood::away-flood <count>:<period>

Away flood protection: limits /away to 'count' changes per 'period' seconds. Example: away-flood 5:60s means max 5 changes per 60 seconds.


Syntax: set::anti-flood::invite-flood <count>:<period>

Invite flood protection: this limits /INVITE to a rate of 'count' per 'period' seconds. The default is 4:60 which means 4 /INVITE's per 60 seconds.


Syntax: set::anti-flood::knock-flood <count>:<period>

Knock flood protection: this limits /KNOCK to a rate of 'count' per 'period' seconds. The default is 4:120 which means 4 /KNOCK's per 120 seconds.


Syntax: set::anti-flood::unknown-flood-amount <amount>

When we receive a connection from a user and this user sends more than <amount> kilobytes of data BEFORE actually coming online (a so called "unknown connection") then the user will be killed.


Syntax: set::anti-flood::unknown-flood-bantime <timevalue>

Specifies for how long an unknown connection flooder is banned (see also previous item).


This configures the maximum number of conversations a user can have with other users at the same time. This is a protection measure against spambots who tend to mass /MSG or /INVITE many different users within a short period of time.

set {
    anti-flood {
        max-concurrent-conversations {
            users 10; /* should be between 1 and 20 */
            new-user-every 15s; /* should be between 1 and 120 */

A user may message up to set::anti-flood::max-concurrent-conversations::users different users without any problem. If he/she then messages another user this is only permitted at a rate of 1 every set::anti-flood::max-concurrent-conversations::new-user-every seconds.

For example, with a users set to 10 and new-user-every set to 15:

  • UnrealIRCd will remember up to 10 users that the user is messaging
  • The user can /MSG the first 10 users without any problem (eg: k1, k2, k3, k4, k5, k6, k7, k8, k9, k10)
  • When trying to send a message to the 11th user (eg: k11) the user will have to wait up to 15 seconds before (s)he can do.
  • Then the user can message the 11th user (k11)
  • If the user then wants to send a message to a 12th user (k12, or even user k1 again which has by now dropped of the active 10 users list) then (s)he has to wait 15 seconds again

Since most users don't actively message many different users within a short period of time, this can be used as a way to detect bots/drones that flood users. The goal is to set the limit high enough for normal users to never experience this limit, yet low enough to be meaningful as a spambot countermeasure.

Also, note that this setting only affects user to user messaging and not messages to channels. This is because it is assumed that channel flood controls can take care of channel flooding.

The default setting is as follows:

Version users new-user-every
UnrealIRCd 3.2.x - 4.2.1 20 15 seconds
UnrealIRCd 4.2.2 - now 10 15 seconds

Syntax: set::default-bantime

Default bantime when doing /KLINE, /GLINE, /ZLINE, GZLINE, /SHUN, etc without a time parameter (like /GLINE *@some.nasty.isp), the default is permanent (0). Example: default-bantime 90d


Syntax: set::modef-default-unsettime <value>

For channelmode +f you can specify a default unsettime, if you specify 10 for example then a /MODE #chan +f [5j]:15 will be transformed to [5j#i10]:15. The default is no default unsettime.


Syntax: set::modef-max-unsettime <value>

The maximum amount of minutes for a mode +f unsettime (in +f [5j#i


Syntax: set::modef-boot-delay

Ignore join flood controls in channel mode +f when the server has just been rebooted. This because users are likely to quickly reconnect in such a case, causing a lot of joins which normally trigger +f, causing channels to end up being +i or +R even if there was no true attack (just a server restart).

The default setting is 75 seconds. You can specify an alternative time in seconds (eg: 120), or by timespec (eg: 2m).

For this setting to work correctly, all your servers need to be on UnrealIRCd 4.2.3 or later. Also, it does not take into account users reconnecting to another server in the network if a server dies or is restarted, as is frequently seen in the case of DNS RR. But at least it partially mitigates the server reboot effect.

The downside of this setting is that if a server is restarted in the middle of a drone attack, then when it is booted up again, drones would be able to bypass limits for the specified amount of time. One needs to weigh this against the false positives in channel mode +f that are otherwise caused by server restarts (eg: channels ending up +i due to +f, only because a server has been restarted during scheduled maintenance).


Syntax: set::ban-version-tkl-time <value>

If you specify an 'action' like zline/gline/etc in a Ban version block, then you can specify here how long the IP should be banned, the default is 86400 (1 day).


Syntax: set::spamfilter::ban-time <value>

Same as above but for *lines/shuns added by spamfilter


Syntax: set::spamfilter::ban-reason <reason>

Default reason to use for entries added by spamfilter


Syntax: set::spamfilter::virus-help-channel <channel>

The channel to use for the 'viruschan' action in spamfilter


Syntax: set::spamfilter::virus-help-channel-deny <yes|no>

If set to yes (or '1') it replies 'invite only' to any normal users that try to join the virus-help-channel. Only opers, people that match spamfilters and people that are /invite'd can join.


Syntax: set::spamfilter::except <target(s)>

These targets are exempt from spam filtering (no action will be taken), can be single target or comma separated list.. Ex: except "#help,#spamreport"


Syntax: set::spamfilter::detect-slow-warn <value>

If a spamfilter takes longer than this amount of milliseconds to execute (1000ms = 1 second), then a warning notice will be sent to all opers (default: 250). See also Spamfilter#Slow Spamfilter Detection


Syntax: set::spamfilter::detect-slow-fatal <value>

If a spamfilter takes longer than this amount of milliseconds to execute (1000ms = 1 second), then the spamfilter will be removed (default: 500). See also Spamfilter#Slow Spamfilter Detection


Syntax: set::check-target-nick-bans <yes|no>

Whenever the user changes his/her nick, check if the NEW nick would be banned. If so, do not allow the nickchange. Default is yes.


Syntax: set::timesynch::enabled <yes|no>

Enable or disable time synchronization on-boot. Default is yes.


Syntax: set::timesynch::server <IP>

Server(s) to synchronize time with. This can be up to 4 IP's separated by comma's. The servers must support NTP protocol version 4. The default is to use 3 time servers (US, EU, AU). Requests to these servers are sent in parallel, fastest reply wins.


Syntax: set::timesynch::timeout

Maximum time to wait for a time server reply. This is a value between 1 and 5, more is not possible because it causes too much inaccuracy. This setting is 3 by default and there's probably no good reason to change it.


Syntax: set::ping-cookie <yes|no>

When a client connects, send a "ping cookie" consisting of a random string that the client should respond with. All clients should cope with this and do so without bothering the user. Ping cookies are a security measure. It helps in preventing blind HTTP-POST attacks and similar security issues. It also helps against TCP spoofing on very old operating systems.

The default is yes (enabled).


Syntax: set::watch-away-notification <yes|no>

Allows you to enable/disable AWAY notification in WATCH. The default is yes (enabled).


This limits the number of targets in a command. For example for PRIVMSG it defaults to 4, which means you can address up to 4 targets via /MSG nick1,nick2,nick3,nick4 hello.

The following are the defaults:

set {
    max-targets-per-command {
        privmsg 4;
        notice 1;
        names 1;
        whois 1;
        whowas 1;
        kick 4;
        list max;
        join max;
        part max;
        sajoin max;
        sapart max;
        kill max;
        dccallow max;
        userhost max;
        userip max;
        ison max;
        watch max;

If you are tweaking the settings you should note that:

  • The commands NAMES and WHOWAS do not support more than 1
  • The setting for the commands USERHOST USERIP ISON WATCH can not be lowered
  • Other than the above there is no checking if the command exists or if the command itself allows multiple targets in the first place

Syntax: set::hide-ban-reason <yes|no>

This will hide the *LINE reason to anyone except the user being killed. This allows you to enter a personal message in commands like /GLINE that will not be publicly displayed.


This module can automatically kill users that seem to have "random looking nicks".

Note that you need to load this module explicitly (it is not loaded by default):

loadmodule "antirandom";

set {
        antirandom {
                /* THRESHOLD:
                 * This is pretty much the most important setting of all.
                 * For every randomly looking ident the user gets a certain amount of
                 * 'points', if this value reaches 'threshold' then the appropriate
                 * action is taken (killed, *lined, see later on).
                 *  lower = more randomly looking users will be catched (but also more
                 *          innocent users)
                 * higher = less chance of innocent users getting killed, but also less
                 *          chance on bots getting catched.
                 * <2:  DON'T!!
                 *  4:  Works good, probably a few more innocent kills but if you got
                 *      quite a bot problem then this might be a useful setting.
                 *  5:  Works well with few innocent kills, probably good to begin with.
                 *  6:  If you want to be a tad more careful
                 * >6:  For the paranoid. Module can still be quite effective, though :)
                threshold 5;

                 * Action to take whenever the user is catched as random, options:
                 * warn, kill, gline, gzline, kline, zline, shun, tempshun
                ban-action kill;

                 * Time to ban the user (irrelevant for tempshun/kill).
                 * Something between 1 hour and 2 days is recommended.
                 * If you set it higher than 3 or 4 days then you get quite a risk
                 * of catching innocent users due to dynamic IP, not to mention
                 * your *line list gets filled up... so choose it wisely.
                ban-time 4h;

                 * The ban (or kill) reason to use.
                 * You might want to put in an entry to a FAQ or an email address
                 * where users can mail if they have been catched and don't know what to do.
                 * NOTE: One of the various reasons that ""innocent users"" are catched is
                 *       if they just randomly type in info for their nick, ident, or realname.
                ban-reason "You look like a bot. Be sure to fill in your nick/ident/realname properly.";

                 * Convert nicks, idents, and realnames to lowercase before doing random checks?
                 * This has not been tested extensively for false positives, but might be (very)
                 * helpful to catch GnStA5FYhiTH51TUkf style random nicks as random.
                 * Enabled by default.
                convert-to-lowercase yes;

                 * If enabled, then upon loading it will check all users that are currently
                 * connected and give a status report about who it would have killed.
                 * Note that it doesn't actually kill any currently connected users, it is for
                 * informative purposes only.
                 * This can be (very) useful if you use the module for the first time.
                 * But you probably want to disable it after a while, since once the module
                 * is actively dealing with randomly looking persons, it shouldn't report any
                 * users anymore on load and then this check only eats useless CPU on /REHASH.
                 * Enabled by default.
                fullstatus-on-load yes;

                 * This will send out a notice whenever a randomly looking user has been catched
                 * during connecting. Obviously this can be pretty noisy.
                 * Especially recommended to enable during the first few days you use this module.
                show-failedconnects yes;

                 * Hostmasks on this list are matched against the IP and hostname of the connecting
                 * user. If it matches then we do not check if the nick/ident/realname is random.
                 * NOTE: Use the REAL host or IP here, not any cloaked hosts!
                except-hosts {
                        mask "*.trusted.yy";
                        mask "192.168.*";

This allows you to specify which channels should be hidden from list. Right now it only supports one option: deny-channel. This will hide channels that the user cannot join due to deny channel { } restrictions:

set { hide-list { deny-channel; }; };

Note that secret channels (channel mode +s) are always hidden and IRCOps always override restrictions (if they have sufficient access).


UnrealIRCd limits the number of connections per IP that are in an "unknown" state, that is: connections that are in a handshake. This is a security setting and it defaults to 3.

Only in very rare circumstances this may need to be adjusted. For example if you have hundreds of users coming from the same IP.

Example: set { max-unknown-connections-per-ip 3; };


By default UnrealIRCd will place bans from spamfilter (and other automatic bans) on *@ip. You can change this to have bans placed on [email protected] This can be useful if you have some unusual amount of trust in idents ;). Note that this doesn't help against zlines/gzlines since ident requests and handshakes (including receiving the username) don't take place for (G)ZLINE's.

Example (this is the default setting): set { ban-include-username no; };


Syntax: set { handshake-delay 2; };

This defines the MINIMUM time it should take for a user to get connected (finish the initial handshake).

This can be useful if you have blacklist blocks so DNSBL checking can finish before allowing the user in.

The default is 2 seconds if you have any blacklist { } block. You could set it slightly higher if your DNSBL checking is slow but for most people the default should be perfectly fine. Values of 10 or more are not permitted.

If you don't have any blacklist { } blocks then the delay defaults to 0 seconds (no delay) since it would not be useful.


This allows you to change the messages that are sent to a user when their connection is rejected. This shows the defaults:

set {
   reject-message {
        password-mismatch "Password mismatch";
        too-many-connections "Too many connections from your IP";
        server-full "This server is full.";
        unauthorized "You are not authorized to connect to this server";
        kline "You are not welcome on this server. $bantype: $banreason. Email $klineaddr for more information.";
        gline "You are not welcome on this network. $bantype: $banreason. Email $glineaddr for more information.";

The set::reject-message::kline message is sent to the user when disconnecting them due to a KLINE or ZLINE. The set::reject-message::gline message is sent to the user upon GLINE or GZLINE. The message is only sent to the affected user and is not seen by other users or IRCOps. In both of these configuration items (::kline and ::gline) the following variables are available:

Variable Description Example
$bantype type of the ban (past tense) K-lined
$banreason reason of the ban (*LINE reason) Stop spamming users
$klineaddr set::kline-address [email protected]
$glineaddr set::gline-address (or, if not set, then set::kline-address) [email protected]
$ip IP address of the user

The antimixedutf8 module will detect and stop spam containing of characters of mixed "scripts", where (for example) some characters are in Latin script and other characters are in Cyrillic script.

Note that you need to load this module explicitly (it is not loaded by default).

loadmodule "antimixedutf8";
set {
        antimixedutf8 {
                /* Take action at this 'score'.
                 * 10 is a good and safe default.
                score 10;

/* Action to take, see:
                ban-action block;

/* Block/kill/ban reason (sent to user) */
                ban-reason "Possible mixed character spam";

/* Duration of ban (does not apply to block/kill) */
                ban-time 4h; // For other types

This adds support for an authentication prompt if you have a soft ban or require authentication { } block matching the user. It asks the user to authenticate via /AUTH user:pass. It does this by simulating a SASL session to Services.

loadmodule "authprompt";
set {
        authentication-prompt {
                /* Enabled or not? */
                enabled yes;

message "The server requires clients from this IP address to authenticate with a registered nickname and password.";
                message "Please reconnect using SASL, or authenticate now by typing: /QUOTE AUTH nick:password";
                /* As you can see you can have multiple 'message' items.
                 * It may be useful to refer to a webpage for more
                 * information and/or where users can register their nick.

fail-message "Authentication failed";
                /* Multiple fail-message lines are also supported */
// If you use the authprompt module then you may want to raise the
// timeout in which users must complete the handshake.
// By uncommenting the following, you can raise it from 30 to 60 seconds:
// set { handshake-timeout 60s; };

The set::connthrottle settings are documented at the Connthrottle page.


Syntax: set::broadcast-channel-messages [auto|always|never]
Important: this setting only exists in UnrealIRCd 5

Up to UnrealIRCd 4, channel messages were only sent to other servers if there is at least 1 user in that channel on that server (or on a server behind it). This was done to reduce needless server to server traffic. However, with channel history (channel mode +H) this is no longer a good idea as it would mean channel history is not recorded on those servers with no channel members.

In UnrealIRCd 5 we now have 3 options:

  • always: always send all channel messages to all servers, regardless of whether they have channel members or not.
  • auto (the default): don't send messages to servers if they have no channel members, except for when the channel mode +H (history) is set. In case of +H we broadcast all messages to all servers.
  • never: never broadcast channel messages to all servers, only send to servers that have channel members.

The set::history::channel::playback-on-join block describes the behavior when a user joins a +H channel. The set::history::channel::max-storage-per-channel block sets limits on what can be set via /MODE #chan +H. Note that these are separate things, as many more history lines can be fetched (in the future) than only the few lines that you see on-join.

Important: this setting (and history playback in general) only exists in UnrealIRCd 5.

This shows the default settings:

set {
        history {
                channel {
                        /* How many lines to playback on join? */
                        playback-on-join {
                                lines 15;
                                time 1d;
                        /* How much history to keep. These are the
                         * upper maximums for channel mode +H lines:time
                        max-storage-per-channel {
                                lines 5000;
                                time 1w;

Syntax: set::part-instead-of-quit-on-comment-change [yes|no]
Important: this setting only exists in UnrealIRCd 5

When a QUIT message is changed due to channel restrictions, such as stripping color or censoring a word, we normally change the QUIT message. This has an effect on ALL channels, not just the one that imposed the restrictions (eg: the QUIT reason loses color or is censored for all). We feel this is the best tradeoff and this is the default setting of no.

You can also set this setting to yes. That will change the QUIT into a PART when the QUIT comment is changed. The channel(s) with the changed comment see the user PARTing, and on all other channels that do not have the restrictions (eg: are -S and -G) they will see the user QUITting with the original message.


Syntax: set::webredir::url ""
Important: this setting only exists in UnrealIRCd 5

When someone (accidentally) types in their web browser then UnrealIRCd can send a HTTP redirect back to, say, Note that this is mostly a gimmick rather than something terribly useful.

For this to work, the IRC server needs to listen on ports 443 and 80 (more information about that here!). However, nowadays more and more IRC servers listen on port 443 so users can bypass firewall restrictions that they may encounter on the regular ports 6667/6697 (and also because of websockets).

Usage example (only do this after reading the above):

loadmodule "webredir";
set { webredir { url "https://..."; } }