Archive

Old and new: Mixing irssi and iPhones for fun and no profit

Introduction

I use irssi for IRC and an iPhone for pocket Internets; These two choices are both excellent, but they're not terribly compatible - typing in irssi on an iPhone via SSH is quite slow and annoying.

Obviously the thing to do is run an iPhone IRC client, but then I'm signing in and out all the time and I have multiple nicknames - what I want is a way to be connected to the same IRC session as normal, but from my phone using the excellent IRC client Colloquy. By taking advantage of several different pieces of Free Software, this is entirely doable! When we're not connected to IRC, messages which trigger irssi's highlight will be forwarded to the iPhone as a Push Notification.

Preparation

These are the tools we are going to use to make this happen: - A patched irssi (don't worry though, the patch is tiny) - An irssi script (just some Perl really) - irssi-proxy - stunnel - Colloquy Mobile (from the iPhone App Store)

Throughout I will be assuming that you're running Ubuntu 10.04 (Lucid Lynx) as this is the currently most recent LTS release and thus most suited to servers. Also it's what I run, and this is my fun evening project :)

Although it will not be necessary to download it, I would like to note the original location of the patch and script that this method relies on. You can obtain both here.

Instead, we are going to install a patched irssi from one of my PPAs, but if you do not care for this idea, the above URL will let you build your own patched irssi and contains the colloquy_push.pl script.

Installation

These commands will install the patched irssi and the colloquy_push.pl script:

sudo add-apt-repository ppa:cmsj/irssi-colloquy-push
sudo apt-get update
sudo apt-get install irssi

(If you don't have add-apt-repository available, it's in the python-software-properties package).

Configuration

irssi-proxy

The first step is to load irssi-proxy. This is distributed as a plugin library in the irssi package, you can load it with:

/load proxy
/set irssiproxy_bind 127.0.0.1
/set irssiproxy_password PICKAGOODPASSWORD
/set irssiproxy_ports network1=31337 network2=31338 network3=31339

Obviously you'll need to replace PICKAGOODPASSWORD with a password, preferably a good one. Also you'll need to replace network1/network2/network3 with the names of the networks you've configured in irssi (which you can see with the command /network list) and switch them to different ports if you want.

Finally you should run /save so irssi writes out its config file with all of these changes. Et voila, we have a running proxy, but as you noticed, we forced it to listed on 127.0.0.1, so we can't yet connect to it from the Internet. The reason we've done this is that irssi_proxy is not able to directly offer encrypted connections. It would be a bad idea to allow all our proxy password and general IRC traffic to flow around unencrypted (even though many IRC server connections are unencrypted).

Stunnel

Stunnel is a very simple tool that lets you  add SSL support to anything listening on a TCP socket. To get started, install the stunnel4 package and edit /etc/default/stunnel4 and change ENABLED=0 to ENABLED=1.

Now we need to construct /etc/stunnel/stunnel.conf. The default contains various options we don't really care about, but one important one is the cert = line - we need an SSL certificate for this to work. You can either buy one or generate your own (a so-called "snake-oil" certificate). There are many guides to generating a .crt file and this is left as an exercise for the reader. With that file in place somewhere, edit stunnel.conf to point at it.

The final step for stunnel is to add port configurations. Jump to the bottom of the file and add a section like this for each of the ports irssi_proxy is listening on:

[myfirststunnel]
accept=123.123.123.123:31337
connect=127.0.0.1:31337

What we have done here is told stunnel to listen on our public IP on the same port that it will then connect to on 127.0.0.1. This might seem confusing, but I think it makes sense that the port numbers stay directly mapped between tunnels and proxy ports. Restart the stunnel4 service and you should see the appropriate ports being listened on.

colloquy_push.pl

This is the irssi script which glues all the magic together - it receives special commands from the iPhone version of Colloquy and uses those to pass on Push Notifications when necessary. To load it, type /script load colloquy_push.pl and you probably want to symlink /usr/share/irssi/scripts/colloquy_push.pl into ~/.irssi/scripts/autorun/.

Colloquy

