Ergo IRC Guide

Introduction

This is a guide to IRC, known in full as the Internet Relay Chat. IRC predates the World Wide Web and has been around since 1988, making it one of the oldest chat protocols still in use today. For this guide I am exploring the Ergo IRC server (also called an IRC daemon or IRCd), for the Dell-shaped prison I call Windows 11.

This page serves as my personal guide for all things IRC, as well as for any of you who want to join me.

IRC Basics

IRC is a protocol, in the way e-mail is. An individual IRC server comprises a daemon and several administrative YAML files that dictate its name, password, operator credentials and connection rules. It behaves like the house of the chatroom, while the IRC client functions as the key. Without a client, you cannot enter an IRC server. Once inside, a user can join channels, use commands and converse freely with the other denizens. This procedure is simple, perhaps jarringly so to more contemporary netizens, but it remains stalwart in a period of rapid monetisation and governmental pressures.

Part 1: Setting the Scene

Step 1: Downloading your Daemon

  1. Go to: https://github.com/ergochat/ergo/releases/latest
    Under "Assets", download the Windows build. It will be named something like: ergo-2.17.0-windows-x86_64.zip

  2. Extract the ZIP into your folder of choice.

  3. Ergo ships with a default config called default.yaml. A YAML file is an easy-to-read configuration format used in various programs. You need to copy this file and name it ircd.yaml. Leave default.yaml alone, it is there as a guide in case you get stuck with the formatting. YAML files can be quite picky; even one mis-spacing is enough to throw things off.

  1. Enter Windows PowerShell to generate your TLS certificates. Your server needs valid certificates to run, but especially if you want to make it go online. Ergo lets you generate self-signed certificates (from here we will call them certs), which you will need to do in the terminal.

  2. Type this exact command into the terminal: ./ergo.exe mkcerts
    You should now see privkey and fullchain pop up in your Ergo folder. These are PEM files, and your main two certs. You cannot have one without the other, they must be together.

You have now created the bare bones of an IRC server. The certs you just generated will be used by the TLS listeners on ports 6667 and 6697. Port 6667 serves plaintext, which is usable but not recommended for private communications. For an encrypted chat, use port 6697. If you try to connect anything to anything right now, you will not get a peep.

Part 2: Establishing the Server

Step 1: Creating an Operator Account

  1. Open PowerShell in your Ergo folder and run: ./ergo.exe genpasswd

  2. It will ask you to create a password, which it will then ask you to confirm. Both entries must match, though this is complicated by the fact that terminals do not show passwords. Make sure it is strong, but not too much of a pain to type.

  3. Once you have confirmed your password, you will be given a long hash starting with $2a$. Hold onto this hash and treat it like you would any other password.

  4. Open your ircd.yaml file in your plaintext editor of choice, preferably Notepad.

  5. Using your program's find-tools, look for the opers block. The oper is named "admin" by default. Find the line: password: "PASTE_YOUR_HASH_HERE"

  6. Replace PASTE_YOUR_HASH_HERE with the hash you just generated, keeping the quotes.

You now have a password for your IRC server. You can change it any time by repeating the process above.

Step 2: Changing the Listeners

  1. Using the find-tool in your program, find the listeners section. In it you should find these two lines around line 43:

    "127.0.0.1:6667":
    "[::1]:6667":
  2. Comment out those two lines by putting a # in front of them. This symbol turns a line into a comment that will not execute as code. Make sure the spacing lines up evenly. Doing this disables the localhost-only listeners so the LAN-wide listener can accept connections from other machines on your network.

  3. Check that it looks exactly like this. The third line (":6667":) should already exist, you are just making sure the two lines above it are commented out:

    # "127.0.0.1:6667":
    # "[::1]:6667":
    ":6667":

Troubleshooting: if Ergo starts but you can only connect from the same machine, double-check the spacing here. YAML is whitespace-sensitive and mismatched indentation will cause the parser to choke silently.

Step 3: Changing the Firewalls

  1. Open PowerShell as Administrator, otherwise it will not let you do this step.

  2. Copy-paste these commands into the terminal:

    New-NetFirewallRule -DisplayName "IRC 6667"
      -Direction Inbound -Protocol TCP
      -LocalPort 6667 -Action Allow
      -Profile Any -Enabled True
    
    New-NetFirewallRule -DisplayName "IRC 6697"
      -Direction Inbound -Protocol TCP
      -LocalPort 6697 -Action Allow
      -Profile Any -Enabled True
  3. Set your Wi-Fi network to Private by running:

    Set-NetConnectionProfile
      -InterfaceAlias "Wi-Fi"
      -NetworkCategory Private

    This is important: if Windows thinks you are on a Public network, it will block incoming connections even with firewall rules in place.

  4. To check your network's firewall profile, run: Get-NetConnectionProfile

Troubleshooting: if the firewall commands fail, make sure you opened PowerShell as Administrator (right-click, Run as Administrator). If the network profile command errors out, your adapter name may differ. Run Get-NetAdapter to see the exact name and substitute it for "Wi-Fi".

Your home network should now know your server exists. If you are running a chatroom with family or roommates, you can theoretically stop here, though you still have to test it, and you will likely want to make it go online too.

Part 3: Testing the Server

