Add signal handler that calls rehash() on SIGHUP, logging results instead of sending to a client. Useful for systemd and container environments where no IRC client is attached. Update docs with channel key config, hot reload section, and roadmap checkoffs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.4 KiB
7.4 KiB
Cheatsheet
Run
bouncer -c config/bouncer.toml # start
bouncer -c config/bouncer.toml -v # start (debug)
bouncer --version # version
bouncer --help # help
Podman
make build # build container image
make up # podman-compose up -d
make down # podman-compose down
make logs # podman logs -f bouncer
podman logs bouncer 2>&1 | grep -E 'INFO|WARN' # filtered logs
podman exec -it bouncer bash # shell into container
podman ps --filter name=bouncer # status
Develop
make dev # install with dev deps into .venv
make test # pytest
make lint # ruff check
make fmt # black + ruff --fix
make run # run with config/bouncer.toml
make clean # rm .venv, build artifacts
Client Auth
PASS <password> # authenticate (all networks)
Bouncer Commands
Inspection
/msg *bouncer HELP # list commands
/msg *bouncer STATUS # all network states
/msg *bouncer INFO libera # detailed network info
/msg *bouncer UPTIME # process uptime
/msg *bouncer NETWORKS # list networks
/msg *bouncer CREDS [network] # NickServ creds
/msg *bouncer CHANNELS [network] # joined channels + topics
/msg *bouncer CLIENTS # connected clients
/msg *bouncer BACKLOG [network] # message counts + DB size
/msg *bouncer VERSION # bouncer + Python version
Network Control
/msg *bouncer CONNECT libera # start disconnected network
/msg *bouncer DISCONNECT libera # stop network
/msg *bouncer RECONNECT libera # restart with fresh identity
/msg *bouncer NICK libera newnick # change nick
/msg *bouncer RAW libera WHOIS user # send raw IRC command
Config Management
/msg *bouncer REHASH # reload config file
/msg *bouncer ADDNETWORK name host=h port=N tls=yes nick=n channels=#a,#b
/msg *bouncer DELNETWORK name # remove network
/msg *bouncer AUTOJOIN net +#chan # add to autojoin
/msg *bouncer AUTOJOIN net +#chan key # add with channel key
/msg *bouncer AUTOJOIN net -#chan # remove from autojoin
NickServ
/msg *bouncer IDENTIFY libera # force IDENTIFY
/msg *bouncer REGISTER libera # trigger registration
/msg *bouncer DROPCREDS libera # delete all creds
/msg *bouncer DROPCREDS libera nick # delete one nick's creds
CertFP
/msg *bouncer GENCERT libera # generate cert (current nick)
/msg *bouncer GENCERT libera nick # generate cert (specific nick)
/msg *bouncer CERTFP # list all cert fingerprints
/msg *bouncer CERTFP libera # list certs for one network
/msg *bouncer DELCERT libera # delete cert (current nick)
/msg *bouncer DELCERT libera nick # delete cert (specific nick)
Account Farming
/msg *bouncer FARM # global farming status
/msg *bouncer FARM libera # network stats + trigger attempt
/msg *bouncer ACCOUNTS # list all stored accounts
/msg *bouncer ACCOUNTS libera # accounts for one network
Namespacing
#channel/network # channel on a specific network
nick/network # foreign nick on a specific network
own-nick # own nicks shown without suffix
/msg #libera/libera hello # send to #libera on libera network
/join #test/oftc # join #test on oftc
/join #a/libera,#b/oftc # comma-separated, different networks
Connection States
DISCONNECTED -> CONNECTING -> REGISTERING -> PROBATION (45s) -> READY
| State | What happens |
|---|---|
| CONNECTING | TCP + SOCKS5 + TLS handshake |
| REGISTERING | Random nick/user/realname sent to server |
| PROBATION | 45s wait (configurable), watching for K-line |
| READY | Switch to configured nick, join channels |
Auth Cascade
SASL EXTERNAL (cert + creds) > SASL PLAIN (creds) > NickServ IDENTIFY
Reconnect Backoff
5s -> 10s -> 30s -> 60s -> 120s -> 300s (cap)
PING Watchdog
Detects stale connections where TCP stays open but server stops responding.
ping_interval = 120 # silence before PING (seconds)
ping_timeout = 30 # wait for PONG (seconds)
Total detection time: ping_interval + ping_timeout (default 150s).
server-time (IRCv3)
Automatic -- no config needed. Timestamps injected on all messages. Backlog replay includes original timestamps.
Push Notifications
notify_url = "https://ntfy.sh/my-topic" # ntfy or generic webhook
notify_on_highlight = true # channel mentions
notify_on_privmsg = true # private messages
notify_cooldown = 60 # rate limit (seconds)
notify_proxy = false # use SOCKS5 for notifications
Only fires when no clients are attached.
Hot Reload
kill -HUP $(pidof bouncer) # reload config via signal
/msg *bouncer REHASH # reload config via command
Config Skeleton
[bouncer]
bind / port / password
client_tls / client_tls_cert # client-side TLS
client_tls_key # separate key file (optional)
captcha_api_key # NoCaptchaAI key (optional)
captcha_poll_interval / captcha_poll_timeout
probation_seconds / nick_timeout / rejoin_delay
backoff_steps / http_timeout
email_poll_interval / email_max_polls / email_request_timeout
cert_validity_days
ping_interval / ping_timeout # PING watchdog
notify_url / notify_on_highlight / notify_on_privmsg
notify_cooldown / notify_proxy # push notifications
farm_enabled / farm_interval # background account farming
farm_max_accounts
[bouncer.backlog]
max_messages / replay_on_connect
[proxy]
host / port
[networks.<name>] # repeatable
host / port / tls
nick / channels / autojoin
channel_keys # keys for +k channels
password # optional, IRC server PASS
Files
| Path | Purpose |
|---|---|
config/bouncer.toml |
Active config (gitignored) |
config/bouncer.example.toml |
Example template |
config/bouncer.db |
SQLite backlog (auto-created) |
{data_dir}/bouncer.pem |
Listener TLS cert (auto-created) |
{data_dir}/certs/{net}/{nick}.pem |
Client certificates (auto-created) |
Backlog Queries
-- recent messages
SELECT * FROM messages ORDER BY id DESC LIMIT 20;
-- per-network counts
SELECT network, COUNT(*) FROM messages GROUP BY network;
-- last seen state
SELECT * FROM client_state;
Source Layout
src/bouncer/
__main__.py # entry point, event loop
cli.py # argparse
config.py # TOML loader
irc.py # IRC message parse/format
namespace.py # /network encode/decode for multiplexing
proxy.py # SOCKS5 connector (local DNS, multi-IP, CertFP)
network.py # server connection + state machine + SASL
client.py # client session handler
cert.py # client certificate generation + management
captcha.py # hCaptcha solver via NoCaptchaAI
farm.py # background account farming
commands.py # bouncer control commands (/msg *bouncer)
notify.py # push notifications (ntfy/webhook)
router.py # message routing + backlog trigger + server-time
server.py # TCP listener
backlog.py # SQLite store/replay/prune