Skip to content

Yet another way to get Irssi notifications on your Linux desktop

One of the things lacking (in my opinion at least) when using Irssi and GNU Screen is the lack of a way for Irssi to alert you when you are not looking at the terminal.

I have looked at many implementations for libnotify (default in Ubuntu), Mumbles (Growl for Linux) and Dzen.

Some of the things I have looked at

  • thl’s irssi notification script aka fnotify
    Most of this is actually quite good and has formed the basis for my implemenation. Uses libnotify.
  • Using irssi with libnotify over Secure Shell
    A different implementation of the above, using xterm’s print facility to send data to libnotify.
  • irssi-libnotify
    Uses notify-send on the same machine as irssi, requires X-forwarding (which is a bitch with screen). I liked this but as it uses X-Windows on the remote server the notifications might not match those of your desktop
  • Dzen notifications
    This is where I got the idea for using a named pipe
  • Mumbles
    I used this before libnotify became standard in Ubuntu. It was hard to make it work and required several (Python) daemon running to forward the notifications.

Since I have several machines I use to access my server where Irssi is running none of the other implementations I looked at really worked since I need to be sure that all machines get the notifications. In the end I decided to use MySQL as a “proxy” for the notifications.

Prepare the MySQL database

It’s a good idea to set up a separate database – just in case one of the scripts f*ck up and deletes everything.

$ sudo mysqladmin -u root -p create irssi
mysql> use irssi
Database changed
mysql> CREATE TABLE `notify` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `summary` varchar(64) CHARACTER SET utf8 NOT NULL,
  `message` varchar(255) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM;
mysql> GRANT ALL ON irssi.* TO 'irssi'@'localhost' IDENTIFIED BY 'Password';

Installing the Irssi script

It is also possible to simply create a table inside an existing database; just adjust the configuration values in Irssi.

The Irssi script is based on Jared Quins work (which in turn is based on irssi-libnotify). The basic idea is the same as with fnotify but instead of writing to a temporary file I write to a MySQL database.

## Put me in ~/.irssi/scripts, and then execute the following in irssi:
##
##       /load perl
##       /script load notify
##

use strict;
use Irssi;
use vars qw($VERSION %IRSSI);
use HTML::Entities;
use DBI;
use utf8;

$VERSION = "0.01";
%IRSSI = (
    authors     => 'Allan Willems Joergensen',
    origauthors => 'Luke Macken, Paul W. Frields, Jared Quinn',
    contact     => 'allan@nowhere,dk',
    name        => 'notifier.pl',
    description => 'Use libnotify to alert the user of new messages or hilights (Using MySQL as "proxy")',
    license     => 'GNU General Public License',
    url         => 'http://www.nowhere.dk/articles/irssi-notification',
);

Irssi::settings_add_str('notifier','notifier_mysql_user', 'irssi');
Irssi::settings_add_str('notifier','notifier_mysql_password', 'changeme');
Irssi::settings_add_str('notifier','notifier_mysql_host', 'localhost');
Irssi::settings_add_str('notifier','notifier_mysql_db', 'irssi');

sub write2db {
        my $db_user = Irssi::settings_get_str('notifier_mysql_user');
        my $db_pass = Irssi::settings_get_str('notifier_mysql_password');
        my $db_host= Irssi::settings_get_str('notifier_mysql_host');
        my $db_name = Irssi::settings_get_str('notifier_mysql_db');
        my ($summary, $message) = @_;
        my $dsn = "dbi:mysql:dbname=$db_name;host=$db_host";
        my $dbh = DBI->connect($dsn, $db_user, $db_pass) || die "DB connect failed";

        my $sth = $dbh->prepare("INSERT INTO notify (summary, message) VALUES (?, ?)")
            or die "Can't prepare statement: $?";
        $sth->execute($summary, $message) or die "Couldn't execute INSERT: $?";

        $dbh->disconnect;
}


sub notify {
    my ($server, $summary, $message) = @_;
    my $safemsg = HTML::Entities::encode($message, '<>&"');
    my $utf8msg = utf8::encode($safemsg);

    write2db($summary, $safemsg);
}

sub print_text_notify {
    my ($dest, $text, $stripped) = @_;
    my $server = $dest->{server};
    return if (!$server || !($dest->{level} & MSGLEVEL_HILIGHT));
    my $sender = $stripped;
    $sender =~ s/^\<.([^\>]+)\>.+/\1/ ;
    $stripped =~ s/^\<.[^\>]+\>.// ;
    my $summary = "Hilite in " . $dest->{target};
    notify($server, $summary, $stripped);
}


sub message_private_notify {
    my ($server, $msg, $nick, $address) = @_;
    return if (!$server);
    notify($server, "Private message from ".$nick, $msg);
}

sub dcc_request_notify {
    my ($dcc, $sendaddr) = @_;
    my $server = $dcc->{server};

    return if (!$dcc);
    notify($server, "DCC ".$dcc->{type}." request", $dcc->{nick});
}

Irssi::signal_add('print text', 'print_text_notify');
Irssi::signal_add('message private', 'message_private_notify');
Irssi::signal_add('dcc request', 'dcc_request_notify');

Download the script to ~/.irssi/scripts and rename it to notifier.pl.

If you want it to load automatically, symlink it to ~/.irssi/scripts/autorun
$ ln -sf ~/.irssi/scripts/notifier.pl ~/.irssi/scripts/autorun/notifier.pl

Load the script inside irssi
/script load notifier.

Once you have loaded the script, set these variables inside Irssi (adjust according to your setup)

/set notifier_mysql_db irssi
/set notifier_mysql_host localhost
/set notifier_mysql_user irssi
/set notifier_mysql_password Password

Setup MySQL port forwarding

It is possible to use autossh to automatically setup the tunnel but since I am always connected to my server (at least when I am in front of a computer) I chose to use normal ssh port forwarding.

In ~/.ssh/config I have

Host my.server.bogus
        LocalForward 13306 localhost:3306

The stuff running on your local machine

That is, the stuff that actually shows the notifications

I did not want to bother trying to make the MySQL-stuff error proof so I simply call the Perl script from a shell script like so

#!/bin/bash

wait=0
while true
 do
    $HOME/bin/irssi-notify-client.pl

    let wait=$wait+5
    if [ $wait -ge 30 ]
     then
        sleep 30
    else
        sleep $wait
    fi
done

Save the script as ~/bin/start-irssi-notify-client.sh

The Perl script requires DBI and Desktop::Notify – Both are available in Ubuntu

$ sudo install libdesktop-notify-perl libdbd-mysql-perl
#!/usr/bin/perl

use strict;
use warnings;
use DBI;
use Desktop::Notify;

my $last = 0;
my $loops = 0;
my $notify_timeout = 2000;
my $icon = "gnome-irc.png";

sub mysql_connect {
    my $db_user = "irssi";
    my $db_pass = "Password";
    my $db_host = "127.0.0.1:13306";
    my $db_name = "irssi";
    my $dsn = "dbi:mysql:dbname=$db_name;host=$db_host";
    my $dbh = DBI->connect($dsn, $db_user, $db_pass) or die "DB connect failed";

    return($dbh);
}