To use an IRC server, you need a client. This guide will be using HexChat, a free and widely-used IRC client for Windows. Note that HexChat is no longer actively maintained, but it is perfectly safe and has plenty of forks. If you would rather use a different client, the general steps are roughly the same.

Step 1: Installing HexChat

  1. Download HexChat from https://hexchat.github.io and run the installer. The defaults are fine.

  2. On every launch, HexChat will show a Network List. Fill in a nickname at the top, then click Add to create a new network entry. Name it whatever you like, e.g. My IRC Server.

  3. Click Edit on your new network.

  4. Under the Servers tab, remove the placeholder entry and add your server address. Since you are only connecting locally for now, use your machine's local IP followed by port 6697. If you do not know your IP address, run ipconfig in PowerShell and look for the IPv4 Address in the Wi-Fi section.

  1. Tick "Use SSL for all the servers on this network" if you are using port 6697. Since you are using a self-signed cert for now, also tick "Accept invalid SSL certificates". You can untick this once you have a real cert from WinACME later.

  2. Click Close to exit the Edit window.

Step 2: Entering your Server

  1. If your server is not running, open the terminal from your Ergo folder and run: ./ergo.exe run. Closing this window stops the server.

  2. You should see lines like the following appear:

    now listening on :6667, tls=false
    now listening on :6697, tls=true
    Server running
  3. In a second PowerShell window, run: netstat -an | findstr 6667

  4. You should see 0.0.0.0:6667, which means it is reachable from other computers. If you only see 127.0.0.1:6667, the YAML change in Step 2 of Part 2 did not take effect.

Troubleshooting: if you see nothing at all, Ergo likely did not start properly. The most common cause is a YAML formatting mistake, wrong indentation, or tabs instead of spaces.

Step 3: Connecting with HexChat

  1. With Ergo running, go back to HexChat and click Connect. You will be met with Ergo's default Message-Of-The-Day and the chat interface itself.

  2. Type /join #general (or any channel name you like) in the text box and press Enter. If the channel does not exist yet, Ergo will create it on the spot.

  3. You can join multiple channels at once, just repeat the /join command. Each channel will open as a new tab in HexChat, just like a web browser.

Your server is now working on a basic LAN connection. Anyone on your local network can connect the same way you just did. If you are only using IRC for immediate friends, family or roommates, you can theoretically stop here. However, you will not be able to connect your server to any web-based clients, which we will be going over in Part 4.

Part 4: Getting Your Server Online

To get your server online, you will need a stable domain, two authentic TLS certs, several opened ports in your router, and a slight addition to your YAML file. While there are a lot of moving pieces, it means you own your server fully, without relying on third-party services such as VPS providers.

You may not be able to proceed with the free method if:

  1. Your ISP does not support inbound connections. Some ISPs use CGNAT (Carrier-Grade NAT), which means multiple households share one public IP. This renders port-forwarding impossible.

  2. Your ISP blocks port 80, which you will need for generating your HTTPS certs.

Assuming you have not had either of these issues, you can proceed onto the rest of this section without any problems.

Step 1: Setting up No-IP Dynamic DNS

This gives your server a stable hostname (e.g. yourserver.ddns.net) regardless of changes your home IP address might experience. WinACME needs this hostname to issue a real TLS certificate, and your web client uses it to connect.

  1. Go to https://www.noip.com and sign up for a free account. Once logged in, go to Dynamic DNS, No-IP Hostnames and create a new hostname such as yourserver.ddns.net. Write this down and treat it like a password.

  2. Download the No-IP DUC (Dynamic Update Client) from https://www.noip.com/download?page=win. This is a small background app that watches your public IP address and automatically updates No-IP whenever it changes. Without it, your hostname will point to the wrong IP after a router restart.

  1. Install the DUC, log in with your No-IP account credentials, and make sure your hostname is ticked. Set it to run on startup so it is always active in the background.

  2. Once the DUC is running, verify everything is working by looking up your hostname at https://www.nslookup.io. The A record should match your current public IP, which you can check at https://www.whatismyip.com.

Note: No-IP's free tier requires you to confirm your hostname every 30 days, or they will delete it. Keep an eye on your inbox for their reminder emails.

Step 2: Generating Certificates with WinACME

Self-signed certs from mkcerts work for HexChat on your LAN, but browsers will outright refuse a WebSocket connection to a self-signed cert. To use Kiwi IRC from the internet you need a real, trusted certificate. This is where WinACME comes in, it gets you a free Let's Encrypt certificate to go with your No-IP hostname.

Before you start: make sure Ergo is not running, port 80 is forwarded on your router, and opened in your firewall. Opening port 80 is a temporary measure, WinACME needs to answer a challenge on this port to prove you control the domain.

  1. Download WinACME from https://www.win-acme.com. Extract the ZIP somewhere convenient, e.g. C:\Users\YourName\Downloads\win-acme\

  2. Open PowerShell as Administrator in the WinACME folder and run: ./wacs.exe

