Wednesday, August 13, 2014

Howto: Setup web-based IRC on Ubuntu

I want a way for students to chat me when I'm in my office hours. My classes are online and I want to make it easy for remote students to reach me. I had some time to try different solutions and I found one that is very easy to use. I had a few constraints:

  1. Anonymous signin from the web. I don't want to have to create and delete accounts for students because that's a lot of work and, since I'm using my own server, I don't have access to the CIS AD server.
  2. Use a popular protocol. Just because students login on the web doesn't mean that I should login from the web. I want to have my choice of clients so that I can pick one that's easy for me to manage. 
  3. Using Ubuntu (of course)
So here's what I came up with. I started with ircd-hybrid. It's fairly simple to configure with a very readable configuration syntax. Install it:

apt-get install ircd-hybrid 

There are two files you will need to change first-thing:

/etc/ircd-hybrid/ircd.conf (the main configuration file)
/etc/ircd-hybrid/ircd.motd (the login message)

The ircd.conf file is fairly well documented. I setup the basic settings, naming my server and providing admin information. Because we'll be accessing this server over the web and because my webserver runs on the same machine I had to tweak the configuration somewhat. 

The irc daemon by default trusts clients connected from "localhost" (127.0.0.1). That's usually a very safe thing to do. In my case localhost should not be trusted so I altered the following section: 

auth {
        user = "*@127.0.0.1";
        spoof = "irc.lifealgorithmic.com";
        class = "users";
        flags = need_password, spoof_notice, no_tilde;
};

In this definition I use the "spoof" directive because I want to control what the domain name looks like in the client. In the default auth section I set a password:

auth {
        user = "*@*";
        class = "users";
        password = "SoooperSeeeeecretPaaaaasword";
};

This will keep random lurkers out because I can give my students the password in class. A determined person could watch my class or slides for the password but that would take more than a port scanner. If need be I can password protect the web interface. 

Now we need a web client. There happens to be a really nice and attractive one called KiwiIRC. It hasn't made it into Ubuntu yet but I hope it will someday. It's a very elegant program written in node.js. I read the installation instructions, but they need to be amended if you intend to run securely as a daemon. 

1. Install node.js and some components 

apt-get install npm

2. Create a user for kiwi. 

useradd -d /srv/kiwi -r kiwiuser

The user's home is in /srv/kiwi where I intend to install it. The kiwi user is a system user and doesn't (shouldn't) have a password. Create the home directory and make sure kiwi owns it:

mkdir /srv/kiwi
chown -R kiwiuser:kiwiuser /srv/kiwi 

3. Become kiwiuser and follow the installation instructions.

4. Make it an always thing. Until they throw upstart overboard we need to add a script to /etc/init. 

# This is /etc/init/kiwi.conf
# kiwi - The Kiwi web based IRC server

description "Kiwi server"

start on runlevel [2345]
stop on runlevel [!2345]

script
  HOME=/srv/kiwi
  export HOME
  cd /srv/kiwi
  exec /srv/kiwi/kiwi start
end script

exec /srv/kiwi/kiwi start

Now you can start kiwi with
service kiwi start

Unfortunately kiwi doesn't play nice with upstart and stopping the service must be done by hand. It's a small price to pay. Kiwi's configuration (found in config.js) is very simple. These lines matter if you're starting it as root: 

conf.user = "kiwiuser";
conf.group = "kiwiuser";

They tell kiwi to drop permissions, which it does. The daemon logs as it's own user so you will have to create a separate directory in /var/log to store the log file and give it proper permissions. Here's how you get kiwi to only connect to the local IRC server:

conf.outgoing_address = {
    IPv4: '127.0.0.1'
};

It won't be able to make connections anywhere else with that address. That's a good thing for me because I don't want my site to be abused. In the "conf.client" section you can set the default values the client gets. They can be overridden by the user or using HTML (which is rad). But the more interesting section to me was this group of directives: 

conf.restrict_server = "irc.lifealgorithmic.com";
conf.restrict_server_port = 6667;
conf.restrict_server_ssl = false;
conf.restrict_server_channel = "#web";

You can use these directives to force the way kiwi can connect to the server. This let's me put all my web clients into the "#web" jail if I want. It also keeps clever hackers from using HTML to override my defaults. The last step is to embed the widget onto your site. You can do that with an iframe element. Add HTTP arguments to control default values. Here's an example: 

<iframe frameborder="0" height="400" width="400px"
  src="http://irc.lifealgorithmic.com:7778/?theme=mini&amp;channel=#office"
></iframe>

Notice you can specify what channel to login to by default. Assuming you haven't put your users in the web jail you can use that to make widgets chat-room specific. That's what I want.