while (1) {
    my $dbh = mysql_connect();

    if ($last == 0) {
        my $sth_state = $dbh->prepare("SELECT MAX(id) FROM notify");
        $sth_state->execute() or die "Unable execute query: $dbh->err, $dbh->errstr\n";
        $last = ($sth_state->fetchrow_array)[0];
        $sth_state->finish();
    }

    my $sth = $dbh->prepare("SELECT id,time,summary,message FROM notify WHERE id > ? ORDER BY id ASC LIMIT 0,10");
    $sth->execute($last) or die "Unable execute query:$dbh->err, $dbh->errstr\n";

    if ($sth->rows > 0) {
        my $notify = Desktop::Notify->new();
        my $notification = $notify->create(timeout => $notify_timeout, app_icon => $icon);
        while (my $ref = $sth->fetchrow_hashref()) {
       
            my $id = $ref->{'id'};
            my $summary = $ref->{'summary'};
            my $message = $ref->{'message'};
           
            $notification->summary($summary);
            $notification->body($message);
            $notification->show();

            $last = $id;
            sleep 1;

        }
        $notification->close();
    }

    $sth->finish();
   
    # Clean up once in a while. This is not really essential so we simply
    # do it once every 1000 iterations
    $loops++;
    if ($loops > 1000) {
        my $sth_cleanup = $dbh->prepare("DELETE FROM notify WHERE id < ?");
        $sth_cleanup->execute($last);
        $sth_cleanup->finish();
    }

    $dbh->disconnect;

    sleep 5;
}

Save the script to ~/bin/irssi-notify-client.pl.

Remember to make both scripts executable.

The final thing to do is to add the notify client to your desktop environment’s autostart

In GNOME: System -> Preferences -> Startup Applications

Add Startup Program

Add Startup Program

Shorten URL Firefox extension now supports aurls.info

Ubuntu: Fixing Java in Firefox 3.6

If you have installed Firefox 3.6 (for instance from the Ubuntu Mozilla Daily Build Team PPA) you will discover that Java is no longer working

For i386 (32 bit Ubuntu):

$ sudo update-alternatives --install /usr/lib/mozilla/plugins/libjavaplugin.so mozilla-javaplugin.so /usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so 50

For amd64 (64 bit Ubuntu):

$ sudo update-alternatives --install /usr/lib/mozilla/plugins/libjavaplugin.so mozilla-javaplugin.so /usr/lib/jvm/java-6-sun/jre/lib/amd64/libnpjp2.so 50

Updated MoreAdorned template for Movie Sheet Generator

A nice soul has converted rodfeli’s MoreAdorned Tvixie template for use with Movie Sheet Generator.

I have tweaked the template further and I am pretty happy with the results

Changes compared to the original

  • Removed effects from cover and added static cover backgroup
  • Changed fonts
  • Added support for media flags – only two since it looks nicer

Download the updated template

The joys of outsourcing

I normally don’t post stuff written by others but I just had to share this one.

It’s from Slashdot.org and sums up my experience with outsourcing to India really well.

>> Hello there!
>> Please refer to your opening on job posting site. I, Rajesh Sharma, would like to apply for the job.[...]My hourly rates are $ 9 USD.
> We all like to pretend this isn’t here and it isn’t happening, but I would say conservatively half the job market has disappeared in 10 years due to this currency/standard of living imbalance.

There’s another reality: it’s really, really hard to manage projects in India. I have tried this for a number of projects, and have learned the following things:

  • A day before the deadline, Rajesh will ask for more time
  • Halfway through the project, Rajesh will ask for more money
  • Rajesh will not give the source, as was agreed
  • Rajesh will not use unit tests, or Subversion, as was agreed
  • Rajesh cannot be bothered to provide an estimate or a planning
  • Rajesh will take on other projects and give priority to those before yours
  • Rajesh actually has a day job and just does projects on the side
  • Rajesh will tell you he takes a holiday for three weeks, starting tomorrow
  • Rajesh has a wedding of a brother, a pregnant sister, a sick father, etc and cannot make the planning
  • Rajesh will ask for more money at the end of the project
  • Rajesh cannot be reached because he lost his mobile
  • Rajesh cannot be reached because his mobile was stolen
  • Rajesh cannot be reached because his mobile its battery is empty
  • Rajesh cannot be reached because the e-mail server is down
  • Rajesh cannot be reached because the internet is down

Each and every project, I have had the above things. There are lots of ways around the above, but the main thing is that it’s very hard.

Pic is related

Programmer Kitty

Me. On StreetView

Datatalk ApS erklæret konkurs

Egentlig ikke en nyhed da virksomheden blev erklæret konkurs 24/12-2009, men jeg har først set det i dag.

Som jeg tidligere har skrevet om har vi stadig et udestående på næsten 1700 kroner med dem. De penge er desværre nok tabt for evigt (der er altid mulighed for at gøre krav mod konkursboet, men umiddelbart skulle det krav have været fremsat til kurrator senest 16/01-2010, men vi vil forsøge alligevel, selvom chancerne er minimale).

Jeg kan godt frygte at butikken genopstår under et nyt navn – altså samme folk bag og samme elendige service, men bare med et nyt navn.

UFW: Blocking outgoing connections

Note: This is known to work for a machine acting as masquerading firewall for an entire network.

I wanted to block connections to certain outbound ports. After some trial and errors I found something that works

Add the following to /etc/ufw/before.rules:

-A ufw-before-forward -s <SOURCE IP> ! -d <LOCAL NET>/24 -p tcp -m tcp --dport <DEST PORT> -j DROP

it’s as simple as that.

Remember to reload all the rules:

$ sudo ufw reload

Using ISO-8859-15 encoding with Twirssi

Since I run irssi all the time, packing as many features into it as possible seems like a nice idea.

So I use bitlbee to connect to Messenger, Google Talk/Jabber and ICQ and I have been using tircd (Twitter/irc gateway) and tweet.im (Twitter/Google Talk gateway) to connect to Twitter; but none of them works like I want them to.

Today I stumbled across Twirssi, a script for irssi to interact with Twitter.

Out of the box twirssi expects input to be UTF-8 which caused some grief because my terminal is ISO-8859-15.

First, lets install required modules for twirssi

I run Ubuntu Karmic Koala so Net::Twitter is available as a package

$ sudo apt-get install libnet-twitter-perl

If you run an older Ubuntu release or another Linux/Unix variant that does not have a native package, install it from CPAN (I will not go into the configuration of CPAN here – have a look at this article for more information).

$ sudo perl -MCPAN -e shell
cpan[1]> install Net::Twitter

Answer yes to all dependencies.

Next step is to install a Perl module for the URL shortening service you wish to use; I use Bit.ly so let’s install the module

$ sudo perl -MCPAN -e shell
cpan[1]> install WWW::Shorten::Bitly

Now, let’s install twirssi

Head to irssi’s scripts directory

$ cd ~/.irssi/scripts

Download the script

$ wget http://twirssi.com/twirssi.pl

Make sure the script is autoloaded at startup

$ cd autorun
$ ln -sf ../twirssi.pl .

Patch twirssi to support other charsets than UTF-8

$ cd ~/.irssi/scripts
$ wget http://people.freebsd.org/~garga/patches/twirssi_charset.diff
$ patch -p1 < twirssi_charset.diff

Finally, configure twirssi

The configuration is done from inside irssi

  1. Create a new window for twirssi
    /win new hidden
  2. Name the new window
     /win name twitter
  3. Optional: Move the new window to another location
    /win move <number>
  4. Optional: Save new window layout
    /layout save
  5. Load twirssi
    /script load twirssi.pl
  6. Configure URL shortening service
    /set short_url_provider Bitly

    /set short_url_args "Bitly API key"
  7. Configure Twitter usename
    /set twitter_usernames Your_Twitter_Username

    /set twitter_passwords Your_Twitter_Password

    (Note: This will store your Twitter password in clear text in irssi’s configuration)

  8. Set charset to use
    /set twirssi_charset ISO-8859-15
  9. Reload the script to pickup autologin to Twitter
    /script load twirssi.pl

More information on how to use twirssi is available here

AT&T Global Network Client on Ubuntu article updated

It’s been a while since I last looked at my AT&T Global Network Client on Ubuntu article (primarily because I never actually used the application when I worked at IBM).

Anyway, at some point AT&T reorganized their FTP server, breaking the download link – The rest of the article is still valid.

AT&T Global Network Client

AT&T Global Network Client

Cool tool: namebench

Most users are either using their ISP’s nameservers, running their own recursive nameserver (like me) or using a free alternative like OpenDNS or Google DNS.

But which is better? Enter namebench:

It hunts down the fastest DNS servers available for your computer to use. namebench runs a fair and thorough benchmark using your web browser history, tcpdump output, or standardized datasets in order to provide an individualized recommendation. namebench is completely free and does not modify your system in any way

Written in Python, it’s a availble for Unix (source), Windows and OS X.

The program makes some recommendations and draws some pretty graphs

So, which should you use? Tests on my own server show that Google DNS, OpenDNS and UltraDNS are much faster than my own recursive server. I know it might not be wise to trust Google too much given Google CEO Erik Schmidt’s view on privacy but at least they do not hijack DNS results like OpenDNS and UltraDNS does.

Idaho680 TViXiE/Movie Sheet Generator Templates

If you frequent the WDTV community you may know of some pretty fantastic templates for TViXiE and Movie Sheet Generator by Idaho680.

Aeon Basic by Idaho680

Aeon Basic by Idaho680

Idaho680 is also responsible for a couple of nice OSD mods for WTDV.

For reasons not known to the wider public (me included) Idaho680 one day simply announced that he had had enough, deleted most (if not all) of his work from the forum and disappeared.

I had one of the template packs (revision 3) laying around so I decided to make the file available.

Get it here.

Outage, again

Once again my ISP screwed me over, resulting in the website being offline from 2/12-09 (around 9:30) to 3/12-09 (around 20:00).

Telenor never gave me a real reason for shutting down my line (there have been several reasons but none of them seem to make real sense).

I know I will be switching my ADSL provider soon and I will probably find a better hosting facility than a server on an ADSL connection.

The truth about working in the IT industry

Oldie but goodie.

  1. We work weird (night) shifts…
    Just like prostitutes.
  2. They pay you to make the client happy…
    Just like prostitutes.
  3. The client pays a lot of money, but your employer keeps almost every penny…
    Just like prostitutes.
  4. You are rewarded for fulfilling the client’s dreams…
    Just like prostitutes.
  5. Your friends fall apart and you end up hanging out with people in the same profession as you…
    Just like prostitutes.
  6. When you have to meet the client you always have to be perfectly groomed…
    Just like prostitutes.
  7. But when you go back home it seems like you are coming back from hell…
    Just like prostitutes.
  8. The client always wants to pay less but expects incredible things from you…
    Just like prostitutes.
  9. When people ask you about your job, you have difficulties to explain it…
    Just like prostitutes.
  10. Everyday when you wake up, you say: “I’m not going to spend the rest of my life doing this.”
    Just like prostitutes.

b-rad releases WDLXTV 0.5.8.1

This is more or less a bugfux release for 0.5.8.1

0.5.8.1
* fixed typo preventing S00custom-options from executing
* persistent video resume filename correction: video_resume_points_table
* dos2unix /conf/net.mounts & /conf/net.config to fix windows editing

The 0.5.8.x series also seem to finally do away with the remote controller sluggishness that have plagued us for a long time

Importantly: It seems as if I *might’ve* finally found & fixed the sluggish remote / unresponsive video issue that popped up for a small minority of people a long time back. It turns out that dmaosd doesn’t like a lot of stuff happening while it is loading, and especially does not like NTP changing the system clock during init

Read more.

In case RapidShare makes it impossible to download the firmware package I’ve mirrored the file here.

b-rad releases WDLXTV 0.5.8

WDLXTV is a souped up unofficial firmware for the Western Digital WDTV. It is based off the 1.03.01 firmware, but with many extra features. Similar to my dvdmod firmware, this is a permanent flash, just like an official upgrade. There is no Linux knowledge required to use WDLXTV.

I’ve finally found the time time make a new WDLXTV release, now based on WD TV firwmare 1.03.01. There have bee a lot of changes since the last published release, mostly background tweaks/bugfixes/enhancements.

Read more.

Backup and bare-metal restore with rdiff-backup

pusio-boslightuxI know there are lots of different backup tools for Linux and that many people recommend Mondo Rescue but I have never been able to make it work properly (my last attempt resulted in 8 DVD images totaling 31 GB – The source of the backup was 140GB), no doubt my own fault.

So I decided to write down how I made backup and bare-metal restore using rdiff-backup work for my own future reference; and what better place to write it down than in my own blog :)

I am using an external (USB) disk for backups.

First, the backup
Instead of having to run everything by hand each time, I quickly created a script for my backups:

#!/bin/bash
# Backup script - allan@nowhere.dk
# This version is for local backups
#
# Requirements: rdiff-backup, sfdisk