You will be walked through an interactive menu. Here is what to pick at each step:

  • Choose "Create certificate (full options)", not the simple IIS option.
  • For source, pick "Manual input" and enter your No-IP hostname, e.g. yourserver.ddns.net
  • For validation, pick "Self-hosted (HTTP-01)". WinACME will spin up a tiny temporary HTTP server on port 80 so Let's Encrypt can confirm you control the hostname.
  • Leave the private key type as the default (RSA).
  • For storage, pick "PEM encoded files". This gives you separate .pem files that Ergo can read. Choose a folder to save them to, e.g. C:\Users\YourName\Downloads\Ergo\certs\
  • Accept the defaults for any remaining prompts and proceed.
  1. If everything executed correctly, WinACME will save PEM files to your chosen folder. Look for files ending in -chain.pem and -key.pem.

  2. Open ircd.yaml and update the cert paths in two places, the 6697 TLS listener and the 8097 WebSocket listener. Make sure both point to the same folder:

    ":6697":
      tls:
        cert: C:\...\certs\yourserver-chain.pem
        key:  C:\...\certs\yourserver-key.pem
    ":8097":
      tls:
        cert: C:\...\certs\yourserver-chain.pem
        key:  C:\...\certs\yourserver-key.pem
      websocket: true
  1. Start Ergo again with ./ergo.exe run. The TLS warning in HexChat should now be gone on port 6697, and Kiwi IRC will be able to connect on port 8097.

Note on renewal: Let's Encrypt certs expire after 90 days. WinACME installs a scheduled task to auto-renew them, so you should not need to do anything manually. If renewal fails (e.g. port 80 is not forwarded), WinACME will send a reminder email to the address you registered with.

Step 3: Port Forwarding on your Router

For anyone outside your home network to reach your server, your router needs to forward the right ports to your machine.

  1. Find your router's admin page. Usually this involves entering a specific IP address into your browser, though this may vary between ISPs.

  2. Log in with your router's admin credentials. These should be visible on the back of the router alongside your Wi-Fi password.

  3. Find your PC's local IP by running ipconfig and looking for the IPv4 Address in the Wi-Fi section, something like 192.168.1.XXX. It is worth assigning this as a static IP in your router's DHCP settings (look for "DHCP reservation" or "static lease") so it never changes and breaks your forwarding rules.

  1. In your router's port forwarding section (often under Advanced, Port Forwarding, or NAT / Virtual Servers), add the following rules pointing to your laptop's local IP:

    TCP  6667 → 6667   Plain IRC
    TCP  6697 → 6697   TLS IRC (HexChat with SSL)
    TCP  8097 → 8097   WSS WebSocket (Kiwi IRC)
    TCP  80   → 80     HTTP (WinACME cert verification)
  2. Save the rules. You can test that a port is reachable from outside using https://www.yougetsignal.com/tools/open-ports/, enter your No-IP hostname and port number to confirm it is open.

Note: port 80 only needs to be forwarded while running WinACME to issue or renew your certificate. You can remove it afterwards if you prefer.

Step 4: Connecting from Kiwi IRC

Kiwi IRC is a browser-based IRC client, no installation needed. It connects to your server over WebSocket Secure (WSS) on port 8097, which is why the real TLS cert from WinACME was necessary.

  1. On any device, open a browser and go to: https://kiwiirc.com/nextclient/

  2. Fill in the connection screen: Server address: yourserver.ddns.net / Port: 8097 / SSL/TLS: ON / Channel: #general / Nick: YourName

  3. Hit Connect. You should see the server welcome message and land in your channel. This works from any network, your phone on mobile data, a friend's house, anywhere, as long as Ergo is running at home.

"Unable to connect": check that Ergo is running and port 8097 is forwarded. "Certificate error": check the cert files still exist and run /rehash. "Connection closed immediately": SSL must be ON for port 8097.

Conclusion

Congratulations, you have just set up an IRC server. Invite your friends, or drag them kicking and screaming.

If your company is hesitant to make the switch, try Kiwi or The Lounge for a modernised IRC experience. IRC is a protocol, there is no one way to run or use it, so it is more about finding what works best for your needs.

If you want to move your server to a Raspberry Pi for permanent self-hosted use, continue to the next section. Running Ergo on a Pi has several benefits; the most apparent is that your server stays online no matter what happens to your main machine. The Pi's small size, low power draw, low cost, and basis in Linux make it ideal for running servers long-term.

Pi-Roject: Ergo IRC (Hello World)

This section covers setting up Hello World, the same Ergo IRC server moved to a Raspberry Pi for permanent self-hosted use. It goes from a bare Pi to a fully working setup: a domain that tracks your home IP, a real TLS certificate, Ergo running as a systemd service, and connections working via both HexChat and KiwiIRC. Written based on the actual setup session, mistakes and all.

This is not a beginner guide, it assumes you have already got your Pi set up and can SSH into it comfortably.

Overview

Ergo IRC: version ergo-2.14.0-linux-arm64, running on the Pi.

No-IP DUC: keeps helloworld.ddns.net pointed at your home IP. Lives on the Pi as a systemd service.

Win-ACME: stays on Windows. Handles TLS cert renewal via Let's Encrypt, then copies the renewed certs to the Pi automatically via a batch script.

HexChat: desktop client, port 6697 (TLS). KiwiIRC: browser client, port 8097 (WebSocket over TLS).

Step 1: SSH into the Pi

From your Windows terminal (VPN off):

