Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MeshIRCd

A federated IRC server for hobbyist networks. Modern protocol internals, classic IRC interface.

What It Is

MeshIRCd is a from-scratch IRC server in Go that federates with other MeshIRCd servers over a custom S2S protocol. Clients connect with any standard IRC client. Servers find each other via a shared GitHub repository.

What Makes It Different

JSON-LD S2S Protocol
Server-to-server communication uses JSON-LD over TLS. Events are signed with Ed25519, ordered with Lamport clocks, and deduplicated across the mesh. No TS6, no services, no legacy baggage.

GitHub-Based Discovery
Servers find peers by polling a servers.json file in a GitHub repo. Join the network with a PR. Leave by deleting your entry. Git history is your audit log.

DID Identity
Users can attach Decentralized Identifiers to their presence. Prove you control did:key:... or did:web:example.com. Identity propagates across the federation and shows in WHOIS.

IRCv3 Features
SASL EXTERNAL (TLS client certs mapped to DIDs), SASL GITHUB (device flow login), SASL OAUTHBEARER, message IDs, echo-message, chathistory, labeled-response. Modern client UX on a modern server.

GitHub Login
Users can authenticate with their GitHub account. No NickServ, no password registration — just AUTHENTICATE GITHUB, authorize in browser, done. Verified users get +r mode and nick protection.

Soft Mesh Topology
Servers connect to all peers they can reach. Messages flood with deduplication. No spanning tree, no single point of failure. Partitions heal automatically.

Architecture

┌──────────────┐    JSON-LD/TLS     ┌──────────────┐
│  MeshIRCd A  │◄──────────────────►│  MeshIRCd B  │
└──────┬───────┘                    └───────┬──────┘
       │ IRC                                │ IRC
       ▼                                    ▼
   ┌───────┐                            ┌───────┐
   │ irssi │                            │ weechat│
   └───────┘                            └───────┘
  • C2S: Standard IRC protocol + IRCv3 extensions
  • S2S: JSON-LD messages, Ed25519 signatures, Lamport ordering
  • Discovery: GitHub repo with servers.json

Quick Start

# Generate keypair and server config
meshircd --init --hostname irc.example.com --port 6697 --admin you@example.com

# Start the server
meshircd \
  --hostname irc.example.com \
  --port 6697 \
  --cert server.crt \
  --key server.key \
  --discovery-url https://raw.githubusercontent.com/MarkAtwood/meshircd-network/main/servers.json

Joining a Network

  1. Run meshircd --init to generate your server block
  2. Fork the network's config repo
  3. Add your block to servers.json
  4. Open a PR
  5. Wait for merge
  6. Start your server — peers connect within 5 minutes

Configuration

