====== TLS Connection Issues (bytes remaining on stream) ====== **Symptoms** IRC clients show "connection to server lost (bytes remaining on stream)" errors repeatedly. **Cause** Attempting to proxy IRC protocol through Caddy using HTTP-based directives. **What Did Not Work** 1. **Caddy reverse_proxy** - reverse_proxy is designed for HTTP, not raw TCP - IRC is a long-lived, bidirectional, line-oriented protocol - This causes stream corruption and connection drops 2. **Caddy tcp_proxy** - tcp_proxy is not a valid Caddy directive in standard builds - Would require custom Caddy build with layer4 module (mholt/caddy-l4) - Even with proper module, Caddy has known issues with TCP stream corruption **What Finally Worked** Ergo native TLS termination with certificate sync from Caddy. **Implementation** 1. **docker-compose.yml changes** - Expose port 6697 from Ergo directly, not through Caddy - Remove port 6697 from Caddy - Add certificate volume mount to Ergo: ./irc/certs:/ircd/certs:ro 2. **ircd.yaml configuration** - Configure Ergo to listen on 127.0.0.1:6667 for The Lounge (plaintext, internal) - Configure Ergo to listen on :6697 with TLS certificates - TLS certificates specified in listeners section: ```yaml ":6697": tls-certificates: - cert: /ircd/certs/fullchain.pem key: /ircd/certs/privkey.pem ``` 3. **Certificate sync script** - Create sync-irc-certs.sh to copy certificates from Caddy to Ergo - Caddy stores certificates at /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/irc-direct.folk.zone/ - Script copies .crt to fullchain.pem and .key to privkey.pem - Script sends SIGHUP to Ergo to reload certificates without dropping connections - Add to cron for automatic renewals 4. **Caddyfile** - Remove IRC proxy block entirely - Keep irc-direct.folk.zone info page for certificate renewal - Caddy continues to handle HTTP for The Lounge and other services **Benefits** - No TCP relay layer, eliminating stream corruption risk - Ergo handles TLS natively as designed - Certificates managed by Caddy, synced to Ergo - Certificate renewals handled automatically with cron - The Lounge connects internally via Docker network - External IRC clients connect directly to Ergo on port 6697 **Prevention** Use native TLS termination for IRC daemons instead of proxying through HTTP reverse proxies. IRC is a TCP protocol, not HTTP. Last updated: 2026-06-21