ssh ircuser@192.168.1.XXX

Step 2: No-IP DUC on the Pi

This keeps your domain pointing at your home IP automatically. If you have previously been running the No-IP client on Windows, this replaces it.

cd /tmp
wget https://www.noip.com/client/linux/noip-duc-linux.tar.gz
tar xzf noip-duc-linux.tar.gz
cd noip-2.1.9-1
sudo make install

Follow the prompts: enter your email and password, select your hostname group, set the update interval to 30 minutes, and say no to running a script on update.

Create the systemd service file:

sudo nano /etc/systemd/system/noip2.service

Paste in:

[Unit]
Description=No-IP Dynamic DNS Update Client
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/noip2
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable noip2
sudo systemctl start noip2
sudo systemctl status noip2

You should see active (running) and enabled.

Step 3: TLS Certificates (Win-ACME on Windows)

Let's Encrypt certificates are what make TLS connections to the server trustworthy. Win-ACME handles obtaining and automatically renewing them, but there is a catch worth knowing about.

Why cert renewal runs on Windows, not the Pi: When Win-ACME verifies your domain, Let's Encrypt contacts your external IP on port 80. On a UK residential connection, ISPs commonly block inbound port 80. Port 443 and higher ports like 6697 are usually fine. Since Win-ACME was already set up on Windows and working there, the simplest fix is to keep it there and automate pushing the renewed certs to the Pi.

Important: The router rule for port 80 must point to your Windows machine, not the Pi. Check this before the next renewal date.

Setting Up Passwordless SSH (Windows to Pi)

This is needed so the cert copy script can run without a password prompt. Run on Windows as Administrator:

ssh-keygen -t rsa -b 4096
(hit Enter through all prompts, no passphrase)
type C:\Users\black\.ssh\id_rsa.pub | ssh ircuser@192.168.1.XXX "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Enter the Pi password when prompted. Test it by running ssh ircuser@192.168.1.XXX, it should connect with no password.

The Cert Copy Script

Create this file at C:\Users\black\Documents\copy-certs-to-pi.bat:

@echo off
scp C:\...\helloworld.ddns.net-chain.pem ircuser@192.168.1.XXX:/home/ircuser/ergo/certs/fullchain.pem
scp C:\...\helloworld.ddns.net-key.pem ircuser@192.168.1.XXX:/home/ircuser/ergo/certs/privkey.pem
ssh ircuser@192.168.1.XXX "sudo systemctl restart ergo"

This copies the renewed certs to the Pi and restarts Ergo so it picks them up. Add this as a post-renewal installation step in Win-ACME so it runs automatically after every renewal.

Step 4: Create the Ergo systemd Service File

On the Pi:

sudo nano /etc/systemd/system/ergo.service

Paste in:

[Unit]
Description=Ergo IRC Server
After=network.target

[Service]
Type=simple
User=ircuser
WorkingDirectory=/home/ircuser/ergo/ergo-2.14.0-linux-arm64
ExecStart=/home/ircuser/ergo/ergo-2.14.0-linux-arm64/ergo run --conf /home/ircuser/ergo/ergo-2.14.0-linux-arm64/ircd.yaml
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Note the --conf flag on the ExecStart line. Easy to miss, and Ergo will fail silently without it. Save with Ctrl+O, Enter, Ctrl+X. The asterisk (*) in nano's title bar means you have unsaved changes, make sure it is gone before you exit.

Step 5: Enable and Start Ergo

sudo systemctl daemon-reload
sudo systemctl enable ergo
sudo systemctl start ergo
sudo systemctl status ergo

You are looking for active (running) in the status output, along with log lines like info : server : Server running. If something goes wrong:

journalctl -u ergo -f

Step 6: Disable Plaintext (TLS Only)

When Ergo first starts, it warns that port 6667 (plaintext IRC) is active. Since we want TLS-only connections, this needs to be commented out.

nano /home/ircuser/ergo/ergo-2.14.0-linux-arm64/ircd.yaml

Find the listeners section and add a # at the very start of the ":6667": line, before the quote mark. Nano may highlight it differently, only an actual # at the start of the line counts:

Wrong:  ":6667":
Right: #":6667":

Save, then restart Ergo:

sudo systemctl restart ergo

Verify port 6667 is no longer listening (this should return nothing):

ss -tlnp | grep 6667

Check the cert expiry while you are at it:

openssl x509 -in /home/ircuser/ergo/certs/fullchain.pem -noout -dates

Step 7: Port Forwarding on the Router

External connections will not work unless the right ports are forwarded to the Pi. The router admin page is usually at 192.168.1.XXX for a BT Home Hub.

Port 6697, Pi
TLS IRC connections (HexChat and other desktop clients).
Port 8097, Pi
WebSocket TLS connections (KiwiIRC and other browser clients).
Port 80, Windows machine
Used by Win-ACME for Let's Encrypt domain verification. Must not point to the Pi.

A common mistake is having 6697 and 8097 pointing at the wrong machine. If external connections are not working, check these rules first.

Step 8: Connect with HexChat

  1. HexChat menu, Network List (or Ctrl+S)
  2. Click Add, name it "Hello World"
  3. Add server: helloworld.ddns.net/6697 (or 192.168.1.XXX/6697 for LAN only)
  4. Tick Use SSL for all the servers on this network
  5. Tick Accept invalid SSL certificates
  6. Click Connect

