This guide covers the automated SSL certificate management system for IRC.atl.chat, which uses Let's Encrypt with Cloudflare DNS-01 challenge for secure certificate provisioning and renewal.
IRC.atl.chat enforces TLS-only connections for security. All IRC clients must connect via SSL/TLS on port 6697. Plaintext connections on port 6667 are disabled.
- Certificate Authority: Let's Encrypt (free, automated certificates)
- Challenge Method: DNS-01 via Cloudflare API
- Automation: Custom SSL manager script with Docker integration
- Storage: Certificates stored in
data/letsencrypt/and copied to UnrealIRCd - Renewal: Automatic renewal with service restart
- Domain must be managed by Cloudflare
- DNS records must exist for your domain and
*.yourdomain.com - DNS must be propagated (verify with
dig yourdomain.com)
- Log into Cloudflare Dashboard
- Go to My Profile → API Tokens
- Create a new token with these permissions:
- Zone:DNS:Edit permission for your domain
- Copy the token (keep it secure!)
Ensure your .env file has the required SSL variables:
# Required for SSL
IRC_ROOT_DOMAIN=yourdomain.com
LETSENCRYPT_EMAIL=admin@yourdomain.com# Copy the template
cp cloudflare-credentials.ini.template cloudflare-credentials.ini
# Edit with your API token
vim cloudflare-credentials.ini
# Add: dns_cloudflare_api_token = your-actual-token-here
# Secure the file
chmod 600 cloudflare-credentials.ini# Issue initial certificates
make ssl-setup
# This runs the SSL manager script which:
# 1. Validates configuration
# 2. Issues certificates via Let's Encrypt
# 3. Copies certificates to UnrealIRCd
# 4. Restarts servicesImportant: SSL setup must complete before starting services. UnrealIRCd configuration expects certificates to exist.
# Start all services (SSL certificates must exist first)
make up# Quick status check
make ssl-status
# Detailed certificate information
./scripts/ssl-manager.sh check --verbose# Check certificates
./scripts/ssl-manager.sh check
# Issue new certificates (force renewal)
./scripts/ssl-manager.sh issue
# Renew if needed (checks expiry first)
./scripts/ssl-manager.sh renew
# Copy certificates to UnrealIRCd
./scripts/ssl-manager.sh copy
# Restart services after certificate update
./scripts/ssl-manager.sh restartdata/letsencrypt/
├── live/yourdomain.com/
│ ├── fullchain.pem # Certificate chain
│ ├── privkey.pem # Private key
│ └── cert.pem # Certificate only
src/backend/unrealircd/conf/tls/
├── server.cert.pem # Certificate for UnrealIRCd
├── server.key.pem # Private key for UnrealIRCd
└── curl-ca-bundle.crt # CA bundle for SSL validation
Certificates are automatically renewed when:
- Expiry is within 30 days (warning threshold)
- Expiry is within 7 days (critical threshold)
The renewal process:
- Checks certificate expiry
- Renews via Let's Encrypt if needed
- Copies new certificates to UnrealIRCd
- Restarts affected services
# Check SSL status
make ssl-status
# View SSL logs
make ssl-logs
# Check overall service health
make status# Check if credentials file exists
ls -la cloudflare-credentials.ini
# Verify file permissions (should be 600)
chmod 600 cloudflare-credentials.ini
# Check file format
cat cloudflare-credentials.ini
# Should contain: dns_cloudflare_api_token = your-token# Verify DNS records exist
dig TXT _acme-challenge.yourdomain.com
dig TXT _acme-challenge.*.yourdomain.com
# Check Cloudflare DNS settings
# Ensure records exist and are not proxied (orange cloud off)
# Wait for DNS propagation (can take 24+ hours)# Check current certificate details
./scripts/ssl-manager.sh check --verbose
# Force renewal if needed
./scripts/ssl-manager.sh issue# Check certificate file permissions
ls -la src/backend/unrealircd/conf/tls/
# Manually restart services
docker restart unrealircd unrealircd-webpanel
# Check service logs
make logsEnable detailed logging for troubleshooting:
# Debug SSL operations
./scripts/ssl-manager.sh --debug check
./scripts/ssl-manager.sh --debug issue
# Verbose output
./scripts/ssl-manager.sh --verbose renew# Verify certificate chain
openssl verify -CAfile src/backend/unrealircd/conf/tls/curl-ca-bundle.crt \
src/backend/unrealircd/conf/tls/server.cert.pem
# Check certificate details
openssl x509 -in src/backend/unrealircd/conf/tls/server.cert.pem -text -noout
# Test SSL connection
openssl s_client -connect yourdomain.com:6697 -servername yourdomain.com- Private keys: Stored with 644 permissions (readable by UnrealIRCd)
- File permissions: Credentials file must be 600 (owner read/write only)
- API tokens: Never commit to version control
- Certificate validation: Full chain validation with trusted CA bundle
- TLS-only policy: Plaintext IRC connections disabled
- Modern TLS: Configured for security (see UnrealIRCd config)
- Perfect Forward Secrecy: Supported cipher suites
- HSTS: HTTP Strict Transport Security headers
- Certificate expiry: Monitored automatically
- Renewal failures: Logged with error details
- Service restarts: Automatic after certificate updates
- Health checks: Certificate validity included in service health
The SSL manager uses these default paths (configurable in the script):
TLS_DIR="./src/backend/unrealircd/conf/tls"
LETSENCRYPT_DIR="./data/letsencrypt"
CREDENTIALS_FILE="./cloudflare-credentials.ini"The current setup issues certificates for:
yourdomain.com*.yourdomain.com
For additional domains, modify the certbot command in ssl-manager.sh.
Let's Encrypt has rate limits:
- Certificates per domain: 5 per week
- Failed validations: 5 per hour
- Duplicate certificates: 1 per week
# Weekly: Check certificate status
make ssl-status
# Monthly: Verify automation works
./scripts/ssl-manager.sh renew --verbose
# Quarterly: Review SSL configuration
# Check UnrealIRCd TLS settings
# Verify Cloudflare DNS settingsIf certificates expire unexpectedly:
-
Immediate action: Check why renewal failed
make ssl-logs ./scripts/ssl-manager.sh check --debug
-
Manual renewal: Force certificate issuance
./scripts/ssl-manager.sh issue --verbose
-
Service restart: Ensure services use new certificates
make restart
Certificates are automatically backed up in data/letsencrypt/. To restore:
# Copy from Let's Encrypt backup
./scripts/ssl-manager.sh copy
# Restart services
./scripts/ssl-manager.sh restart- README.md - Quick start guide
- SECRET_MANAGEMENT.md - API token and password management
- USERMODES.md - IRC user mode reference
- UnrealIRCd Documentation - Server configuration
- Let's Encrypt Documentation - Certificate authority
- Cloudflare API Documentation - DNS management