if [ $# -ne 1 ]
 then
    echo "Usage: $0 <dest dir>"
    echo "The directory backup will be created inside <dest dir>"
    exit 0
fi

# White-space separated list of directories or files to exclude. Adjust to suit local needs."
EXCLUDE="/tmp /media /proc /sys /dev"

# Time to keep files in backups - See rdiff-backup manual for more info
KEEP="5D"

# Where to put the backup
BU_DIR="$1/backup"

# Temporary file for exclude list
EXCLUDE_FILE=`mktemp /tmp/backup.XXXXXX`

# Test if backup dir exists
if [ ! -d $BU_DIR ]
 then
    # Create the directory - Note, not using -p for security reasons
    mkdir $BU_DIR
    if [ $? -ne 0 ]
     then
        echo "Unable to create $BU_DIR - Please check permissions"
        exit 1
        fi
fi

# Create a list of all packages currently installed - Used on Debian/Ubuntu
dpkg --get-selections > /etc/dpkg.lst

# Create a copy of the partition table, assumes one disk only
sfdisk -d /dev/sda > /etc/sda.sfdisk

# Generate an exclude file for rdiff-backup
for file in $EXCLUDE
 do
    echo "$file/**" >> $EXCLUDE_FILE
done

# Run the backup; this will backup ALL files/directories (except does excluded) and
# does not care about filesystems.
rdiff-backup --exclude-device-files --exclude-fifos --exclude-sockets -v5 \
        --exclude-globbing-filelist $EXCLUDE_FILE / $BU_DIR

# Remove increments older than $KEEP days
rdiff-backup --remove-older-than $KEEP $BU_DIR

# Cleanup
rm $EXCLUDE_FILE

If you want to create the backup on another server, first setup key-based SSH login to the remote server.

Here is a short guide if you do not already have key based authentication running

  1. Create a new ssh key on the source server (for root):
    $ sudo ssh-keygen -t dsa
    Generating public/private dsa key pair.
    Enter file in which to save the key (/root/.ssh/id_dsa):
    Created directory '/root/.ssh'.
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /root/.ssh/id_dsa.
    Your public key has been saved in /root/.ssh/id_dsa.pub.
    The key fingerprint is:
    16:b6:a3:a9:f2:f4:d3:37:3d:b1:fe:df:8a:00:03:a9 root@bender
    The key's randomart image is:
    +--[ DSA 1024]----+
    |                 |
    |       .         |
    |      o o        |
    |     . o o       |
    |    E   S        |
    |       + +  .    |
    |    . o.  .. o   |
    |  .. o. . o.+.  .|
    |   oo .. . oooooo|
    +-----------------+

    Note: Fingerprint and randomart will differ.

  2. Copy the contents of /root/.ssh/id_dsa.pub on the source machine to ~user/.ssh/authorized_keys on the destination machine. While it is possible to connect as root I recommend using a non-privileged user.
  3. Test the connection:
    # ssh user@remote

And the backup script:

#!/bin/bash
# Backup script - allan@nowhere.dk
# This version is for remote backups.
#
# Requirements: rdiff-backup, sfdisk, ssh

if [ $# -ne 3 ]
 then
    echo "Usage: $0 <remote host> <remote user> <dest dir>"
    echo "The directory backup will be created inside <dest dir>"
    exit 0
fi

# White-space separated list of directories or files to exclude. Adjust to suit local needs."
EXCLUDE="/tmp /media /proc /sys /dev"

# Time to keep files in backups - See rdiff-backup manual for more info
KEEP="5D"

# Where to put the backup
RHOST="$1"
RUSER="$2"
SSH="ssh -l $RUSER"
BUDIR="$3/backup"
# Temporary file for exclude list
EXCLUDE_FILE=`mktemp /tmp/backup.XXXXXX`

# Test if remote host is connectable
rdiff-backup --test-server $RUSER@$RHOST::$BU_DIR
if [ $? -ne 0 ]
 then
    echo "Unable to connect to $RHOST"
    exit 1
fi

# Test if backup dir exists
$SSH test -d $BU_DIR
if [ $? -ne 0 ]
 then
    # Create the directory - Note, not using -p for security reasons
    $SSH mkdir $BU_DIR
    if [ $? -ne 0 ]
     then
        echo "Unable to create $BU_DIR - Please check permissions"
        exit 1
        fi
fi

# Create a list of all packages currently installed - Used on Debian/Ubuntu
dpkg --get-selections > /etc/dpkg.lst

# Create a copy of the partition table, assumes one disk only
sfdisk -d /dev/sda > /etc/sda.sfdisk

# Generate an exclude file for rdiff-backup
for file in $EXCLUDE
 do
    echo "$file/**" >> $EXCLUDE_FILE
done

# Run the backup; this will backup ALL files/directories (except does excluded) and
# does not care about filesystems.
rdiff-backup --exclude-device-files --exclude-fifos --exclude-sockets -v5 \
        --exclude-globbing-filelist $EXCLUDE_FILE / $RUSER@$RHOST::$BU_DIR

# Remove increments older than $KEEP days
rdiff-backup --remove-older-than $KEEP $RUSER@$RHOST::$BU_DIR

# Cleanup
rm $EXCLUDE_FILE

Both scripts need to run as root on the source machine.

Restore
First of all: Test your restore!. Nothing feels worse than a useless backup. Use a virtual machine to test your backup.

  1. Download a boot CD (and boot it). Some steps of the restore requires Internet access so keep you wireless details handy (if applicable)
  2. rdiff-backup is not included on the live CD, so we need to “install” it. Go to the System -> Administration and select Synaptics Package Manager, select Settings -> Repository and enable the universe repository
    Screenshot-Software Sources
    When you click Close, you will be informed that you need to click the Reload button (please do)
  3. Close Synaptics and open a terminal (Applications -> Accessories -> Terminal) and install rdiff-backup by running
    sudo apt-get install rdiff-backup
  4. Create a new partition table using GParted (found in System -> Administration), the size of each partition can be found in /media/usbdisk/backup/etc/sda.sfdisk – the filesystem type of each partition is found in /media/usbdisk/backup/etc/fstab
  5. Mount filesystems for the restore; in my case I took the filesystems listed in /media/usbdisk/backup/etc/fstab:
    /dev/sda1 /               ext3    relatime,errors=remount-ro 0       1
    /dev/sda6 /home           ext3    relatime,user_xattr        0       2

    This translates to:

    $ sudo mount /dev/sda1 /mnt
    $ sudo mkdir /mnt/home
    $ sudo mount /dev/sda6 /mnt/home
  6. We are now ready to restore:
    $ sudo rdiff-backup --force -r now -v5 /media/usbdisk/backup /mnt

    The force flag is needed because some of the destination directories are present at target.

  7. Next step is to reinstall grub into the MBR and fix fstab.
    1. First set up and enter a chroot:

      $ mount -t proc none /mnt/proc
      $ mount -o bind /dev /mnt/dev
      $ mount -o bind /sys /mnt/sys
      $ sudo chroot /mnt /bin/bash

      All work done from this point on is done with the actual data from your old system.

    2. Now find the UUID of your partitions:
      # blkid
      /dev/sda1: UUID="ff98e4b0-2383-42f7-9812-cd05af1498ea" TYPE="ext4"
      /dev/sda5: UUID="a1d38cf3-2a8a-4ca4-b1ee-5f7fcb43d51b" TYPE="swap"
      /dev/sda6: UUID="c64dcaa8-2bad-4ecd-b984-ed6b2718b985" SEC_TYPE="ext2" TYPE="ext3"
    3. Open /boot/grub/menu.lst, locate kopt= and groot= and then change the UUID value with the one corresponding to the value of your root filesystem above
    4. Open /etc/fstab and change the UUID values to match those above
    5. Install grub:
      # grub-install /dev/sda
    6. Update the grub configuration
      # update-grub
    7. Optional: Open /etc/udev/rules.d/70-persistent-net.rules and remove the rule for eth0 if you are moving to new hardware
    8. Exit the chroot
      # exit

Setting the correct locale in Karmic

I want to use ISO-8859-15 instead of UTF-8 because I use IRC a lot.

For some reason the tip I posted a long time ago does not work in Ubuntu Karmic Koala (the trick was to add the correct locale and then selecting it from GDM).

This seems to do the trick. After adding your locale to /var/lib/locales/supported.d/local like so

en_DK ISO-8859-15

regenerate locates

$ sudo locale-gen --purge

The next step is to change the locale globally

$ sudo update-locale LANG=en_DK

(this will in fact change the LANG variable in the file /etc/default/locale).

Once done, log out and select the newly added locale from GDM’s language selector (there will most likely be two identical entires, select the one not currently selected) – Oh, and you might need to reboot.

Select new language

Select new language

Building a cheap HD media player with WD TV

Introduction, description and background

A couple of months ago I was looking for a media player for the bedroom. I already had a TViX running in the living room.

I had a few criteria

  1. “Cheap” (cheaper than TViX at least)
  2. Able to play HD content on both HD TV (through HDMI) and my old 32″ Sony Trinitron
  3. Able to play content from my NFS server
  4. No mowing parts = No noise and lower power consumptions
  5. Hopefully a better user interface than the TViX

I looked at several machines and ended up at the Western Digitial WDTV because it was cheap (around 700 DKK =~ $90) and could play the same content as the TViX (as they are based on the same Sigma chipset) – plus it is very small and completely without any moving parts and the default user interface is prettier than that of the TViX.

The WDTV in all its glory

The WDTV in all its glory

Things it does not do – out of the box at least: Network (it is intended to be used to play content of a USB hard drive) and DTS down-mixing (so if you do not have a amplifier capable of decoding DTS you will not get any sound).

Luckily both problems are pretty easy to solve.

The WD TV is based on a Linux distribution for the Sigma chipset; this means that though some kernel modules (for the Sigma hardware) is released as object code only, large portions of the firmware is GPL and released as such, making it possible for anyone to make their own firmware.

The WDTV community have used this to add networking support. Making the WDTV play content from the network (through a NFS or CIFS share) requires three pretty simple steps

  1. Flash the device with a custom firmware and install the required driver (if needed)
  2. Obtaining a supported device
  3. Configure network support

At the time of writing there a two custom firmwares for the WDTV

The main difference is that ext3-boot is more complete (includes more drivers as well as applications like Dropbear sshd) but does require a USB stick or hard drive to boot where as the basic WDLXTV is able to boot completely from flash. It is extensible through application packs (that resides on a USB stick or hard drive).

Personally I have opted for the WDLXTV firmware and the rest of the article will describe how I have achieved my goals using that particular firmware.

Let’s get cracking then

Finding the right network adapter

Once again our Chinese friends over at DX comes to the rescue. After checking the list of supported devices I settled for these two USB network adapters (one wired and one wireless):

Flashing the WDTV

Flashing the WDTV with an alternate firmware is as easy as flashing it with an official WD firmware

  1. Download the latest WDLXTV firmware
  2. Unpack the firmware archive and copy the two files wdtv.bin and wdtv.ver to a FAT32 formated USB stick (2GB maximum)
  3. Depending on the firmware version installed the WDTV will either automatically start to upgrade or it will auto-select a menu entry in the system configuration menu. Selecting this menu entry will start the firmware upgrade

Mounting network shares

Mounting network shares requires two components; an app package (for either NFS or Samba/CIFS) and the configuration telling WDLXTV which shares to mount.

NFS: Download the nfs app package, unpack it and place the file nfs.app.bin on the the USB stick.

Samba/CIFS: Download the samba app package, unpack it and place the file samba.app.bin on the USB stick.

net.mounts contains any network shares you wish to mount on the WDTV:

# Example net.mounts file to demonstrate auto-mounting
# of network shares
# Mount a windows file share (must be done by IP address)
# xmount //192.168.0.33/ShareName ShareName cifs
#  if your "guest" account is disabled, you must supply username and password
# xmount //192.168.0.34/ShareName ShareName cifs user=username,pass=password
# Mount a NFS share
# xmount 192.168.0.44:/nfsroot ShareName nfs
# Notice that we no longer need to modprobe, nor create the directory.
# That is handled for us by xmount.

add any mounts you wish to match your local setup.

Wired networking

In addition to the right share app package and net.mounts wired networking just requires on configuration file on the USB stick: net.config

#You can override the hostname here:
HOST=wdtv
# if you do not set a hostname,a random one is assigned.
# attempt to set jumbo frames
#MTU=9000
#
# Dynamic IP Configuration:
DHCP=yes
#
# Static IP Configuration:  (only if not DHCP)
#DHCP=no
#IP=192.168.0.10
#GW=192.168.0.1
#NM=255.255.255.0
#DNS1=192.168.0.1
#DNS2=205.171.3.65
#
# Optional:  
#specify time server host
NTP=pool.hest
#specify timezone
TZ=CET

There have been some problems with the NTP service and WDLXTV so setting NTP= to something bogus is a good idea.

With these files on your USB stick and the USB stick and USB network interface card connected to the WDTV, it is a simple matter of going to “Folders” in either the Video, Music or Photo menu, select the mount point and browse your files.

Wireless network

Download the wireless-mod-rt app package, unpack the zip archive and copy the file wireless-mod-rt.app.bin to the USB stick.

Besides this app package wireless networking requires two files on the USB stick:

net.config

# Network configuration file
#You can override the hostname here:
HOST=wdtv
# if you do not set a hostname,a random one is assigned.
# attempt to set jumbo frames
#MTU=9000
#
# Dynamic IP Configuration:
DHCP=yes
#
# Static IP Configuration:  (only if not DHCP)
#DHCP=no
#IP=192.168.0.10
#GW=192.168.0.1
#NM=255.255.255.0
#DNS1=192.168.0.1
#DNS2=205.171.3.65
#
# Optional:
#specify time server host
NTP=pool.hest
#specify timezone
TZ=CET
#
#one of rt61sta.dat, rt73sta.dat, RT2400.dat, RT2500STA.dat, RT2570STA.dat, RT2870STA.dat (used by rt3070 as well)
WLAN_CFG=RT2870STA.dat
#one of rt61.ko, rt73.ko, rt2400.ko, rt2500.ko, rt2570.ko, rt2870sta.ko, rt3070sta.ko
WLAN_LOAD=rt3070sta.ko
#need to bring up device?
WLAN_UP=yes
#time to sleep while waiting for wireless association
WLAN_SLEEP=10

RT2870STA.dat:

Default
CountryRegion=5
CountryRegionABand=7
CountryCode=
SSID=This is your SSID
NetworkType=Infra
WirelessMode=7
Channel=0
BeaconPeriod=100
TxPower=100
BGProtection=0
TxPreamble=0
RTSThreshold=2347
FragThreshold=2346
TxBurst=1
WmmCapable=0
AckPolicy=0;0;0;0
AuthMode=WPA2PSK
EncrypType=TKIP
WPAPSK=This is your WPA key
DefaultKeyID=1
Key1Type=0
Key1Str=
Key2Type=0
Key2Str=
Key3Type=0
Key3Str=
Key4Type=0
Key4Str=
PSMode=CAM
FastRoaming=0
RoamThreshold=70
HT_RDG=1
HT_EXTCHA=0
HT_OpMode=1
HT_MpduDensity=4
HT_BW=1
HT_AutoBA=1
HT_BADecline=0
HT_AMSDU=0
HT_BAWinSize=64
HT_GI=1
HT_MCS=33
HT_MIMOPSMode=3
IEEE80211H=0
TGnWifiTest=0
WirelessEvent=0
CarrierDetect=0

There have been some problems with the NTP service and WDLXTV so setting NTP= to something bogus is a good idea.

With these files on your USB stick and the USB stick and USB network interface card connected to the WDTV, it is a simple matter of going to “Folders” in either the Video, Music or Photo menu, select the mount point and browse your files.

Troubleshooting

If your WDTV does not connect to the network download the log-saver app package; on next boot this application will save system logfiles (dmes, messages and more) to the USB stick.

Enhancing your WDTV experience

There are several ways of enhancing the look and feel of the WDTV

OSD mod : simple and unadorned

This OSD mod will completely change the look and feel of the WDTV

Original main menu

Original main menu


vs.
Lilibabe main menu

Lilibabe main menu

Download the latest OSD mod app package and place it on your USB stick. The next time you boot the WDTV the user interface will be completely changed.

Enhancing the file browser

Through an app package and a program called TviXie it is possible to further enhance this cool user interface.

LaurentG: “My pack enhancing OSD”

Here are the enhancements included in this application pack:
- new video thumbmail views using ratio 3/4 instead of 2/3 for thumbmails + menus to choose the configuration,
- new view displaying the movie sheet previously generated for example with the softwares Movie GUI Builder or TViXiE,
- access to the network shares even when the media library is off

The most important feature is the ability to display a custom background when entering a directory, like this one:

More on the actual creation of the background image later.

Download the latest app package, unpack it and copy these files and directories to the USB stick:

event-osd.app.bin
LaurentG.app.bin
LaurentG.app.event
LaurentG.conf.txt
LaurentG_templates
Creating custom backgrounds (or movie sheets) using Movie Sheet Generator

I have developed a little tool that will hopefully make some of your lives easier. It is a windows based application that uses theMovieDb.org to get information about films and automatically create movie sheets using the backdrops supplied by themoviedb.org.
Users have the option to select which backdrop and cover art they wish to use from the available list and then generate the movie sheet using these images.

The original version was sort of abandoned by the author, beanian – As far as I remember he simply did not have time to keep on improving the program.

It was picked up by a group of developers and are constantly being improved.

Unfortunately this is a Windows-only program but it is still worth it :)

Download, install and use one of these templates or this one.

I prefer MoreAdorned as it matches lilibabe’s OSD mod but Aeon Basic is a good choice (and is actually included in the Movie Sheet Generator package).

Creating movie sheets are pretty straight forward and should be self-explanatory – Configure MSG to use the right template and “flags”.

Another way to produce movie sheets is using TViXie. It has some more advanced graphic options but overall I find MSG to be easier and faster to use.

Running Windows applications natively and seamlessly on Linux with SeamlessRDP and Virtualbox or KVM

Background

In the past I have written a couple of articles on how to run Windows applications using SeamlessRDP and Sun xVM (Virtualbox) and Linux KVM (Kernel-based Virtual Machine). After reviewing both articles I have decided to write a new article encompassing both hypervisors and correcting some of the mistakes I have found as well improvements made by a couple of guys who have done quite a deal of testing: Thomas Hansson and Peter Clarén.

By the way – There is no reason why this guide should not work on other platforms like FreeBSD (Virtualbox, Qemu), Mac OSX (Virtualbox) or Solaris/OpenSolaris (Virtualbox) as long as the host platform is x86 or x64. The guide is centered around Ubuntu but it should be possible to use it for other Linux distributions without much work.

So, what is the reason for this article?

I run Linux on my primary machine (well, on all my machines really) but there are a few Windows application I need to run – Some run under Wine but does not act like in native Windows, some will not run under Wine. The solution was to run a virtual machine with Windows but I did not like the fact that I had to have a complete Windows desktop.

Enter SeamlessRDP. SeamlessRDP is an “extension” of the RDP protocol (originally developed by Cendio AB for their ThinLinc product).

SeamlessRDP makes it possible to run individual applications rather than a full desktop. In this mode, rdesktop creates a X11 window for each window on the server side. The remote applications can be moved, resized and restacked.

Choosing a hypervisor

I deal a lot with virtualization in job and have come to be a great fan of VMware’s line of products. Naturally I have been running VMware Workstation on my computer for a very long time but for this particular task it did not fit my needs (most noticeably it does not have the option to run “headless”) so I had to start looking at alternatives.

I started using VMware Server which worked great in version 1.x but after upgrading to 2.0 I was put of by the fact that is now uses a horrible memory hog of a web interface (which could be disabled but one is then dependent on Virtual Infrastructure Client which is Windows only).

After ditching VMware I ended up with two (equally great) products:

  • Sun xVM Virtualbox
    Pros: No problems with kernel modules. Great support for USB devices. RDP based “console”. Great performance using paravirtualized devices. Supports running 64 bit guests on a 32 bit host OS (the host has the be 64 bit of course). Export virtual machines as appliances. Seamless integration of the guests and hosts (using guest additions to provide shared clipboard and dynamic screen resizing)Cons: Not free (there is an open sourced edition which lacks some of the feature described above).
  • Linux KVM
    Pros: Part of the kernel. Lots of features (like live migrations). Powerful. Open source
    Cons: Does not support 64 bit guests on 32 bit host OS. Requires Intel VT-x or AMD-V. Though Virtual Machine Manager makes it easier it is not for the average user

Because I use both on a regular basis I will describe how to accomplish the goal using both hypervisors. My guides are based on Ubuntu so you may need to change the commands to match your environment.

Installing and configuring hypervisor

Installing KVM

One important note: KVM requires hardware virtualization support. To check if your computer supports this, run

$ egrep -c '(vmx|svm)' /proc/cpuinfo

The output should be at least 1 – If you know your CPU support VT-x or AMD-v but the above command does not show anything make sure virtualization is enabled in the computer’s BIOS.

KVM is in Ubuntu’s package repository, so installing it easy

$ sudo apt-get install kvm xtightvncviewer

Install Virtualbox

Virtualbox does not require hardware virtualization support but will benefit from it.

Enable Virtualbox’ package repository

$ echo "deb http://download.virtualbox.org/virtualbox/debian jaunty non-free" | sudo tee -a  /etc/apt/sources.list
$ wget -q http://download.virtualbox.org/virtualbox/debian/sun_vbox.asc -O- | sudo apt-key add -

and then install Virtualbox:

$ sudo apt-get update
$ sudo apt-get install virtualbox-3.0 rdesktop

Configuring network on the host

Though both Virtualbox and KVM support simple NAT networking we need to be able to connect to the virtual machine and the virtual machine need to be able to connect to the outside network.
Virtualbox now supports bridging to host interfaces but that is not necessarily what we want since that exposes the virtual machine to the outside network (which can cause problems on networks that only allow one MAC address per switch port).

So, we’ll set up a virtual interface on the host and let the host handle DNS, DHCP and IP forwarding (using dnsmasq and iptables).

First, install the needed software

$ sudo apt-get install dnsmasq ufw uml-utilities

Ubuntu tries to keep security really tight so be default only root is allowed to access tun/tap devices. To fix this we create a udev rule to allow group access to those devices

$ echo "KERNEL==\"tun[0-9]*\",GROUP=\"uml-net\" MODE=\"0660\"" | sudo tee -a /etc/udev/rules.d/40-permissions.rules
$ sudo udevadm control --reload-rules

Next create a interface configuration for a tap interface which will spawn a dedicated instance of dnsmasq when the interface is initialized (with Virtualbox it is also possible to use a bridge interface but since it does not work with KVM I will use tap for both) – Add this to /etc/network/interfaces:

auto tap0
iface tap0 inet static
         address 192.168.10.1
         netmask 255.255.255.0
         up /usr/sbin/dnsmasq --interface=${IFACE}  --except-interface=lo,eth0,wlan0,ath0 --bind-interfaces --user=nobody \
         --dhcp-range=kvm,192.168.10.150,192.168.10.250,255.255.255.0,192.168.10.255,8h \
         --domain=kvm.lan --pid-file=/var/run/${IFACE}_dnsmasq.pid --conf-file
         tunctl_user nobody

test if it works

$ sudo ifup tap0
$ ps aux | grep dnsmasq | grep -c kvm
1

You also need to add any users running virtual machines to the group uml-net:

$ sudo adduser <user> uml-net

(It will not work until the user logs on after adding her to the group)

In order for the virtual machine to reach the outside network we need to set up IP forwarding; I use Uncomplicated Firewall because it is very simple to use.

  1. Edit /etc/default/ufw and change DEFAULT_FORWARD_POLICY from DROP to ACCEPT
  2. Edit /etc/ufw/sysctl.conf and enable the line net/ipv4/ip_forward=1 (remove the # in front of the line)
  3. Add the following lines to /etc/ufw/before.rules (right after the comments at the top):
    # nat Table rules
    *nat
    :POSTROUTING ACCEPT [0:0]

    # NAT all traffic coming from 192.168.10.0/24 going through any interface.
    -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE

    # don't delete the 'COMMIT' line or these nat table rules won't
    # be processed
    COMMIT
  4. In the same file (/etc/ufw/before.rules), locate the line -A ufw-before-output -o lo -j ACCEPT and add these lines right after:
    -A ufw-before-input -i tap0 -j ACCEPT
    -A ufw-before-output -o tap0 -j ACCEPT

Getting things running

Converting an existing VMware virtual machine

Both KVM and Virtualbox support vmdk files so there is no need convert the disk files, just adjust the virtual machine creation to point at the vmdk file instead.

Windows can be quite picky when it comes to hardware so moving a virtual machine to a new hypervisor will most likely result in BSOD. If this happens find a Windows XP install CD, boot from it and repair your Windows XP installation.

Creating a virtual machine

Using KVM

Create the script $HOME/bin/kvm-windows:

#!/bin/bash

HD="-hda $HOME/path/to/Windows.img"
NIC1MAC="00:16:3e:66:42:73"
KVM="kvm"
VNC="-vnc :1"
NET="-net nic,macaddr=$NIC1MAC -net tap,script=no,vlan=0,fd=0"
SOUND="-soundhw es1370"
TIME="-localtime"
MEM="-m 512"
NAME="-name Windows"
CPU="-cpu core2duo"
KB="-k da"
USB=""
OTHERARG="-daemonize"

$KVM $HD $NET $VNC $SOUND $MEM $TIME $NAME $CPU $KB $USB $OTHERARG "$@"

Change HD, NIC1MAC, KB and CPU to match your needs.

Last step is to create a virtual disk:

$ kvm-img create -f qcow2 $HOME/path/to/Windows.img

before booting the virtual machine

$ kvm-windows -cdrom /path/to/WindowsXP.iso -boot d

and connecting to the “console”

$ xtightvncviewer :1

Continue to installing Windows

Using Virtualbox

We will create the virtual machine from the shell – simply because it is easier.

$ VBoxManage createvm --name "Windows" --register
$ VBoxManage createhd --filename "Windows.vdi" --size 10000 --remember
$ VBoxManage modifyvm "Windows" --memory "512MB" --hda "Windows.vdi" --dvd /path/to/WindowsXP.iso --acpi on \
   --boot1 dvd --nic1 bridged --bridgeadapter1="tap0" --vrdp on --vrdpport 1337

Boot the virtual machine (this has to be done from the shell to run the “console” as a RDP service):

$ VBoxManage startvm Windows -type vrdp

and then connect to the “console”

$ rdesktop localhost:1337

Continue to installing Windows

Installing and configuring Windows XP

The installation of Windows XP is no different than any other install so I will not go into that.

KVM: Installing paravirtualized network driver

Download the driver disc, shut down the virtual Windows machine, change the variable NET to read:

NET="-net nic,model=virtio,macaddr=$NIC1MAC,vlan=0 -net tap,vlan=0,ifname=tap0,script=no"

and then boot Windows again

$ kvm-windows -cdrom NETKVM-20081229.iso

when Windows asks for a driver for the new network interface device, point to the CD-ROM.

Virtualbox: Installing guest additions

Shut down the virtual Windows machine, then from the shell run

$ VBoxManage modifyvm "Windows" --dvd /usr/share/virtualbox/VBoxGuestAdditions.iso

Boot Windows again

$ VBoxManage startvm Windows -type vrdp

and then connect to the “console”

$ rdesktop localhost:1337

Inside Windows, open the CD-ROM drive and select VBoxWindowsAdditions.exe and follow the instructions.

Configuring and tuning Terminal Services

Terminal Services is called Remote Access in Windows XP – enable it in Start -> Control Panel -> System -> Remote Access.

One downside is that someone needs to log on before XP punches a hole in the firewall. To circumvent this either manually add an exception for the RDP service or simply turn of the firewall (that’s what I did since the host will be protected by the host’s firewall as well as the NAT feature of VirtualBox).

One of the more annoying limitations in Windows XP is that the color depth by default is limited to 16 bits.

To change this open the Group Policy Editor (Start -> Run -> gpedit.msc) and navigate to Administrative Template -> Windows Components -> Terminal Services and change the limit:

Setting maximum colour depth in for Terminal Services

Setting maximum colour depth for Terminal Services

There are a few other parameters one can change, feel free to poke around.

To be able to connect to the Windows machine using RDP you need to set a password for the user you wish connect as.

Assign a static IP to your virtual machine, this will make it easier to create the scripts further down in this article.

Install and configure SeamlessRDP

The main component in this setup is SeamlessRDP which allows one to launch a single application using RDP (remote desktop) and open only the window of that application. The drawback (with Windows XP) is that you are only allowed to open one session which means you can only launch one application at the same time.

Luckily someone grew tired of this and has made a patch to both rdesktop and SeamlessRDP that makes it possible to launch more than one application over the same SeamlessRDP session.

Installing rdesktop from CVS

First make sure that you have all the required packages for building rdesktop

$ sudo apt-get build-dep rdesktop cvs

Download rdesktop from CVS

$ cvs -d:pserver:anonymous@rdesktop.cvs.sourceforge.net:/cvsroot/rdesktop login
$ cvs -z3 -d:pserver:anonymous@rdesktop.cvs.sourceforge.net:/cvsroot/rdesktop co -P rdesktop

Download the patch to the checked out source

$ cd rdesktop
$ wget http://www.fontis.com.au/system/files/rdesktop.patch

Patch the source

$ patch -p2 < rdesktop.patch

Compile the source and install (install it as rdesktop-cvs to not interfere with the Ubuntu package)

$ ./bootstrap
$ ./configure
$ make
$ sudo make install
$ sudo mv /usr/local/bin/rdesktop /usr/local/bin/rdesktop-cvs

Installing the Windows component

Download the updated SeamlessRDP program and unpack it to c:\seamlessrdp inside the virtual machine.

Making it all come together

To ease the execution of Windows programs I’ve created a small script called $HOME/bin/winrun:

#!/bin/bash

RDESKTOP="/usr/local/bin/rdesktop-cvs"
SRDP="c:\seamlessrdp\seamlessrdpshell.exe"
SOCKET="$HOME/.rdesktop/socket"
RDESKTOP_ARGS="-k da -u username -p<password  -z -x l -M $SOCKET -A"
RHOST="192.168.10.10"
RUNNING=$(pgrep -c -U $USER -x rdesktop-cvs)

if [ -e $SOCKET -a $RUNNING -ge 1 ]
 then
    $RDESKTOP $RDESKTOP_ARGS -l "$*"
 else
    $RDESKTOP $RDESKTOP_ARGS -s "$SRDP $*" $RHOST
fi

What this script does it to check for a socket file; if it does not exist rdesktop connects the same way as the standard client. If it does exist rdesktop uses the socket and the existing connection to create another window.

Similarly I have a script to connect to the Windows desktop when I need to do some maintenance

#!/bin/bash

RHOST="192.168.10.10"
VM="Windows"

rdesktop -k da -u <username> -p <password>  -g 90% -T $VM -z -x b $RHOST

Sharing data between the host and guest

When running KVM

Remote Desktop resource redirection

This is the easiest way of sharing data but it has some drawbacks.

Enable it by adding this to RDESKTOP_ARGS in winrun:

-r disk:Home=$HOME

This will make your entire home directory available to your virtual machine but only when you are connected and not with an assigned drive letter.

RDP resource redirection active

RDP resource redirection active

Samba

One could also use a Samba server on the host

$ sudo apt-get install samba

By default the section in /etc/samba/smb.conf concerning home directories is commented out

[homes]
   comment = Home Directories
   browseable = no
   read only = no
   create mask = 0700
   directory mask = 0700
   valid users = %S

Be sure to reload the Samba service

$ sudo service samba reload

Then map the home share inside the virtual machine

> net use h: \\192.168.1.1\<username>
When running Virtualbox

The same methods can be used as with KVM but it is a lot smarter to use Shared Folders.

Shut down the virtual machine then run (in a shell on the host):

$ VBoxManage sharedfolder add "Windows" --name Home --hostpath $HOME

Boot Windows again

$ VBoxManage startvm Windows -type vrdp

and then connect to the “console”

$ rdesktop localhost:1337

Inside Windows, run the following command to map the shared folder

> net use h: \\vboxsrv\home

Tips and tricks

Running Explorer in seamless mode

If you try to run explorer.exe using the winrun method you will get the entire desktop. This is because the first explorer.exe launched will be always be used as the “shell” (or desktop).

To get around this, download Litestep, install it and set it as the shell for Windows. Now you are able to run explorer.exe and only get the file manager window presented in Linux.

Running any Windows program as a service

This might come in handy if you need a particular program running (this could be an VPN client needed to access resources from within Windows). In my example I will use the Aventail Connect Client.

Install and configure the program you wish to run as a service. Make sure it works as expected.

Download svcany.zip and unpack in your virtual machine. This example uses C:\srvany

Create a new service

> c:\srvany\instsrv "Aventail Connect Client" c:\srvany\srvany.exe

Open regedit (Start -> Run -> regedit) and nagivate to HKEY_LOCAL_MACHINE -> System -> CurrentControlSet -> Services -> Aventail Connect Client. Add a new key (Edit -> New -> Key) called Parameters and under this new key add a new string called Application with the content “C:\Program Files\Aventail\Connect\as32.exe” (this string has to match your program).

Edit service

Edit service

That’s it.

Errors (and fixes)

A comment in one of the old articles asked: When I run winrun I get this error:

VirtualBox Command Line Management Interface Version 2.1.4_OSE
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.

[!] FAILED calling a->virtualBox->OpenRemoteSession(a->session, uuid, sessionType, env, progress.asOutParam()) at line 2731!
[!] Primary RC = NS_ERROR_INVALID_ARG (0×80070057) – Invalid argument value
[!] Full error info present: true , basic error info present: true
[!] Result Code = NS_ERROR_INVALID_ARG (0×80070057) – Invalid argument value
[!] Text = Invalid session type: ‘vrdp’
[!] Component = Machine, Interface: IMachine, {ea6fb7ea-1993-4642-b113-f29eb39e0df0}
[!] Callee = IVirtualBox, {339abca2-f47a-4302-87f5-7bc324e6bbde}
/home/george/bin/winrun: line 22: 4422 Segmentation fault $RDESKTOP $RDESKTOP_ARGS -s “$SRDP $*” $RHOST

That is because you are using the Open Source Editition (OSE) of Virtualbox which does not have a RDP server build in.

Jeremy Clarkson Beat Box

I just stumbled upon this cool video.

A guy who calls himself Swede Mason has made a song using clips featuring Top Gear’s Jeremy Clarkson as a sort of “beat box”.

The video is hilarious and really well made. Enjoy.

Updated “Cold 720p” template for TViXie and WDTV

TViXiE is a GUI builder for TViX, NMT (Popcorn Hour, etc…) and Western Digital WD TV HD Player media players.

TViXiE automatically downloads movie/music information and covers and builds a graphical browsing experience for the TViX/NMT media player.

A user (Dolu) has created a template called Cold 720p which I find very pleasant to view (colors and the fact that is uses icons instead of text).

Original Cold 720p template

Original Cold 720p template

The format of the template is not quite compatible with the WD TV GUI so another user (FraD) updated the template. The result was better but still not good enough (for some reason the generated image didn’t fit the screen) so I tinkered a bit with it (moving stuff around a bit and changing some fonts and colors) before getting a result I liked.

wdtv screen shot

Updated Cold 720p template (for WD TV)

The template works a lot better when used with LaurentG’s OSD enhancement app package.

I hope you like it – here it is.

WDTV: Make video resume boot persistent

Note: This feature has now been incorporated into WDLXTV 0.5.8. Yay.

Just a quick fix to make the video resume feature boot persistent (I use b-rad’s firmware, I’m not sure how this can be done with ext3-boot, specifically the part concerning mount points may differ.

This can either be done on a computer (with the USB stick/disk attached) or telnet’ing/ssh’ing into the box. If you are doing the latter I assume you know where to find the files on the USB stick/disk).

  • Create an empty file called video_resume_point_table
  • Add this to the file S00custom-options:
    echo 'ln -sf /tmp/mnt/sda/video_resume_point_table /tmp/video_resume_point_table' >> /tmp/init.d/S99post-init

Port forwarding with OpenWRT Kamikaze

Port forwarding in itself is nothing new in OpenWRT, though the way it is done has changed dramatically between White Russian and Kamikaze.

One reoccurring problem is that port forwarding only works for packets coming in through the wan interface – In White Russian it was possible to add some clever rules to

/etc/firewall.user

but things does not seem to be so easy in Kamikaze (even if it is possible to include

/etc/firewall.user

from

/etc/config/firewall

the rules do not work.

Luckily I have a work-around.

As an example, let us say I want to forward traffic from the Internet to my server


192.168.0.1: OpenWRT router
192.168.0.2: Server

First, create the configuration for the forwarded port by adding this to

/etc/config/firewall

:

config 'redirect' 'www'
    option 'src' 'wan'
    option 'proto' 'tcp'
    option 'src_ip' ''
    option 'src_dport' '80'
    option 'dest_ip' '192.168.0.2'
    option 'dest_port' '80

config 'rule'
    option 'src' 'wan'
    option 'proto' 'tcp'
    option 'src_ip' ''
    option 'dest_ip' ''
    option 'dest_port' '80'
    option 'target' 'ACCEPT'
root@OpenWRT:~# /etc/init.d/firewall restart

That is it, traffic coming to the wan interface is now forwarded to the server.

But there is a problem. If you try to connect to www.my.site (which resolves to your public IP) you will get the webif of OpenWRT instead of the website.

To circumvent this we need to redirect (or proxy) the traffic to the web server as there does not seem to be any easy way to do “lan to lan port forwarding”.

For this I decided to use xinetd since it has native support for port redirection.

Start by moving the webif to another port, the configuration is in

/etc/config/httpd

:

config 'httpd'
    option 'home' '/www'
    option 'port' '1080'
root@OpenWRT:~# /etc/init.d/httpd restart

(The configuration for the SSH server is in

/etc/config/dropbear

)

Now install xinetd – It’s not in the “native” OpenWRT packages but can be found in OptWare:

root@OpenWRT:~# ipkpg install http://ipkg.nslu2-linux.org/feeds/optware/openwrt-brcm24/cross/unstable/xinetd_2.3.14-8_mipsel.ipk

Now, either copy

/etc/services

from a Linux/Unix machine or add this line:

www     80/tcp      http        # WorldWideWeb HTTP

Then create the file

/opt/etc/xinetd.d/http-forward

:

service http
{
   flags = REUSE
   socket_type = stream
   wait = no
   user = root
   redirect = 192.168.1.2 80
   log_on_failure += USERID
}

If you plan on using a lot of OptWare packages you could at a custom start-up script that calls all S-scripts in

/opt/etc/init.d

- But I opted for a single OpenWRT-style init-script for xinetd.

/etc/init.d/xinetd

:

#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org

START=39
start() {
    [ -x /opt/sbin/xinetd ] && {
        /opt/sbin/xinetd
    }      
}
root@OpenWRT:~# /etc/init.d/xinetd enable
root@OpenWRT:~# /etc/init.d/xinetd start
root@OpenWRT:~# ps aux | grep [x]inetd
 1599 root      1900 S    /opt/sbin/xinetd
 1935 root      1900 S    /opt/sbin/xinetd

logread should show something like

May 10 23:25:45 xinetd[2166]: Reading included configuration file: /opt/etc/xinetd.d/http-forward [file=/opt/etc/xinetd.conf] [line=15]
May 10 23:25:45 xinetd[2166]: xinetd Version 2.3.14 started with no options compiled in.
May 10 23:25:45 xinetd[2166]: Started working: 1 available services

Now try to connect to the forwarded port, there should be something like this in the log:

May 10 23:25:53 xinetd[2166]: START: http pid=2168 from=192.168.1.240

XFCE: Unable to perform shutdown

At some point during the Jaunty test cycle shutting down and rebooting the machine stopped working with the Action Buttons menu applet – It would fail with the message “Unable to perform shutdown” and some HAL-related messages.

While annoying I didn’t put any real effort into solving the problem, until today.

I didn’t have to look long though as the answer was in the Arch Linux forum.

Open the file /etc/PolicyKit/PolicyKit.conf and add these lines

<match action="org.freedesktop.hal.storage.mount-removable">
<return result="yes"/>
</match>
<match action="org.freedesktop.hal.power-management.shutdown">
<return result="yes"/>
</match>
<match action="org.freedesktop.hal.power-management.reboot">
<return result="yes"/>
</match>

Add them inside the config stanza.