servers.json (in your network's GitHub repo):

{
  "network": "MyNetwork",
  "servers": {
    "irc.example.com": {
      "port": 6697,
      "pubkey": "ed25519:MCowBQYDK2VwAyEA...",
      "admin": "admin@example.com"
    }
  }
}

GitHub OAuth Setup

MeshIRCd supports GitHub-based authentication via SASL GITHUB mechanism and did:github identity verification. This requires a GitHub OAuth App.

Creating the OAuth App

  1. Go to GitHub Settings > Developer settings > OAuth Apps > New OAuth App
  2. Fill in the application details:
    • Application name: MeshIRCd (or your network name)
    • Homepage URL: Your server's URL or GitHub repo
    • Authorization callback URL: http://localhost (not used, but required)
  3. Click Register application
  4. Copy the Client ID
  5. Click Generate a new client secret and copy it immediately

Required Settings

  • Device flow must be enabled: On the OAuth App settings page, check Enable Device Flow
  • Scopes: Only read:user is needed (for username lookup)

Configuring MeshIRCd

OAuth credentials can be provided via:

1. Init wizard (recommended)

meshircd --init --hostname irc.example.com --admin you@example.com
# Follow prompts for GitHub OAuth setup

2. Environment variables

export GITHUB_CLIENT_ID=your_client_id
export GITHUB_CLIENT_SECRET=your_client_secret

3. Command-line flags

meshircd --github-client-id=xxx --github-client-secret=xxx

4. Config file (/data/github-oauth.json)

{
  "client_id": "your_client_id",
  "client_secret": "your_client_secret"
}

Priority: flags > env vars > config file.

Identity

Users can attach DIDs to their IRC presence:

/quote IDENTITY CHALLENGE
/quote METADATA * SET identity :{"@context":[...],"id":"did:key:z6Mk...","proof":{...}}

Identity shows in WHOIS and propagates across the federation.

Specs

Document Description
S2S.md Server-to-server federation protocol
IDENTITY.md DID-based identity extension
IRCV3.md IRCv3 client protocol extensions
DISCOVERY.md GitHub-based peer discovery
GITHUB.md GitHub OAuth authentication

Building

go build -o meshircd .

Requires Go 1.21+.

Docker

# Build
docker build -t meshircd .

# Initialize (generates keys, outputs servers.json block)
docker run --rm -v meshircd-data:/data \
  -e MESHIRCD_HOSTNAME=irc.example.com \
  -e MESHIRCD_ADMIN=you@example.com \
  meshircd --init

# Run
docker run -d --name meshircd \
  -v meshircd-data:/data \
  -p 6697:6697 \
  -e MESHIRCD_HOSTNAME=irc.example.com \
  -e MESHIRCD_DISCOVERY_URL=https://raw.githubusercontent.com/MarkAtwood/meshircd-network/main/servers.json \
  meshircd

Environment variables:

  • MESHIRCD_HOSTNAME — server hostname (required)
  • MESHIRCD_DISCOVERY_URL — servers.json URL for federation
  • MESHIRCD_NETWORK — network name (default: MeshIRCd)
  • MESHIRCD_ADMIN — admin email (for init)
  • MESHIRCD_DATA — data directory (default: /data)
  • GITHUB_CLIENT_ID — GitHub OAuth app client ID (enables GitHub login)
  • GITHUB_CLIENT_SECRET — GitHub OAuth app client secret

Keys persist in the /data volume. First run with --init, PR the output block to the network repo, then run normally.

Running Behind a Reverse Proxy

MeshIRCd can run behind Caddy or another proxy using TCP passthrough. TLS must terminate at MeshIRCd (not the proxy) so federation peers see the correct certificate.

Caddy with layer4 plugin:

# Caddyfile
{
  layer4 {
    :6697 {
      route {
        proxy meshircd-backend:6697
      }
    }
  }
}

Build Caddy with the layer4 plugin:

xcaddy build --with github.com/mholt/caddy-l4

This works well for homelab setups where MeshIRCd runs on an internal server (e.g., via Tailscale) and Caddy runs on a public VPC.

Tor Support

MeshIRCd can federate over Tor, both connecting to .onion peers and running as a hidden service.

Connecting to .onion Peers

Enable Tor SOCKS5 proxy to connect to .onion federation peers:

meshircd --tor-socks=127.0.0.1:9050 ...

Or via environment variable:

TOR_SOCKS=127.0.0.1:9050 meshircd ...

When enabled, any peer in servers.json with a .onion hostname will be dialed through Tor.

Running as a Hidden Service

Run your server as a Tor hidden service for anonymous federation:

meshircd --onion --tor-control=127.0.0.1:9051 --tor-cookie=/var/lib/tor/control_auth_cookie ...

Or with password auth:

meshircd --onion --tor-control=127.0.0.1:9051 --tor-password=mypassword ...

The server creates an ephemeral hidden service and logs the .onion address on startup.

servers.json with .onion Peers

Mixed clearnet and .onion servers can federate together:

{
  "servers": {
    "irc.example.com": {
      "port": 6697,
      "pubkey": "ed25519:...",
      "admin": "admin@example.com"
    },
    "abc123xyzdef456.onion": {
      "port": 6697,
      "pubkey": "ed25519:...",
      "admin": "anon@protonmail.com",
      "onion": true
    }
  }
}

Environment variables:

  • TOR_SOCKS — SOCKS5 proxy address (default: 127.0.0.1:9050)
  • TOR_CONTROL — Control port address
  • TOR_PASSWORD — Control port password
  • TOR_COOKIE — Path to control_auth_cookie file
  • MESHIRCD_ONION — Set to "true" to enable hidden service
  • MESHIRCD_TOR_CLIENT_ADDR — Listener for anonymous Tor clients (e.g., 127.0.0.1:6698)

Tor Client Listener

Separate listener for clients connecting via Tor hidden service:

meshircd --tor-client-addr=127.0.0.1:6698 --onion --tor-control=127.0.0.1:9051 ...

Point the hidden service at this port. Users connect normally (NICK/USER), pick their own nick. No identity verification available, so no +r mode — but otherwise standard IRC.

OIDC Authentication

Authenticate via any OIDC provider (Azure AD, Okta, Keycloak, university IdPs, etc).

meshircd \
  --oidc-issuer=https://login.microsoftonline.com/tenant/v2.0 \
  --oidc-client-id=your-client-id \
  --oidc-client-secret=your-secret \
  ...

Or via environment variables:

OIDC_ISSUER=https://... OIDC_CLIENT_ID=... OIDC_CLIENT_SECRET=... meshircd

Client Usage

/CAP REQ :sasl
/AUTHENTICATE OIDC

Server sends a verification URL. Visit it, log in with your institution, and you're authenticated.

Nick Format

Authenticated users get username_oidc nick with +r mode.

Internet2 / InCommon

For university authentication:

  1. Register an OIDC client with your institution's IdP
  2. Request openid profile email scopes
  3. Enable device flow (if supported)
  4. Configure meshircd with issuer URL and client credentials

Many universities support OIDC via Shibboleth 4+, Azure AD, or Google Workspace.

SSH Transport

Connect via SSH instead of TLS. Identity verified against GitHub SSH keys.

meshircd --ssh-addr=:2222 ...

Users connect with:

ssh alice@irc.example.com -p 2222

The alice in alice@host is the GitHub username claim. Server fetches github.com/alice.keys and verifies the connecting key is in the list.

Nick Format

Auth Nick
GitHub key verified alice_github
Unknown key _ssh_a1b2c3d4

Environment Variables

  • MESHIRCD_SSH_ADDR — SSH listener address (e.g., :2222)

Design Principles

  • TLS only — no plaintext, no STARTTLS upgrade dance
  • No services — identity is DIDs, not NickServ
  • No linking complexity — soft mesh, not spanning tree
  • Git as coordination — PRs for trust decisions, history for audit
  • JSON-LD for extensibility — add contexts, not protocol versions
  • Existing clients work — IRCv3 where it helps, standard IRC everywhere

License

AGPL-3.0

About

Federated IRC server with JSON-LD S2S, DID identity, and GitHub-based discovery

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages