Making IRC work like modern messengers using WeeChat, Pushbullet and more

Sat, Aug 19, 2017

XKCD 1782: Team Chat

Background

Despite the influx of modern messengers with features such as push notifications, websockets, message history and more, IRC is still going strong. During the WannaCry ransomware attacks, I found myself joining various IRC channels to stay in touch with the latest developments. Given I wanted something more permanent than a browser IRC client, I looked into clients for Windows and Android and was met with disappointment: unsurprisingly, the feature sets of these clients were a downgrade from modern messengers, and a modern user interface was too much to ask for.

The main requirement for me was finding a decent way to stay in touch with IRC channels on my Android phone. There were two main features I needed: push notifications if I was mentioned, and keeping message logs by staying connected (commonly known as a bouncer). The majority of Android IRC clients keep connected to IRC channels by running a background service which consumes CPU and network resources (and therefore battery power) even when the phone is idle. This was too big of a sacrifice to make just to meet these features.

One possible solution I found at the time was IRCCloud, a cross-platform, cloud-based IRC platform. However, this was far from perfect as on the free plan, you are: limited to two maximum connections (what messenger does this?); only able to stay connected while inactive for only two hours (making it pointless as a bouncer); not allowed to connect to password-protected servers (!). Additionally, the server side is not open source, and message logs are not encrypted.

Eventually, I settled on rolling a DIY solution with WeeChat, an open source, terminal-based IRC client with a suite of features and plugin support, meeting all of my feature requirements. WeeChat not only acts as a bouncer to keep message logs (logging messages permanently to a file), but also acts as an intermediary server allowing third party apps/WeeChat clients (called relays) to connect to WeeChat over HTTPS. Below is an overview of what accompanied WeeChat:

  • Weebullet, a WeeChat plugin which sends push notifications to any Pushbullet-supported device (e.g., Android, iOS, etc.) whenever your nick is mentioned or receive any other IRC notifications
  • detach_away, a WeeChat plugin which sets whether you're away based on the number of IRC clients connected
  • Weechat Android, an Android client for WeeChat with a great user interface and functionality
  • Glowing Bear, a web client for WeeChat which also has a great user interface

Installing WeeChat

(Note: For an IRC server constantly connected to the Internet, it is important to consider where to install it. A Raspberry Pi connected to your home internet may not be the most reliable solution. It is recommended to invest in a very cheap VPS with DigitalOcean, or take advantage of Amazon AWS' free tier.)

For Ubuntu 16.04, the binary installation process is simple, using apt-get by following the instructions at the bottom of this page. In order to have WeeChat running 24/7, create a systemd service instructing Ubuntu to use tmux during the boot process to start a detached terminal session under your user (ircuser) by creating /etc/systemd/system/weechat.service with the following file contents:

[Unit]
Description=Weechat IRC Client (in tmux)

[Service]
User=ircuser
Type=forking
ExecStart=/usr/bin/tmux -2 new-session -d -s weechat /usr/bin/weechat
ExecStop=/usr/bin/tmux kill-session -t weechat

[Install]
WantedBy=multi-user.target

Next, activate this service by running sudo systemctl enable weechat, and start WeeChat by running sudo systemctl start weechat. Doing so for the first time creates a folder of configuration files under the home directory of the user at /home/ircuser/.weechat.

Configuring WeeChat

Encryption

With WeeChat installed, the first thing to do is to set up a certificate to use for TLS. We can get one for free from Let's Encrypt with one caveat: a certificate lasts for 90 days, so we need to set up a script to renew it automatically. To do so, I followed a blog post here by Aaron Toponce. To summarise the blog post, here are the steps you need to do:

  1. Get a domain or subdomain for you to tie the certificate to, point it to your server via an A record, and ensure that ports 80 and 443 are open and a web server is running (even if it's with a blank web page).

  2. Install Certbot, which manages Let's Encrypt certificates.

  3. Where example.com is the domain which will be tied to your certificate and [email protected] is a valid email address you own, run sudo certbot certonly --standalone -d example.com -m [email protected]. This will create certificate files underneath /etc/letsencrypt/live/example.com, accessible only to the root user.

  4. As WeeChat should not be run under the root user, the keys must be moved underneath a folder WeeChat can access, so run the following command, where ircuser is the user you use to start WeeChat in the systemd file above:

    sudo cat /etc/letsencrypt/live/example.com/privkey.pem \
        /etc/letsencrypt/live/example.com/fullchain.pem > \
        /home/ircuser/.weechat/ssl/relay.pem
    sudo chown ircuser:ircuser /home/ircuser/.weechat/ssl/relay.pem
    
  5. Set a bash script to renew the certificate under /usr/local/sbin/renew-weechat.sh:

    #!/bin/bash
    
    sudo certbot renew -q
    sudo cat /etc/letsencrypt/live/example.com/privkey.pem \
        /etc/letsencrypt/live/example.com/fullchain.pem > \
        /home/ircuser/.weechat/ssl/relay.pem
    sudo chown ircuser:ircuser /home/ircuser/.weechat/ssl/relay.pem
    
  6. Set up this script to run every Monday at midnight by running sudo crontab -e and appending the following:

    0 0 * * 1 /usr/local/sbin/renew-weechat.sh
    
  7. Start weechat by running weechat enter the following commands, where 8443 is the open port which you would like to your relays to connect to in order to interact with WeeChat:

    /relay sslcertkey
    /relay add ssl.weechat 8443
    

Server Defaults

We first want to configure WeeChat with some default settings. A good overview on WeeChat commands can be found on the quick start guide. To give you an idea of the default server settings, use tmux a -t weechat to attach to your terminal if you have already done so, and get all the default server settings by running /set irc.server_default.*. Here are the main settings I've set:

  • /set irc.server_default.realname "" - Sets your real name to blank
  • /set irc.server_default.username "JohnSmith" - Sets your IRC username to JohnSmith
  • /set irc.server_default.nick "JohnSmith,JohnSmith1 - Sets your IRC nick to JohnSmith, but if taken, it tries JohnSmith1, etc.*
  • /set irc.server_default.msg_quit "Goodbye!" - Sets your quit message to Goodbye!, which also means it doesn't send the default which is your WeeChat version number (which isn't ideal for security)
  • /set irc.server_default.msg_part "Parted" - Same as above, but for parting

* The difference between realname, username and nick is explained well on StackOverflow.

These server defaults will be automatically applied to any servers added later on.

Additionally, I personally use a proxy (documentation), where the proxy name can be applied by default using /set irc.server_default.proxy "proxyname".

Adding Servers

To add servers, the quick start guide provides short and sweet instructions. The options I pay attention to (excluding the ones mentioned in the server defaults above) are: addresses + ssl (using encryption where possible), autoconnect, autojoin, command (for authentication over nickserv), sasl_username/sasl_password (if supported), ssl_fingerprint (if a server rolls their own certificate which needs to be manually trusted) and proxy (like above).

Notifications via Pushbullet

In order to receive notifications, we will be using the Pushbullet API. To get started, sign up with them, install the apps, set up end-to-end encryption on your devices, and go to your account page and create an access token (copy it somewhere safe!).

Then, install the Weebullet plugin by following the instructions here (keeping in mind that ~ should be replaced with /home/ircuser). Finally, set the following settings:

  • ignored_channels should be a comma-separated list of channels which notifications will not be sent for (you can include entire servers and private messages by specifying the relevant names without prepending #)
  • ignore_on_relay should be 1 as connected relay clients should have their own notification system; you only want to be notified when no relay clients are connected

Automatic Away

It makes sense to automatically set yourself to away if no relay clients are connected. The detach_away plugin can handle this and also lets you set a default away message (which I use to let people know that I get notified if they mention me). To install this plugin, do the following:

  1. Save the script at https://weechat.org/scripts/source/detach_away.py.html/ as /home/ircuser/.weechat/python/detach_away.py
  2. Run /script load detach_away.py
  3. Run /set plugins.var.python.detach_away.message = "No bouncer clients attached; @ me to send me a notification" to optionally set an away message

Now, whenever your last relay client disconnects, you will automatically be set to away with your away message displayed whenever someone runs /whois on your nick.

Warning: ensure that irc.look.display_away is set to local or off. If it is set to channel, a message will be posted to all channels every time you disconnect/connect clients, which may get you banned from channels for spam.

Installing Relay Clients

With WeeChat now set up, relay clients are needed to act as IRC clients by communicating with WeeChat.

  • For web, I use Glowing Bear, which has a modern UI (with basic themes and font customisation), lightweight feel, and useful features such as nick auto-complete on pressing tab.
  • For Android, I tried the Glowing Bear app, but uninstalled it immediately as it turned out to be a web app packaged inside an Android app, therefore having slow performance and a UI not optimised for mobile screens. Instead, I now use the the developer version (which is regularly updated) of WeeChat Android, which is the perfect Android client!

Known Issues

Despite this being a moderately complex setup, I have only experienced one issue: when the certificate is renewed, the certificate file is replaced, but WeeChat does not automatically load the changed file, leading to certificate errors. My current temporary fix is to SSH into the server and run /relay sshcertkey to reload the certificate. However, a permanent fix does exist, which involves:

  • running Weechat without SSL;
  • blocking Weechat's port access to the Internet;
  • running a web server which has Let's Encrypt integration (such as Caddy) exposed to the Internet;
  • configuring the web server to proxy Weechat using WebSockets as instructed here.

This technique passes the responsibility of handling certificates to the web server, where solutions to automatically reload certificates are much more trivial. WebSocket connections must be supported by the relay clients for this technique to work but fortunately, Glowing Bear and WeeChat Android both support this.

Conclusion

Configuring this setup without a single guide to work from took several hours of breaking and fixing things, however I am extremely happy with the end result. Despite the initial work this required, no maintenance is required on this setup other than ensuring that WeeChat is kept up-to-date with the latest security patches and ensuring certificates are being renewed.

There are many steps to build this setup, so if you have any feedback or questions, feel free to tweet me @KelvZhan and/or leave a comment below!

← Back to Blog