Ilmari Lauhakangas

IRC bouncer setup with soju and gamja on Caddy web server

Categories: IRC

Soju is an IRC bouncer and gamja is a web client that works nicely with it. This article describes how to make them work with Caddy web server.

The file paths mentioned may vary depending on the operating system or Linux distribution used. I set this up using the current stable soju release (0.5.2) provided by Arch Linux.

Install gamja into your web server path:

git clone
cd gamja
npm install --production

You can optionally add a config.json file in the gamja directory to define various settings. Note that you have to remove the comments from the example provided in the gamja site as they are not valid JSON. For this particular setup, there is no need to define a “url” option as the default “/socket” will be used.

In your DNS records, define a subdomain.

Example configuration block for Caddy: {
    encode gzip
    root * /var/www/gamja
    reverse_proxy /socket

Replace the port as you want.

You might want to add basicauth for access control.

/etc/soju/config has by default

db sqlite3 /var/lib/soju/main.db
message-store fs /var/lib/soju/logs/

Run sojuctl to create an admin user:

sudo sojuctl -config /etc/soju/config create-user username -admin

This will modify /var/lib/soju/main.db, adding the new admin user. Save the password as it will be used when logging in via gamja.

In the next release, the admin user creation will be done with the sojudb command instead.

The systemd service file provided by the Arch Linux package did not work for me, so I adapted Damjan Georgievski’s example service, resulting in a /etc/systemd/system/soju.service that looked like this:

Description=soju IRC bouncer service
Documentation=man:soju(1) man:sojuctl(1)

ExecStart=/usr/bin/soju --config /etc/soju/config -listen ws+insecure://
ExecReload=/bin/kill -HUP $MAINPID


Update 21 March 2023: soju now ships with an example service file soju/contrib/soju.service thanks to Damjan.

Enable and start the service with

sudo systemctl enable --now soju

Now you can navigate to your subdomain with a web browser and log into gamja with the admin user name and password.

In the gamja interface, click “bouncer” in the top left to attach to the bouncer. Click “Add network” in the top right to add an IRC network. You can say /msg BouncerServ help to see all the commands you can use to interact with the bouncer. The commands are also documented in soju’s manual.

Regarding the first steps, note what the soju manual says in the description:

When joining a channel, the channel will be saved and automatically joined on the next connection. When registering or authenticating with NickServ, the credentials will be saved and automatically used on the next connection if the server supports SASL.

To conveniently access the log text files with my normal user, I use bindfs and FUSE. I avoid having to mess around with permissions by adding a line like this to /etc/fstab:

/var/lib/soju/logs /home/myuser/sojulogs fuse.bindfs force-user=myuser,force-group=myuser,create-for-user=soju,create-for-group=soju,create-with-perms=g=rD,chgrp-ignore,chown-ignore,chmod-ignore 0 0

and creating the corresponding directory to bind to and mounting it with sudo mount /home/myuser/sojulogs. If you are interested in trying this out, you can start by checking the distro availability of bindfs from Repology.

Thanks to everyone who helped me on #soju at Libera Chat and Caddy server forum!