zircon ChatGPT on IRC, one ZNC account per person

Run

Configuration

Non-secret settings live in the NixOS module; secrets live in one host-only environment file.

NixOS module

The flake exports nixosModules.default, which defines services.zircon.

services.zircon = {
  enable = true;
  environmentFile = "/var/lib/zircon-secrets/zircon.env";
  settings = {
    githubClientId = "<GitHub OAuth app client ID>";
    ircChannels = [ "#lobby" "#soup" ];
  };
};
option default meaning
port 3000 loopback HTTP port for the reverse proxy
maxUsers 16 most users Zircon will create (1 to 100)
enableDiagnostics false expose owner-only /admin/events and store bounded MCP/connection diagnostics
historyRetentionDays 7 maximum days of channel history (1 to 365)
historyMaxPerChannel 5000 maximum entries per user and channel (100 to 100000)
environmentFile none, required secrets file outside /nix/store
settings.publicBaseUrl https://zircon.chooser.us public HTTPS origin
settings.githubClientId required GitHub OAuth app client ID
settings.oauthClientId zircon-chatgpt legacy GPT Action client ID
settings.oauthRedirectUris [] optional exact legacy GPT Action callback URLs
settings.zncPort 6667 ZNC’s loopback IRC listener
settings.zncAdminUser zirconctl ZNC administrator with controlpanel
settings.ircNetworks chonkbase, irc.chonkbase.net:6697, TLS owner-approved servers users may pick
settings.ircUsername zircon IRC username (ident)
settings.ircRealname Zircon ChatGPT bridge prefix for each user’s IRC real name; their GitHub login is appended
settings.ircChannels required channels the owner may grant
settings.ownerLogins [] owner GitHub logins resolved and pinned to numeric IDs for browser diagnostics and user management
settings.diagnosticsAdminLogins [] deprecated alias for ownerLogins; used only when ownerLogins is empty

The service runs with DynamicUser, StateDirectory=zircon, ProtectSystem=strict, no capabilities, and logs to stdout.

Secrets

Put these names in the host environment file. GitHub issues GITHUB_CLIENT_SECRET; generate the others on the host. Every secret except ZNC_ADMIN_PASSWORD must be at least 32 characters.

name used for
GITHUB_CLIENT_SECRET GitHub sign-in token exchange
OAUTH_CLIENT_SECRET legacy GPT Action client secret; still required by current configuration
SESSION_SECRET CSRF tokens for the browser pages
ADMIN_TOKEN the owner’s POST /admin/invite bearer token
ZNC_ADMIN_PASSWORD the ZNC administrator account
ZNC_USER_SECRET deriving each user’s ZNC password
openssl rand -base64 48   # one per secret

Environment variables

Outside NixOS, Zircon reads the same settings from the environment: PUBLIC_BASE_URL, GITHUB_CLIENT_ID, OAUTH_CLIENT_ID, OAUTH_REDIRECT_URIS (optional, comma separated), IRC_CHANNELS (comma separated), IRC_NETWORKS_JSON, ZNC_ADMIN_USER, plus optional PORT, MAX_USERS, HISTORY_RETENTION_DAYS, HISTORY_MAX_PER_CHANNEL, DIAGNOSTICS_ENABLED, DIAGNOSTICS_ADMIN_LOGINS, STATE_DIR (default /var/lib/zircon), ZNC_HOST, ZNC_PORT, IRC_USERNAME and IRC_REALNAME.

bun run src/index.js

Checks

bun test
nix flake check