If you get "Disconnected (Remote host closed socket)", SSL was almost certainly not ticked. The server only accepts TLS, an unencrypted connection gets immediately rejected.

Step 9: Connect with KiwiIRC

  1. Go to kiwiirc.com/nextclient/
  2. Set Server: helloworld.ddns.net
  3. Set Port: 8097
  4. Scroll down to Advanced
  5. Tick Direct websocket
  6. Set the websocket URL to: wss://helloworld.ddns.net:8097/
  7. Click Network

Two things to watch out for. First, the direct websocket field defaults to ws:// (unencrypted), it must be wss://. Second, if it still will not connect, diagnose with:

curl -v https://helloworld.ddns.net:8097 2>&1 | head -30

A timeout here usually means port 8097 is not being forwarded through the router. Fix the port forwarding rule and it will connect immediately.

Quick Reference

Check if Ergo is running
sudo systemctl status ergo

Start / Stop / Restart Ergo
sudo systemctl start ergo
sudo systemctl stop ergo
sudo systemctl restart ergo

View live Ergo logs
journalctl -u ergo -f

Check which ports are listening
ss -tlnp | grep ergo

Edit Ergo config
nano /home/ircuser/ergo/ergo-2.14.0-linux-arm64/ircd.yaml

After editing the service file, always run
sudo systemctl daemon-reload

Check cert expiry on Pi
openssl x509 -in /home/ircuser/ergo/certs/fullchain.pem -noout -dates

Check if No-IP is running
sudo systemctl status noip2

Manually copy certs from Windows
C:\Users\black\Documents\copy-certs-to-pi.bat

Prerequisites

This guide assumes you either own or use an IRC server, particularly one hosted on a Raspberry Pi or other SBC. If this is not the case, please read the Ergo guide to familiarise yourself with the protocol. This guide also assumes you are familiar with OPSEC practices, but want more than hardened Firefox forks and a healthy distrust of strangers. If you need a basic introduction to OPSEC, please read from the following:

EFF's Surveillance Self-Defense: https://ssd.eff.org/

Privacy Guides: https://www.privacyguides.org/en/basics/threat-modeling/

Freedom of the Press Foundation: https://freedom.press/digisec/

Introduction

In stark contrast to other means of online chat, IRC (Internet Relay Chat) is a protocol, not a product. Control starts and ends with the individual operators, who have sole responsibility over their data. Meanwhile, their chatters are responsible for their own interests, and there is no third party that can intervene in this process.

On mainstream chat platforms, a third party dictates the entire process. The corporate entities that own these programs put themselves between the operator and chatter relationship and demand both parties work by its inefficiencies. They track users with data-retention policies, game-ify their chatting experience with monetisation, and if prompted, will drop these users into the awaiting hands of the law. This is not free communication, this is a system that glorifies convenience and enforces learned helplessness.

IRC has no central authority, no single server that handles everyone's traffic. It is an open-standard protocol, freer than e-mail, which itself strains under legal pressure no matter how many privacy features are implemented.

ProtonMail is the best-known example. In 2021 it handed over the IP address and device information of a French climate activist to law enforcement. French police sent the request to Swiss authorities via Europol; Swiss authorities forwarded a legally binding order to Proton; and Proton complied. In their own blog post, Proton's CEO stated plainly: "There was no legal possibility to resist or fight this particular request." Resisting such requests is actually illegal for a company like ProtonMail to do. The privacy policy was updated shortly after as a reminder. If you break Swiss law, ProtonMail can be legally compelled to log your IP address as part of a Swiss criminal investigation.

For mainstream providers like Gmail and Outlook, the situation is more straightforward. Both publicise tens of thousands of government requests per year, under legal frameworks that compel disclosure of metadata by subpoena and message content by warrant. Email also has fundamental architectural problems besides legal cooperation: when you send an e-mail, your message travels through multiple servers, commonly in plaintext form.

Mullvad VPN's encounter with legalities makes the same point from an opposite direction. In April 2023, six members of Sweden's National Operations Department arrived at Mullvad's Gothenburg office with a search warrant and left empty-handed. In Mullvad's own blog post: "In line with our policies such customer data did not exist." This is the crux of the argument: if you have nothing in your server, you have nothing to lose.

As a result, the threat profile of IRC is fundamentally different. The question is not "do you trust this corporation, its lawyers, investors or their capacity to act in your interest." It becomes "do you trust the person running the server?" On a well-configured self-hosted server, that person is you or a close friend. The security of your communications comes down to individuals, not the trajectory of a graph. That is both the freedom and responsibility IRC gives you. You just have to have the initiative to take that responsibility seriously.

Part 1: Setting the Scene

First comes the matter of encryption. IRC is not encrypted by default, nor does it use E2E encryption, instead using TLS. IP addresses are easy to obtain and backtrace to their origin. Servers are also not password-protected by default, which can leave them open to anyone if left untreated. These problems need to be solved if you are to have private communications.

Step 1: The Privacy Benefits of Self-Hosting