Now configure a new IRC Connection in Colloquy on your iPhone. Enter its hostname/IP and the port you have stunnel listening on (the port settings are in Advanced) and enable SSL. Finally, set Push Notifications to On and you're done.

Shortcomings

The script, while excellent, has one or two drawbacks - it's not yet able to detect when you're watching irssi, so it may well send lots of notifications to your phone unnecessarily (I'm looking into expanding it to detect if you're running in screen/tmux and are attached), also it doesn't have any concept of sleeping hours, so you may get woken up by notifications! Nonetheless, this is an excellent way to use your awesome iPhone and not sacrifice the magnificence of irssi!


GStreamer thread oddness

I sometimes find myself in a place where there are a number of Icecast streams going out at once and I'm interested in finding better ways of monitoring these. It seems like a nice option would be a window showing a visualisation of each stream. I quickly whipped up some python to do this, but it almost always locks up when I run it, but I'm not sure if I've done something fundementally wrong or if I've found a bug somewhere. If you are a gstreamer expert, please take a look a this code and let me know what I should do next! If you know a gstreamer expert, please try and bribe them to read this post ;)


Lifesaver for Maverick

I think that enough of the planets have aligned in the shape of a failboat that I have been able to successfully upload a source package of Lifesaver to its PPA for Maverick. I might be wrong though, we'll find out shortly when Launchpad processes the ridiculous output of several ridiculous tools. Seriously Debian/Ubuntu developers, please sort this out. I really don't care about the intricacies of your workflow - just make it easy for me to be an upstream developer pushing packages into a PPA. Don't make me wade through a sea of hundreds of build tools, dscs, origs, diffs, etc. Just make a bundle and shove it into Launchpad. One command. bzr2ppa in a working directory. Done. I'm quite sure the failures I had were due either to my incorrect use of some tool or other, or an incorrect setup, but I contend that I shouldn't have to care. Such a tool just needs to know that there's a debian/ that works and a PPA waiting. Make it happen. Go. Now. Are we there yet? GRRRRRRRRRRRRRR! (Rant over, the package uploaded and will presumably build shortly, enjoy!)


Terminator 0.95 released!

This release is mostly to bring a couple of important compatibility fixes with the newest pre-release of VTE, but we also have some updated translations, improved error handling and two new features for you. The features are a URL handler plugin for Maven by Julien Nicolaud and a DBus server that was the result of some work with Andrea Corbellini - for now the only thing this is useful for is opening additional Terminator windows without spawning a new process, but we'll be exploring options in the future to allow more control and interaction with Terminator processes.


Adventures in Puppet

I'm very slowly learning and exploring the fascinating world of Puppet for configuration management. As I go I'm going to try and blog about random things I discover. Partially for my own future reference, partially to help me crystalise my knowledge and partially to help you. The first post is coming up immediately, I'm just writing this post as an opening bookend :)


Adventures in Puppet: concat module

R.I. Pienaar has a Puppet module on github called "concat". Its premise is very simple, it just concatenates fragments of text together into a particular file. I'm sure that a more seasoned Puppet veteran would have had this running in no time, but since it introduced some new concepts for me, I thought I'd throw up some notes of how I'm using it. I was particularly interested in an example usage I saw which lists the puppet modules a system is using in its /etc/motd, but because of the way Ubuntu handles constructing the motd, I needed to slightly rework the example. In Ubuntu, the /etc/motd file is constructed dynamically when you log in - this is done by pam_motd which executes the scripts in /etc/update-motd.d/. One of those scripts (99-footer) will simply append the contents of /etc/motd.tail to /etc/motd after everything else - my example will take advantage of this. If you are already using motd.tail, you could just have this puppet system write to a different file and then drop another script into /etc/update-motd.d/ to append the contents of that different file. This is what I did:

  • git clone http://github.com/ripienaar/puppet-concat.git
  • Move the resulting git branch to /etc/puppet/modules/concat and add it to my top-level site manifest that includes modules
  • Create a class to manage /etc/motd.tail. In my setup this ends up being /etc/puppet/manifests/classes/motd.pp, which is included by my default node, but your setup is probably different. This is what my class looks like:
    class motd {
           include concat::setup
           $motdfile = "/etc/motd.tail"

           concat{$motdfile:
                   owner => root,
                   group => root,
                   mode => 644
           }

           concat::fragment{"motd_header":
                   target => $motdfile,
                   content => "\nPuppet modules: ",
                   order => 10,
           }

           concat::fragment{"motd_footer":
                   target => $motdfile,
                   content => "\n\n",
                   order => 90,
           }
    }

    # used by other modules to register themselves in the motd
    define motd::register($content="", $order=20) {
       if $content == "" {
          $body = $name
       } else {
          $body = $content
       }

       concat::fragment{"motd_fragment_$name":
          target  => "/etc/motd.tail",
          content => "$body ",
          order => $order
       }
    }

