diff options
| -rw-r--r-- | README.md | 138 |
1 files changed, 115 insertions, 23 deletions
@@ -4,11 +4,11 @@ A lean XMPP AI chatbot in C. It joins MUC rooms, logs messages, answers `@bot` commands via an OpenAI-compatible LLM HTTP API, and runs `@scriptname` commands backed by local scripts. -A C reimplementation of the Python `bot.py` in the parent directory, -written in the suckless spirit: one source file, one library + +Inspired by the suckless spirit: one source file, one library dependency (OpenSSL), fixed buffers, no runtime config parser. -There is **no end-to-end / OMEMO encryption**. Transport is still +There is **no end-to-end OMEMO/OTR encryption**. Transport is still encrypted: STARTTLS for the XMPP connection, HTTPS for the LLM API. ## Build @@ -27,13 +27,23 @@ Edit `config.h` (not the `.def`) to set your server, rooms and model. Non-secret settings live in `config.h`. Recompile after changing it. -Secrets are read from the environment, never stored on disk by the bot: +Secrets are read from the environment, never stored on disk by the bot. +Export them by hand: ```sh export XMPP_PASSWORD='the-bot-account-password' export LLM_API_KEY='sk-...' ``` +Or use the bundled `start` script, which sets both variables and then +execs the bot. Copy the template, fill in your secrets, and lock it +down so only you can read it: + +```sh +cp start.sample start +chmod 700 start +``` + `instruction.md` holds the system prompt; it is read once at startup. On a fresh checkout, copy `instruction.md.sample` to `instruction.md`, then edit it and restart to change the bot's behaviour. @@ -80,6 +90,9 @@ Run from the directory containing `instruction.md` and `config.h`: ./xmppcb ``` +If you set up the `start` script above, run `./start` instead — it +exports the secrets, `cd`s into this directory and execs the bot. + It reconnects automatically after a dropped connection. On an authentication failure it exits with status 1 (no retry loop). Logs go to stderr. Per-room chat history is appended to @@ -143,29 +156,110 @@ do not let scripts print secrets. `CMD_DIR` and `CMD_TIMEOUT_SEC` are in ## Run under a supervisor -The bot does not daemonise. Use a process supervisor so it restarts -and starts at boot. +The bot does not daemonise and does not restart itself after it exits. +Use a process supervisor so it restarts on crash and comes up at boot. +Each example runs the `start` script, so no secrets land in the +supervisor config. Replace `/home/xmppcb/xmppcb` and the `xmppcb` +user/group with yours. + +The scripts below are example templates, not tested on every release — +check them against your OS version before relying on them. + +### FreeBSD (rc.d) + +`/usr/local/etc/rc.d/xmppcb`: + +```sh +#!/bin/sh +# PROVIDE: xmppcb +# REQUIRE: NETWORKING +# KEYWORD: shutdown +. /etc/rc.subr + +name=xmppcb +rcvar=xmppcb_enable +load_rc_config $name + +: ${xmppcb_enable:="NO"} +: ${xmppcb_user:="xmppcb"} +: ${xmppcb_dir:="/home/xmppcb/xmppcb"} + +pidfile="/var/run/${name}.pid" +command="/usr/sbin/daemon" +command_args="-r -P ${pidfile} -u ${xmppcb_user} ${xmppcb_dir}/start" + +run_rc_command "$1" +``` -systemd (`/etc/systemd/system/xmppcb.service`): +`chmod +x` it, then `sysrc xmppcb_enable=YES` and +`service xmppcb start`. `daemon -r` restarts the bot if it dies. -```ini -[Unit] -Description=xmppcb XMPP AI bot -After=network-online.target +### OpenBSD (rc.d) + +`/etc/rc.d/xmppcb`: + +```sh +#!/bin/ksh +daemon="/home/xmppcb/xmppcb/start" +daemon_user="_xmppcb" + +. /etc/rc.d/rc.subr +rc_bg=YES +rc_cmd $1 +``` -[Service] -WorkingDirectory=/home/youruser/xmpp-bot/xmppcb -ExecStart=/home/youruser/xmpp-bot/xmppcb/xmppcb -Environment=XMPP_PASSWORD=... -Environment=LLM_API_KEY=... -Restart=always -RestartSec=10 +`chmod +x` it, then `rcctl enable xmppcb` and `rcctl start xmppcb`. +OpenBSD's rc.d starts the bot at boot but does not respawn it on +crash; pair it with a cron check or a supervisor if you need that. -[Install] -WantedBy=multi-user.target +### OpenRC + +`/etc/init.d/xmppcb`: + +```sh +#!/sbin/openrc-run +description="xmppcb XMPP AI bot" +command="/home/xmppcb/xmppcb/start" +command_user="xmppcb:xmppcb" +supervisor="supervise-daemon" +respawn_delay=10 + +depend() { + need net +} +``` + +`chmod +x` it, then `rc-update add xmppcb default` and +`rc-service xmppcb start`. `supervise-daemon` handles the restart. + +### sysvinit + +sysvinit respawns processes listed in `/etc/inittab`. Add one line: + +``` +xb:2345:respawn:/bin/su -s /bin/sh -c /home/xmppcb/xmppcb/start xmppcb +``` + +Then run `telinit q` to reload. The `respawn` action gives you both +boot start and restart-on-crash without a separate init script. + +### runit + +`/etc/sv/xmppcb/run`: + +```sh +#!/bin/sh +exec chpst -u xmppcb:xmppcb /home/xmppcb/xmppcb/start +``` + +`chmod +x` it, then link the service into the scan directory: + +```sh +ln -s /etc/sv/xmppcb /var/service/ ``` -Prefer an `EnvironmentFile=` with mode 600 over inline secrets. +(some distributions use `/etc/service` or `/run/runit/service`). +runit supervises and restarts the bot automatically. ## Notes and limitations @@ -184,9 +278,7 @@ xmppcb/ ├── config.def.h config template (committed) ├── config.h your config (copied from .def, gitignored) ├── instruction.md.sample system prompt template (committed) -├── instruction.md system prompt in use (gitignored) ├── start.sample run-script template (committed) -├── start run script exporting the secrets (gitignored) ├── cmd/ @scriptname command scripts (weather, uptime, fx) ├── makefile └── history/ per-room chat logs (generated, gitignored) |
