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
- Python 3.11+
- cryptography library:
pip install cryptography - 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
- Copy
keys/mainserver.pubfrom Server A to Server B:scp keys/mainserver.pub user@serverB:/path/to/zircd/keys/mainserver.pub - Update
zircd.cfgon 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
- Use strong random passwords – Generate with
gpw5.py --randpass(32 bytes = 256 bits) - Keep private keys secure – 600 permissions, never share .key files
- Verify public keys – Compare fingerprints out-of-band before adding
- Restrict link ports – Only open port 9999 to trusted servers
- Monitor link health – Watch logs for authentication failures
General Security
- Keep servers updated – Use the same version across the network
- Use encrypted links – Never disable RSA encryption
- Backup private keys – Store securely offline
- Restrict file permissions –
chmod 600for .key files and adminusers.json - 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]”