/\/ Amiga Chat Network \/\ /\/ ACN \/\
zircd – Linking Guide

Overview

Version: 0.51
Last Updated: June, 2026

This guide will walk you through setting up encrypted server-to-server links in zircd

Architecture:

Amiga (zirc) -> Local zircd (unencrypted) <-> Main zircd <-> Other servers (encrypted)
      port 8888                            port 8888    port 8899

Key Features:

  • RSA + AES-256-GCM hybrid encryption – Secure server-to-server links
  • No certificate expiration – Raw RSA keys without certificate management
  • Password authentication – Shared passwords for link authentication
  • Remote key distribution – Add peer keys via AdminServ commands
  • Automatic state synchronization – Users, channels, NickServ, ChanServ, and AdminServ
  • AdminServ synchronization – Share admin credentials across trusted servers (v0.12+)
  • Remote network administration – Manage the entire network from any linked server (v0.12+)
  • Automatic reconnection – Links automatically reconnect with exponential backoff (v0.11+)

Prerequisites

  1. Python 3.11+
  2. cryptography library:
    pip install cryptography
  3. Two or more zircd servers running (can be on same machine for testing)

Step 1: Generate RSA Keys

On each server, generate an RSA key pair:

python3 gpw5.py --genkey
Enter server ID (e.g., mainserver, ciabbs): mainserver

Output:

Generating 2048-bit RSA key pair...
(ok) RSA key pair generated successfully!
  Private key: keys/mainserver.key
  Public key:  keys/mainserver.pub

Security notes:
  - Keep keys/mainserver.key SECURE and PRIVATE
  - Share keys/mainserver.pub with linking servers
  - Private key permissions set to 600 (owner read/write only)

Base64-encoded public key (for AdminServ ADDPEERKEY):
LS0tLS1CRUdJTi....(long base64 string)....QVBERQ==

Important: Copy the base64-encoded public key – you’ll need it later!

Step 2: Configure Server Keys

Edit zircd.cfg on each server and add:

[Server]
NetworkID = MainServer           # Unique ID for this server
PrivateKey = keys/mainserver.key
PublicKey = keys/mainserver.pub
Linkport = 9999                  # Port for encrypted links

Step 3: Configure Link Passwords

Generate a strong random password for each link using gpw5.py:

python3 gpw5.py --randpass
# Press Enter to use default 32 bytes
# Output: V6zK/Etd4DKgQYtDKD3O0ZeBYK8nvBCGewIxZdKhSRU=

Add to zircd.cfg:

[Link1]
NetworkID = CIABBS              # Remote server's NetworkID
Password = V6zK/Etd4DKgQYtDKD3O0ZeBYK8nvBCGewIxZdKhSRU=
# ConnectTo = ciabbs.example.com  # Optional - for initiating connections
# Hostport = 9999
# PeerPublicKey = keys/ciabbs.pub  # Will add in next step
# Using gpw5.py with custom length:
python3 gpw5.py --randpass
# Enter: 16 (for shorter password)

Step 4: Exchange Public Keys

Option A: Manual File Transfer

  1. Copy keys/mainserver.pub from Server A to Server B:
    scp keys/mainserver.pub user@serverB:/path/to/zircd/keys/mainserver.pub
  2. Update zircd.cfg on Server B:
    [Link1]
    NetworkID = MAINSERVER
    Password = shared_password
    PeerPublicKey = keys/mainserver.pub

Option B: Command Line Tool

python3 gpw5.py --showkey
Enter public key file path: keys/mainserver.pub

Copy the base64 output and send via email/chat to remote admin.

Step 5: Update Configuration

On both servers, edit zircd.cfg to add the peer’s public key and configure AdminServ sync.

Server A (MainServer) – Main Hub:

[Server]
NetworkID = MainHost
PrivateKey = keys/mainhost.key
PublicKey = keys/mainhost.pub
Linkport = 8899

[Link1]
NetworkID = CIABBS
Password = V6zK/Etd4DKgQYtDKD3O0ZeBYK8nvBCGewIxZdKhSRU=
PeerPublicKey = keys/ciabbs.pub

Server B (CIABBS) – Linked Server:

[Server]
NetworkID = CIABBS
PrivateKey = keys/ciabbs.key
PublicKey = keys/ciabbs.pub
Linkport = 9999

[Link1]
NetworkID = MainHost
Password = V6zK/Etd4DKgQYtDKD3O0ZeBYK8nvBCGewIxZdKhSRU=
PeerPublicKey = keys/mainhost.pub
ConnectTo = mainhost.example.com  # Connect to main server
Hostport = 9999

Important Notes:

  • Linked servers forward commands to main server automatically

Step 6: Reload Configuration

Restart the servers:

# Linux (systemd):
sudo systemctl restart zircd

# Manual:
Ctrl-C (to stop)
python3 zircd.py (to start)

Step 7: Verify Link

Check server logs:

tail -f logs/zircd.log

On Main Server (MainHost):

