Connect / Self-hosting
Run your own Slirc
Slirc runs as two containers on a private network behind Caddy. Bun serves the app, and Ergo handles chat. This guide takes you from a fresh Linux server to your first message.
Prefer hosted? We can run Slirc for you at yourdomain.slirc.org, from €29/month.
The Elastic License 2.0 lets you run Slirc for your own group. Hosting it for others requires permission from the author.
What you need
- A Linux server with rootless Podman,
podman-compose, Git and just. Slirc runs on a 2 vCPU, 4 GB box with room to spare. The Ergo imageghcr.io/bitbonsai/slirc-ergo:v2.19.1ships for ARM64 and x86_64 under one tag; Podman picks the right one. - A domain. Point
app.yourdomainat the server.docs.yourdomainand the bare domain are optional. - Caddy on the host for TLS.
- A free Resend account to deliver sign-in links.
- Your own machine with Git and just for deploys. Deploys push a committed tree and reset the server checkout to that exact commit, so the server never holds uncommitted code.
1. Clone and set your host
On your machine:
git clone https://github.com/bitbonsai/slirc
cd slirc
Open justfile and set the SSH host, checkout path, and config directory at the top to your own values. Every recipe below uses them.
2. Config on the server
Slirc keeps secrets out of git. Two files live in the config directory on the server, both mode 0600:
ssh yourserver
mkdir -p ~/.config/slirc && chmod 700 ~/.config/slirc
~/.config/slirc/env is the app's environment:
APP_HOST=app.yourdomain
OWNER_NICK=yournick
USERS_JSON={"yournick":"you@example.com"}
IRC_PASSWORDS_JSON={"yournick":"a-long-random-password"}
ERGO_OPER_USER=slirc-org
ERGO_OPER_PASS=another-long-random-password
RESEND_API_KEY=re_...
RESEND_FROM=Slirc <slirc@yourdomain>
VAPID_CONTACT=mailto:you@example.com
Optional keys: GIPHY_API_KEY for GIPHY search, HELP_API_KEY and HELP_MODEL for the help bot and natural-language reminders, WELCOME_MODEL for the welcome helper (see below), SLIRC_HELPERS_ENABLED=false to run without the help, remind, poll, and welcome helpers. Reminder forms such as in 20m stretch, tomorrow 9:00 pick up cake, list, and cancel 3 still work without a model.
The welcome helper sits in #open-chat. When someone joins before verifying their email, it posts three short lines addressed to them: what the room is, that @help sends a tour by DM once they verify, and three links worth knowing. For the next fifteen minutes it answers up to two follow-ups from the docs, then asks them to verify. Replies use the same HELP_API_KEY and HELP_BASE_URL as the help bot; WELCOME_MODEL picks the model and falls back to HELP_MODEL. Without a key the helper skips the model and goes straight to the verify line. Each nick is greeted at most once a day, and the greetings go through Ergo like any message, so IRC clients see them too.
~/.config/slirc/ergo.yaml is Ergo's config. Start from the one in the repo:
scp ergo/ergo.example.yaml yourserver:~/.config/slirc/ergo.yaml
Then edit two things in it. Set network.name and server.name to your domain. Replace the password hash of the slirc-org oper with one for the ERGO_OPER_PASS you chose:
podman run --rm -it ghcr.io/bitbonsai/slirc-ergo:v2.19.1 ergo genpasswd
Keep accounts.authentication-enabled: true, keep the slirc-org oper class as it is, and keep 10.0.0.0/8 in ip-limits.exempted. Every browser reaches Ergo through the app's address, so per-IP limits would lock everyone out at once.
3. Caddy
Copy caddy/slirc.caddy to your Caddy sites directory and replace slirc.org with your domain and the checkout paths with yours. The app block is the one that matters:
app.yourdomain {
handle_path /webirc {
reverse_proxy 127.0.0.1:8067
}
handle {
reverse_proxy 127.0.0.1:9010 {
lb_try_duration 20s
}
}
}
Port 8067 is Ergo's WebSocket listener, 9010 is the app. Both bind to localhost only. Reload Caddy.
4. Bootstrap
Back on your machine, with a clean tree:
just bootstrap
This pushes main, resets the server checkout to it, creates the slirc network and the three volumes, starts Ergo, then builds and starts the app. The app registers your account with Ergo from USERS_JSON and IRC_PASSWORDS_JSON, creates #open-chat and #help, and starts the helpers. Check it:
just status
just logs app
The first line you want in the log is app listening on :8080.
5. First sign-in
Open https://app.yourdomain, type the email from USERS_JSON, and open the link Resend delivers. That account is the owner: it can create channels, invite people, and connect agents and bots. Everyone else joins with an email; see Getting started.
Day to day
just deploy # tests, then rebuild and recreate the app; Ergo keeps running
just deploy-ergo # recreate Ergo; the app keeps running
just deploy-docs # publish the docs site, if you serve one
just logs ergo
deploy refuses to run if Ergo restarted underneath it, and deploy-ergo refuses if the app did.
Backups
Three things hold state:
slirc-org-data, the volume with the app's SQLite database (accounts, sessions, channel metadata, uploads).slirc-org-ergo-data, the volume with Ergo's history and account database.~/.config/slirc/, the two config files, which hold every secret.
Copy the config directory with scp or your usual file backup. For the volumes, podman volume export slirc-org-data > app-data.tar writes a tarball you can move off the box, and podman volume import restores it. Ergo writes its database while running, so stop the Ergo container before exporting slirc-org-ergo-data, or follow the copy guidance in the Ergo manual for a live copy. The app has no backup recipe yet; a cron line around the two exports is enough.
When something is off
- "Reconnecting…" in the browser after a burst of joins. The
10.0.0.0/8exemption is missing fromergo.yaml. Add it andPOST /v1/rehashfrom inside the app container, or runjust deploy-ergo. owner credentials are missingon start.OWNER_NICKis not a key in bothUSERS_JSONandIRC_PASSWORDS_JSON.- Sign-in links never arrive. Check
RESEND_FROMis a verified sender on your Resend account, thenjust logs appfor the send error. - Ergo logs
read ircd.yaml: is a directory. Theergo.yamlfile was missing when the container started, and the bind mount created a directory in its place. Remove that directory, restore the file, recreate Ergo.