IRC operates on a client-server model: your client connects to a server (called an IRCd), which routes messages between users. By default, all IRC traffic transmits as plaintext unless TLS encryption is manually configured. The operator of a server can read every message that passes through it, the exact times of logins and logouts, and every other action within its confines. Your ISP can also read every message, as can anyone performing a man-in-the-middle attack, and any server in the relay chain.

TLS (Transport Layer Security) encrypts data in transit between two parties. TLS prevents your ISP and passive network eavesdroppers from reading your messages, but does not prevent the server itself from reading them, because the server must decrypt traffic to route it. TLS is transport encryption, not end-to-end encryption. However, this amount of control lends to a user-mandated log policy, the protocol does not get to decide how long messages last, if at all.

Even on a properly TLS-configured server, IRC exposes your IP as part of your "hostmask", the identifier other users see when you connect. One risk remains regardless: Direct Client-to-Client (DCC) file transfers establish a direct connection between two clients, bypassing the server entirely and exposing both parties' real IPs.

What self-hosted IRC protects against: ISP reading your messages (through TLS); government requesting historical logs (partially, more effective against retrospective disclosure than real-time surveillance); IP leaking to other users (partially, via cloaks); third-party traffic correlation.

What it does not protect against: Compromised client devices; live interception; server compromise; social engineering; your ISP observing connection metadata.

Minimum requirements: Access restricted to known users; DCC disabled; logging policy defined; self-hosted on hardware under your physical control; TLS enforced, plaintext disabled; TLS certificate pinned in all clients.

Step 2: Privacy Features in Ergo

Ergo is a modern IRC server daemon written in Go that combines an IRCd, a services framework (NickServ, ChanServ), and a bouncer into a single binary. It supports requiring SASL for all logins, IP cloaking, TLS client certificate authentication, and running as a Tor hidden service.

SASL (Simple Authentication and Security Layer) authenticates to a server as part of the initial connection handshake, before the client is fully registered, more secure than post-connection NickServ identification. SASL EXTERNAL / CertFP authenticates using a TLS client certificate rather than a password, so no password ever transmits over the wire.

For Operators

1. Disable server-side message history. Ergo stores message history in ircd.db by default. Disable it in ircd.yaml:

history:
  enabled: false

If you keep history enabled, set aggressive limits: short retention windows (hours, not days), low message counts. If you have been running Ergo without configuring this, wipe the database.

2. Disable always-on clients. Ergo's always-on feature keeps a user's nick present after they disconnect, causing messages to accumulate in server-side history. For high-privacy setups, disable this by policy.

3. Require SASL and disable self-registration together. Enabling require-sasl without disabling registration means anyone can still self-register and connect. Set both:

accounts:
  require-sasl:
    enabled: true
  registration:
    enabled: false

Create user accounts manually with /msg NickServ SAREGISTER <username> <password> from an oper session.

4. Enable IP cloaking with full privacy settings. Setting num-bits: 0 produces a cloak entirely unrelated to the user's IP, making the original address impossible to recover:

server:
  ip-cloaking:
    enabled: true
    enabled-for-always-on: true
    netname: "irc"
    cidr-len-ipv4: 32
    cidr-len-ipv6: 64
    num-bits: 0

5. Run Ergo as a non-root user with systemd hardening. A hardened service unit prevents a compromised Ergo process from reading your home directory, escalating privileges, or writing outside its data directory:

NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes

6. Treat the database file as sensitive media. ircd.db contains account data and, if history is enabled, message content. On a Raspberry Pi this lives on a microSD card, which you will have to wipe and physically destroy when decommissioning.

7. Bind to LAN or tunnel, not the public internet. For single-device use, bind to 127.0.0.1. For trusted-circle use with other devices, bind to a WireGuard interface IP (e.g. 10.0.0.1). WireGuard is preferable to SSH tunnelling for persistent connections, as it operates at the kernel level, has a significantly smaller attack surface, and handles reconnections more gracefully.

8. Keep Ergo updated. Security fixes ship in point releases. Use the stable branch or release tags, not the master branch.

For Users

1. Ask the operator about their setup before connecting. Is logging enabled? Is server-side message history stored? Who else has physical access to the hardware? A trustworthy operator will answer these questions without hesitation and show you proof. If you feel uncomfortable, trust your instincts and leave.

2. Understand what the operator can access. An IRC Operator can read every message that passes through their server, see any traffic related to the server even if TLS prevents ISPs from seeing it, and sees your real IP address even with an IP cloak enabled. Cloaking only hides it from other users.

3. Verify the server certificate fingerprint. Ask the operator for the TLS certificate fingerprint before your first connection and pin it in your client. If the fingerprint does not match on connection, do not proceed.

4. Your trust in the server is only as strong as your trust in the Operator. A correctly configured server is meaningless if you do not trust the person running it.

Step 3: Privacy Features in HexChat

HexChat is a free, open-source IRC client for Windows and Linux with built-in support for TLS, SASL (both PLAIN and EXTERNAL), and TLS client certificates. It remains functional and widely understood, despite being unmaintained since its last release in 2024. Active alternatives include WeeChat and Irssi (both terminal-based, Linux/macOS/Windows).

For Operators

1. Use SASL EXTERNAL (certificate authentication). Generate a combined .pem file containing both the private key and the certificate:

openssl req -x509 -noenc -days 3650 \
  -newkey ed25519 \
  -keyout ~/.config/hexchat/certs/Network.pem \
  -out ~/.config/hexchat/certs/Network.pem

Then: chmod 600 ~/.config/hexchat/certs/Network.pem

Use -noenc (not the deprecated -nodes) and ed25519 (preferred over rsa:4096, ~128 bits of security, NIST FIPS 186-5 approved). Name the file exactly as your network appears in the Network List. Set the Login method to "SASL EXTERNAL (cert)", then register with: /msg NickServ cert add

2. Pin the server certificate fingerprint. In HexChat's Network List editor, enter your server's TLS certificate fingerprint. HexChat will refuse the connection if the fingerprint does not match, protecting against unannounced renewals, misconfigurations, and interception attempts.

3. Handle the HexChat server password conflict. If your server has a connection password set, it can conflict with SASL. Use the combined format: set your HexChat server password to username:password. This does not apply if you are using SASL EXTERNAL.

4. Disable local logging. HexChat logs all conversations to disk by default. Disable it at: Settings, Preferences, Logging, uncheck "Enable logging". A local log is a plaintext transcript regardless of how well the server is configured.

5. Disable DCC. DCC bypasses the server and exposes your real IP. At minimum, disable auto-accept: /set dcc_auto_recv 0

6. Suppress your client version string. Go to Settings, CTCP Replies and delete or blank the VERSION entry. Note that /set irc_hide_version on sets the +i user mode and does not suppress CTCP VERSION responses, use the CTCP Replies panel instead.

For Users

1. Disable local logging. This is the single most important client-side step. Settings, Preferences, Logging, uncheck "Enable logging".

2. Use SASL EXTERNAL if the operator supports it. Generate your own client certificate and ask the operator to register its fingerprint against your account. No password travels over the wire and your authentication cannot be replayed if intercepted.

3. Disable DCC. You have no reason to accept direct client connections in a private trusted-circle context. At minimum: /set dcc_auto_recv 0

4. Suppress your version string. Settings, CTCP Replies, delete or blank the VERSION entry.

5. Connect only from a device you control. Shared computers, work machines, and devices with unknown software installed are not appropriate for private IRC use.

6. Disconnect when you are not present. Do not leave an authenticated IRC session open and unattended. If the operator has always-on clients enabled, your nick may persist on the server after you disconnect.

Part 2: Configuring a Private Ergo Server

This section is for Operators who use Ergo, but has some use if you are a Chatter. If your local Operator uses Ergo and is acting evasively toward questions of privacy, you can measure this information against any claims they are making.

Config note: The exact YAML structure for history and related options has evolved across Ergo releases. Always verify key names against the MANUAL.md bundled with your installed version before deploying. The require-sasl path in particular has been reorganised in some releases. Treat that block as especially worth verifying against your version's MANUAL.md.

Step 1: Configuring ircd.yaml

Message History. Message history is a log by another name. Ergo stores message history server-side in ircd.db by default. Disable it explicitly:

history:
  enabled: false

If you keep history enabled, set aggressive limits. If you have been running Ergo without configuring this, the database already contains history and should be wiped and reinitialised.

Authentication. Require SASL and disable self-registration together. Ergo's own documentation warns that enabling require-sasl without disabling registration means anyone can still self-register and connect:

accounts:
  require-sasl:
    enabled: true
  registration:
    enabled: false

Create accounts with /msg NickServ SAREGISTER <username> <password> from an oper session. This is Ergo-specific operator syntax and will not work on a standard IRC network.

IP Cloaking. Setting num-bits: 0 produces a cloak entirely unrelated to the user's IP. The enabled-for-always-on: true key ensures always-on clients also receive unique cloaked hostnames:

server:
  ip-cloaking:
    enabled: true
    enabled-for-always-on: true
    netname: "irc"
    cidr-len-ipv4: 32
    cidr-len-ipv6: 64
    num-bits: 0

Service Hardening. Run a hardened systemd service that prevents privilege escalation and limits filesystem access:

[Service]
User=irc
Group=irc
ExecStart=/usr/local/bin/ergo run \
  --conf /etc/ergo/ircd.yaml
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/ergo

TLS Configuration. Use a trusted CA certificate or a self-signed certificate with its fingerprint pinned in all clients. CA-signed certificates add external trust. Self-signed removes third-party dependency but requires strict pinning.

Key Management. Back up the TLS private key securely to prevent lockout after hardware failure or certificate regeneration.

Data Sensitivity. ircd.db contains account data and optional message history. Treat storage media such as SD cards as sensitive and dispose of them securely.

Network Binding. Bind to 127.0.0.1 for single-device setups, or to a WireGuard interface IP (e.g. 10.0.0.1) for remote trusted access. WireGuard is preferable to SSH tunnelling for persistent connections, as it operates at the kernel level, has a significantly smaller attack surface, and handles reconnections more gracefully. Do not expose IRC directly to the public internet unless explicitly required.

Step 2: Managing a Multi-User Trusted-Circle Server

The moment a second person connects to your server, the threat model changes. Every device connecting is a potential disclosure vector, regardless of your configuration. The security of the channel is bounded by the least-secure device connecting to it.