So that's quite a mouthful. Let's break it down: * We have to include concat::setup so the concat module can...set... up :) * We then set a variable pointing at the location of the file we want to manage * We then instantiate the concat module for the file we want to manage and set properties like the ownership/mode * We then call the concat::fragment function for two specific fragments we want in the output - a header and a footer (although I do this on a single line, so it's the phrase "Puppet modules" and "\n\n" respectively). They're forced to be header/footer by the "order" parameter - by making sure we use a low number for the header and a high number for the footer, we get the layout we expect. * Outsite this class we define a function motd::register which other modules will call and the content they supply will be handed to concat::fragment with a default order parameter of 20 (which is higher than the value we used for the header and lower than the footer one).

Finally, in each of my modules I include the line: motd::register{"someawesomemodule":}

and now when I ssh to a node, I see a line like: Puppet modules: web ssh

It's a fairly simple little thing, but quite pleasing and from here out it's almost zero effort - just adding the motd::register calls to each module.


Adventures in Puppet: Tangled Strings

I am trying to do as much management on my new VM servers as possible with Puppet, but these are machines I still frequently log on to, and not everything is managed by Puppet, so it's entirely possible that in a fit of forgetfulness I will start editing a file that Puppet is managing and then be annoyed when my changes are lost next time Puppet runs. Since prior preparation and planning prevents pitifully poor performance, I decided to do something about this. Thus, I present a VIM plugin called TangledStrings, which I'm distributing as a Vimball (.vba) you can download from its project page on Launchpad. For more information on Vimball formatted plugins, see this page. To install the plugin, simply:

  • vim tangledstrings.vba
  • Follow the instructions from Vimball to type: :so %

By default, TangledStrings will show a (configurable) warning message when you load a Puppet-owned file: This message can be disabled, and you can choose to enable a persistent message in the VIM status line instead: (or you could choose to enable both of these methods). For more information, see the documentation included in the Vimball which you can display with the VIM command:

:help TangledStrings

Suggestions, improvements, patches, etc. are most welcome! Email me or use Launchpad to file bugs and propose merges.


TangledStrings 1.0 released!

I'm very pleased to announce the release of 1.0 of TangledStrings, a VIM plugin to help Puppet users avoid the confusion and frustration of editing a file that Puppet is managing and subsequently losing ones changes as it is replaced by Puppet's version.


Delightful Hybridisation

I've probably mentioned before that I really like the music of Hybrid, so I figured I'd pimp some stuff of theirs that's floated onto the web recently:

  • A couple of videos from their live set at Glastonbury this year (I'm very gutted that I didn't make it to see them)
  • Their latest Frisky Radio mixtape just hit Soundcloud, here.

Enjoy!


Dream a little dream of me

Last night I had a lovely meal out and then saw Inception with Rike and some friends. I've really enjoyed all of Christopher Nolan's previous films and I think he does an excellent job of creating surprising and compelling stories. I'm not really going to say anything about the plot, other than to advise you avoid reading anything about it until you've seen it - not because there's anything particularly secret, but because it's nice to not have any preconceptions about what might happen. For me, the best films have me leaving the cinema totally caught up in their world, my mind reeling with the possibilities of what they have explored. Inception achieved this, and I want to see it again, although preferably at home on Bluray so I can hear every word of dialogue properly - a surprising shortcoming of one of London's flagship cinemas.