Skip to main content

Self-Hosted ZNC IRC Bouncer with Docker & Reverse Proxy

ZNC is an advanced IRC network bouncer that stays connected to IRC servers even when you are offline. It allows you to replay the chat logs you missed and keeps your nick online 24/7.

While ZNC is easy to install via package managers, running it in Docker keeps the host system clean. However, setting it up with a Reverse Proxy (like Nginx or YunoHost) and handling permissions correctly requires a few specific steps.

This guide covers installing the linuxserver/znc image, generating the initial configuration securely, and integrating it with a web proxy.

Prerequisites

  • A VPS or Linux server with Docker and Docker Compose installed.
  • A Reverse Proxy (Nginx, Traefik, or YunoHost).
  • Your user PUID and PGID (run id in your terminal to find these).

Step 1: Directory & Permissions

First, create a dedicated directory for ZNC. Using the LinuxServer.io image allows us to map the container's internal user to our host user, preventing permission issues.

# Create the directory structure
mkdir -p ~/docker/znc/config

Step 2: The Docker Compose File

Create a docker-compose.yml file inside your ZNC directory.

We are mapping two ports:

  1. 6501: The Web UI port. We map this to 127.0.0.1 (localhost) only, because we will expose it via a secure Reverse Proxy later.
  2. 6697: The IRC port. We map this globally so IRC clients can connect directly via SSL.
services:
  znc:
    image: linuxserver/znc:latest
    container_name: znc
    environment:
      - PUID=23691    # Replace with your User ID (run `id` to check)
      - PGID=23691    # Replace with your Group ID
      - TZ=Asia/Kuala_Lumpur
    volumes:
      - ./config:/config
    ports:
      - "127.0.0.1:6501:6501" # Internal Web UI (for Reverse Proxy)
      - "6697:6697"           # External IRC Port (SSL)
    restart: unless-stopped

Step 3: Generating the Configuration (The Tricky Part)

ZNC requires an initial configuration file with a hashed password to start. You cannot simply create a text file. Furthermore, the LinuxServer image does not allow running the generator as root.

To solve this, we use s6-setuidgid to run the configuration wizard as the correct internal user (abc).

Run this command to start the wizard:

docker compose run --rm znc s6-setuidgid abc znc --makeconf

Answer the prompts as follows:

  1. Listen on port: 6501
  2. Listen using SSL: No (Crucial: The reverse proxy handles SSL for the website; ZNC handles it internally for the IRC port).
  3. Listen using IPv6: Yes
  4. Username/Password: Set your desired admin credentials.
  5. Launch ZNC now? No

Note: If you encounter errors about "Old Config" or permissions, delete the contents of the ./config folder and try the command again.

Step 4: Start the Service

Once the configuration file is generated, start the container in the background:

docker compose up -d

Step 5: Reverse Proxy Setup (YunoHost Example)

To access the ZNC web interface securely (e.g., at znc.obulou.org), you need to point your proxy to the local port we defined.

If you are using YunoHost:

  1. Go to Web Admin > Applications > Install.
  2. Select "Redirect" (or "Custom Webapp").
  3. Label: ZNC
  4. Domain/Path: e.g., znc.obulou.org or obulou.org/znc
  5. Destination URL: http://127.0.0.1:6501

Step 6: Connecting Your Client

You can now connect any IRC client (HexChat, The Lounge, mIRC) to your bouncer.

  • Server: obulou.org (Your domain)
  • Port: 6697
  • SSL/TLS: Enabled (Accept invalid certificate if self-signed)
  • Password: username/network:password

A Note on SSL Certificates

By default, ZNC generates a self-signed certificate for the IRC port (6697). Your IRC client may warn you about this. You can accept the warning, or for a "cleaner" setup, you can mount your Let's Encrypt certificates (from /etc/letsencrypt or YunoHost certs) into the ZNC container volume, though that requires additional file permission management.