INFO - LinkServer initialized on :::8899
INFO - Link server listening on :::8899
INFO - Incoming link connection from ('::ffff:10.0.0.244', 46690, 0, 0)
INFO - Remote server CIABBS version: 0.33, local version: 0.33
INFO - Link CIABBS authenticated
INFO - Link CIABBS: Version match (v0.33)
INFO - Link CIABBS encryption established
INFO - Synchronized 2 admin(s) to CIABBS
INFO - Receiving state sync from CIABBS
INFO - State sync complete from CIABBS

On Linked Server (CIABBS):

INFO - LinkServer initialized on :::8899
INFO - Link server listening on :::8899
INFO - Initiating outbound link to MainHost at 10.0.0.1:8899
INFO - Connected to MainHost at 10.0.0.1:8899
INFO - Remote server MainHost version: 0.33, local version: 0.33
INFO - Link MainHost: Version match (v0.33)
INFO - Link MainHost encryption established (initiator)
INFO - Admin vorlon synchronized from MainHost
INFO - Admin vk3heg synchronized from MainHost
INFO - Receiving state sync from MainHost
INFO - State sync complete from MainHost

Testing Network Connectivity

Firewall Configuration

Ensure port 8899 is open in firewall:

# Linux (ufw):
sudo ufw allow 8899/tcp

# Linux (iptables):
sudo iptables -A INPUT -p tcp --dport 8899 -j ACCEPT

Test Connectivity

From linked server:

# Test if port 8899 is reachable
nc -zv mainhost.example.com 8899
# Or
telnet mainhost.example.com 8899

Troubleshooting

“cryptography library not available”

pip install cryptography

“Private key not found”

python3 gpw5.py --genkey
# Update zircd.cfg with correct paths

“Link authentication failed”

  • Check that NetworkID matches on both servers
  • Verify Password is identical on both servers
  • Check challenge-response hash in logs

“Key exchange failed”

  • Verify PeerPublicKey points to correct file
  • Ensure public key file is readable
  • Check that public keys were exchanged correctly

“Link timeout – no PONG received”

  • Check network connectivity
  • Verify port 9999 is accessible
  • Check firewall rules
  • Check logs on both servers for connection errors

“Version mismatch” warning

  • Update both servers to the same version
  • Version mismatches may cause compatibility issues

Security Best Practices

Link Security

  1. Use strong random passwords – Generate with gpw5.py --randpass (32 bytes = 256 bits)
  2. Keep private keys secure – 600 permissions, never share .key files
  3. Verify public keys – Compare fingerprints out-of-band before adding
  4. Restrict link ports – Only open port 9999 to trusted servers
  5. Monitor link health – Watch logs for authentication failures

General Security

  1. Keep servers updated – Use the same version across the network
  2. Use encrypted links – Never disable RSA encryption
  3. Backup private keys – Store securely offline
  4. Restrict file permissionschmod 600 for .key files and adminusers.json
  5. Monitor logs – Watch for suspicious activity, failed auth attempts

Password Policy Consistency

The [Server] section of zircd.cfg includes two password policy settings:

MinPasswordLength = 10   # Minimum character count for NickServ/AdminServ passwords
PasswordComplexity = no # yes = require uppercase, lowercase, number, and special char

These settings must match on every server in the network. The reason is how NickServ registrations propagate:

  • When a user registers on a secondary server, that server validates the plaintext password against its own policy, hashes it, and syncs the hash to the main server. The main server only ever receives the hash – it never validates the plaintext.
  • If the secondary has a weaker policy (e.g. MinPasswordLength = 4) it will accept passwords that the main server’s stricter policy would reject. The weak password then propagates across the network as a hash.
  • AdminServ commands (ADDADMIN, SETADMINPASS, SETPASS) are forwarded to the main server and validated there too, so those are doubly enforced. NickServ REGISTER is not.

When distributing a new server package, always include your current policy values in the example config so new sysops start with matching settings.

Example: Three-Server Network

         Main Server (MainHost)
        /                      
       /                        
  CIABBS                      FREDBBS

MainServer zircd.cfg:

[Server]
NetworkID = MainHost
PrivateKey = keys/mainhost.key
PublicKey = keys/mainhost.pub
Linkport = 8899

[Link1]
NetworkID = CIABBS
Password = <password1>
PeerPublicKey = keys/ciabbs.pub

[Link2]
NetworkID = FREDBBS
Password = <password2>
PeerPublicKey = keys/fredbbs.pub

CIABBS zircd.cfg:

[Server]
NetworkID = CIABBS
PrivateKey = keys/ciabbs.key
PublicKey = keys/ciabbs.pub
Linkport = 8899

[Link1]
NetworkID = MainHost
Password = <password1>
PeerPublicKey = keys/mainhost.pub
ConnectTo = host.example.com

All servers can see users and channels from all other servers once links are established!

Next Steps

  • Set up more links to build your network
  • Monitor logs for link health

Getting Help

  • Check logs in logs/zircd.log
  • Contact Vorlon in the channel, or email vorlon “[email protected]