Soju User Delete Hash
I have recently switched from ZNC to Soju as my IRC bouncer. I already like it quite a bit. No more manually maintaining a configuration file for my various IRC connections.
On Debian 13 (trixie), it is quite straightforward the setup is. Here are some example commands that show how straightforward it is to set it up.
sudo apt-get update
sudo apt-get -y install soju
sudo sojuctl user create -username soju -password YOUR_SOJU_PASSWORD
sudo sojuctl user run soju network create -name bnc1 -addr irc.libera.chat -nick YOUR_NICK -pass YOUR_NICK_PASSWORD
The above commands installs and configures Soju 0.9.0 on Debian 13.2. Note that YOUR_SOJU_PASSWORD is a placeholder for a new password you must choose for your Soju user. Then, on your IRC client, you can connect to Soju and connect to IRC networks via it. For example, here's how we can connect to Soju from Irssi:
/network add -nick YOUR_NICK -user soju/bnc1 net1
/server add -tls -network bnc1 YOUR_SOJU_HOST 6697 YOUR_SOJU_PASSWORD
/connect net1
You can also set up multiple connections to IRC networks via the
same instance of Soju. All you need to do is repeat the Soju
commands above to create new networks
say bnc2, bnc3, etc. and then repeat the
configuration for your IRC client with new network names,
say, net2, net3. These network names are
completely user-defined names, so you could name them anything you
want. The names bnc2, net2, etc. here are
only examples.
One thing that caught my attention while creating and deleting Soju users was that the delete command asks for a confirmation, like so:
$ sudo sojuctl user delete soju To confirm user deletion, send "user delete soju 4664cd" $ sudo sojuctl user delete soju 4664cd deleted user "soju"
That confirmation token 4664cd for a user never
changes, no matter how many times we create or delete it. The
confirmation token is not saved in the Soju database, as can be
confirmed here:
$ sudo sqlite3 -table /var/lib/soju/main.db 'SELECT * FROM User' +----+----------+--------------------------------------------------------------+-------+----------+------+--------------------------+---------+--------------------------+--------------+ | id | username | password | admin | realname | nick | created_at | enabled | downstream_interacted_at | max_networks | +----+----------+--------------------------------------------------------------+-------+----------+------+--------------------------+---------+--------------------------+--------------+ | 1 | soju | $2a$10$yRj/oYlR2Zwd8YQxZPuAQuNo2j7FVJWeNdIAHF2MinYkKLmBjtf0y | 0 | | | 2026-02-16T13:49:46.119Z | 1 | | -1 | +----+----------+--------------------------------------------------------------+-------+----------+------+--------------------------+---------+--------------------------+--------------+
Surely, then, the confirmation token is derived from the user definition? Yes, indeed it is. As can be confirmed from the source code here. Quoting the most relevant part from the source code:
hashBytes := sha1.Sum([]byte(username))
hash := fmt.Sprintf("%x", hashBytes[0:3])
Indeed if we compute the same hash ourselves, we get the same token:
printf soju | sha1sum | head -c6; echo
4664cd
This allows us to automate the two step Soju user deletion process into a single command:
sudo sojuctl user delete soju "$(printf soju | sha1sum | head -c6)"
But of course, the implementation of the confirmation token may change in future and Soju helpfully outputs the deletion command with the confirmation token when we first invoke it without the token, so it is perhaps more prudent to just take that output and feed it back to Soju, like so:
sudo sojuctl $(sudo sojuctl user delete soju | sed 's/.*"\(.*\)"/\1/')