1. Create accounts manually; never allow self-registration. With accounts > registration > enabled: false in place, create each user's account yourself via operator commands. No one joins without you explicitly adding them.

2. Configure channel modes for private circles. For a private circle, +si is the minimum. Secret means the channel does not appear in /LIST. Invite-only means users can only join if an existing member invites them with /INVITE. Additional modes: +m for moderated channels; +k <key> for a channel key that acts as a shared password.

3. Use SASL EXTERNAL where possible. Walk each person through generating their own client certificate and registering its fingerprint with NickServ. A user authenticating by password is a weaker link.

4. Prepare a revocation process before you need it. In Ergo, suspend a user's account with: /UBAN ADD account:<username>. This disconnects them immediately and prevents reconnection. The account: prefix is required, without it, the argument is interpreted as an IP address or mask, and the command will silently do nothing or match unexpectedly.

5. Restrict oper privileges to the administrator. Oper access includes the ability to read server-level information, manipulate accounts, ban users, and access stored data. Keep oper accounts to one. You are the only operator.

6. Understand message history risks on multi-user servers. These users may not know the log exists, may not have consented to it, and may have threat models that differ from yours. Disable server-side history entirely for any privacy-sensitive multi-user setup.

7. Define the social layer explicitly. Before anyone connects, establish clear answers to: logging policy; access control; device standards; screenshot and forwarding policy; server continuity; and incident response procedure.

Step 3: Minimum Requirements Checklist

Single-User Ergo Server (Raspberry Pi)

Enabled: Non-root execution (systemd hardening); restricted network access (LAN/VPN/tunnel); SASL requirement; TLS on port 6697, no plaintext.

Disabled: Always-on clients; client-side logging (HexChat); DCC; self-registration; server-side message history.

Configurations: SASL authentication method (EXTERNAL preferred); TLS certificate secured; microSD and TLS private key secured; latest version of Ergo.

Chatter (Connecting to Someone Else's Server)

Protocol: SASL authentication (EXTERNAL preferred); TLS certificate pinning; DCC disabled / auto-accept off; client-side logging disabled; CTCP VERSION suppression.

Procedure: Plausible evidence of the server logging status; a trusted, uncompromised device; session lifecycle (disconnect when not present).

Multi-User Server (Additions to the Above)

Technical Controls: Always-on clients disabled; channel modes (+si minimum); client-side logging disabled; IP cloaking; per-user SASL authentication (EXTERNAL preferred).

Operations: An established account revocation process; a transparent security policy; restricted oper access.

Conclusion

Congratulations. You now know how privacy measures work within the IRC protocol. While this guide was made for Ergo users, much of its information is relevant to all sorts of daemons. Enjoy your new technical knowledge and stay safe out there.

Sources

  1. Threat Modeling / Digital Security Risk Assessment — privacyguides.org / freedom.press
  2. Communicating With Others / Communication Network Types — ssd.eff.org / privacyguides.org
  3. Why Metadata Matters / VPN Overview — ssd.eff.org / privacyguides.org
  4. HexChat releases — github.com / libera.chat
  5. WireGuard documentation — wireguard.com / freedom.press
  6. NIST FIPS 186-5 — csrc.nist.gov
  7. Ergo MANUAL.md — github.com/ergochat
  8. ProtonMail / climate activist arrest — proton.me
  9. Mullvad search warrant — mullvad.net
  10. Google transparency report — transparencyreport.google.com

Further Reading

IRC: For Users

TitleDescription
Aaron Swartz IRC Style GuideA humourous guide on speaking in IRC.
Bash ArchiveAn extremely funny archive of IRC chatlogs.
Chat IRC Quote DatabaseAnother funny archive of IRC chatlogs.
FreeBSD Wiki - IRCFreeBSD's IRC documentation and community information.
FreenodeA 30 year old IRC network for the FOSS communities.
IRC HistoryAn abridged version of IRC's origins.
IRC History (GitHub)A Github repo that retells important events in IRC-istory.
IRC NewbiesAnother vintage guide on the IRC protocol.
IRC.orgThe official website of IRCnet, last updated in 2005.
IRCHelp.orgA classic IRC resource since 1996.
Libera.ChatA newer IRC network for the FOSS communities.
Linux IRC Mini-HOWTOA Linux-centric IRC guide from 2005.
NetsplitA search-engine for IRC networks.
TFTB IRC GuideA lighthearted anecdote on the various perverts of IRC.

IRC: For Operators

TitleDescription
Ergo IRC ServerMy daemon of choice, written in Go.
IRC Docs HubA large and precise guide on the state of IRC today.
irc3A pluggable IRC client library based on Python's asyncio.
IRCv3 SpecificationsGitHub repository containing all IRCv3 draft and stable specifications.
IRCv3 Working GroupOfficial IRCv3 working group for standardizing IRC protocol extensions.
Kiwi IRCA web-based client for IRC.
Modern IRCA suggestion and guide rolled into one.
NcatA networking assistant for your homelab needs.
Python IRC LibraryA full-featured IRC client framework for Python.
SopelA simple, easy-to-use, open-source IRC bot written in Python.
Wholok IRC GuideAn old and self-admittedly outdated guide on creating bots for IRC.