RSS Atom Add a new post titled:
practical dynamic network setup for laptops

I really wanted to describe my current network setup I use on my laptop. So here is this post.

My objectives were: keep the configuration simple and easy to use for the user.

What I have

My laptop automatically connects to wifi (for configured SSIDs) and obtains an IP address. If I connect the ethernet cable it gets an IP there as well and the same goes for USB (tethering). Each interface gets the default route and they are inserted with different metrics. The wired connection wins. If the preferred interface gets disconnected (e.g cable pulled out) it automatically starts to use the other available interface.

# ip route show

default via dev usb0  metric 267 
default via dev wlan0  metric 303 dev wlan0  proto kernel  scope link  src  metric 303 via dev lo  metric 303 dev usb0  proto kernel  scope link  src  metric 267 via dev lo  metric 267 




This is the dhcp client daemon that tries to get IP addresses on interfaces that are operational mode up. When a link comes up which is: usually after cable insertion for wired ethernet or successful AP association for wireless.

This tool also takes care to add the default routes with the mentioned metrics attached.

To get rid the legacy isc dhclient I did (there may be cleaner ways):

dpkg-divert --divert /sbin/dhclient.orig --rename /sbin/dhclient
ln -s /bin/true /sbin/dhclient

I created a systemd unit file (the default init script is also fine): /etc/systemd/system/dhcpcd.service

Description=dhcpcd5 - IPv4 DHCP client with IPv4LL support

ExecStart=/sbin/dhcpcd5 -B -L -d


wpa_supplicant and /etc/network/interfaces

iface wlan0 inet dhcp
  wpa-conf /etc/network/wpa_supplicant.conf

wpa_supplicant.conf looks like this for me:


    group=CCMP TKIP
    subject_match="/C=HU/ST=Budapest/L=Budapest/O=Pazmany Peter Katolikus Egyetem/"



I use wpa_cli to control the wifi configuration or if I need to add ad-hoc changes (e.g for debconf). It is also easy to select networks to prefer or just disable all except for one.

The networks needs to be up:

ifup eth0
ifup wlan0
rsnapshot with zfs snapshotting

First of all I feel bad, because I promised John Goerzen to share my experiences, but as with other things I am lagging behind.
Still better late than never.

A few words on rsnapshot

rsnapshot is a great tool for making efficient backups. It basically creates directories like


The directory contents are hard linked on each other and then it is overwritten when the contents (files) are changed.

The way this is achived is by cp -al daily.0 daily.1 then rsync-ing the fresh content to the pre-populated directories. Sometimes rm -rf daily.N (where N is the number of days you want to keep) is run remove old content. (For simplicity I do not talk about weekly and monthly features of rsnapshot).

There is also a rollback mechanism in place if the backup fail to get the last consistent state for the next run as a base.

The problem is that cp -al and rm -rf and the rollback mechanism itself is an expensive operation and does not use the possibilities of ZFS.

ZFS snapshots

ZFS have a convenient way to create snapshots of datasets which are consistent point-in-time state of the filesystem. The snapshots are read-only, mountable and almost free with zfs. As ZFS is a copy-on-write filesystem when you modify a file it is copied first and when you have a snapshot the original is kept after it is changed. Only the changed content takes space.

ZFS and rsnapshot

I choose an easy and convenient way to integrate the ZFS snapshotting from rsnapshot some may call it a hack.

There is a cmd_cp configuration parameter and I wrote the script that does the job for me:


#echo "snapshot created at $(date)" > $2/info

# name of the volume
zname=$(dirname $(echo $2 | cut -b 2-))

# name of the future snapshot
bsname="$zname@rsnap-$(date +%F)"

for i in 1 2 3 4 5
  # exit if success
  zfs snapshot $sname 
  if [ "x$?" == "x0" ]; then
    echo "backup started at $(date)" > $2/info
    exit 0
  # iterate over it if already exists

echo ERROR zfs_cp: something is really broken
exit 1

So every rsnapshot directory is a seperate dataset and when the rsnapshot starts the tedius work and of running cp is eliminated. I will always only have daily.0 there never will be a daily.1 as my script never creates it. This way the rm -rf and the rollback part is also eliminated as there is nothing to delete and nothing to rollback to. If a backup does not complete for one reason or another the next one supposed to correct it.

One thing that is missing: Eliminating and removing of old snapshots. I to keep the 7 recent backup then keeping 4 weekly is fine and 6 monthly. There are tools available to do that I need to look at that.

zfs list -t all sniplet:

NAME                                                  USED  AVAIL  REFER  MOUNTPOINT
backup14q1/rsnapshot_1                               1.85T  15.6T  1.45T  /backup14q1/rsnapshot_1
backup14q1/rsnapshot_1@rsnap-2014-01-08              5.38G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-09              3.82G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-10              3.82G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-11              4.06G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-12              3.86G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-13              5.72G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-14              3.89G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-15              3.90G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-15-v1           3.66G      -  1.44T  -
backup14q1/rsnapshot_1@rsnap-2014-01-17              3.89G      -  1.45T  -
backup14q1/rsnapshot_1@rsnap-2014-02-12              4.21G      -  1.45T  -
backup14q1/rsnapshot_1@rsnap-2014-02-13              4.19G      -  1.45T  -


Some features of rsnapshot like:

  • weekly, monthly snapshots
  • rollback in case of failures

are lost in the process, but overall I am satisfied with the end results. Further improvements are possible.

pvmove makes your XFS filesystem corrupt (or unavailable at least)

Yes, this is sad, but true.

It just happened to me that I migrated between two 2TB size PVs. One on an old and slow FC storage, the other one a fast and new.

Steps (as usual):

# sdl1 is the new PV (let's create it)
pvcreate /dev/sdl1 

# extend the VG with this new PV
vgextend somevg /dev/sdl1

# now move off from the old one
pvmove /dev/sdd1 # with -n one can tell which LV should be moved

# the old PV can be removed with
vgreduce somevg /dev/sdd1

# and this a useful command to find which LV is on which PV
# lvs --segments -o +pe_ranges

And this is it! At least this should work and it worked for me before, but not now.

Instead what I got is:

I/O error in filesystem ("dm-1") meta-data dev dm-1 block 0xe0e280       ("xfs_trans_read_buf") error 11 buf count 4096
xfs_force_shutdown(dm-2,0x1) called from line 395 of file /build/buildd/linux-lts-backport-natty-2.6.38/fs/xfs/xfs_trans_buf.c.  Return address = 0xffffffffa0111943
xfs_imap_to_bp: xfs_trans_read_buf()returned an error 5 on dm-2.  Returning error.
Filesystem dm-2: I/O Error Detected.  Shutting down filesystem: dm-2
Please umount the filesystem, and rectify the problem(s)
Filesystem dm-2: xfs_log_force: error 5 returned.
xfs_force_shutdown(dm-2,0x1) called from line 1111 of file /build/buildd/linux-lts-backport-natty-2.6.38/fs/xfs/linux-2.6/xfs_buf.c.  Return address = 0xffffffffa011cc03

(I suppressed the same messages.)

I had to shutdown the application (which was a pain for the users) and let is continue its work. Here is the explanation:

[dm-devel] [BUG] pvmove corrupting XFS filesystems (was Re: [BUG] Internal error xfs_dir2_data_reada_verify)

Hopefully after it finished and I rebooted the system it came up OK. 7 hours of downtime. At least I started it late.

Zimbra preauth and Shibboleth

How Shibboleth is used to authenticate PPKE users

Zimbra has a mechanism called preauth which makes it possible to interface with other authentication systems.

The big picture

A Shibboleth SP with apache is needed. This authenticates the user with shibboleth and relays it to Zimbra.

In our case shibboleth attribute eduPersonPrincipalName is the same as the email address in Zimbra. The identity provider releases this attribute to the service provider. There a Perl CGI script accesses this as an environment variable. After a valid shibboleth session is established with the SP the user is redirected to a Zimbra URL with a GET variable encoding a signed cookie which identifies the user to Zimbra. This cookie is validated and user access is granted if found valid.

Shibboleth SP setup

From the apache side this is the main part of the configuration. This is needed for the directory containing our custom cgi script. (shibboleth2.xml is needed as usual)

<Directory /where-your-cgi-is>
  AuthType shibboleth
  require shibboleth
  ShibRequireSession On

The cgi script

First the shared secret must be obtained with zmprov:

prov> gdpak

This value is required for the script.


use strict;
use warnings;

use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
use Data::Dump qw(pp);
use CGI;

my $cgi = new CGI->new;

my %k;

#prov> gdpak
#preAuthKey: aaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbccccccccccccccccc


my $zmda = $ENV{"eduPersonPrincipalName"};
my $urlbase = "";

unless($k{$domain}) {
  print $cgi->header(-status=>'500 Service Unavailable');
  print "unknown domain, are you authorized for zimbra?";

my $redir = buildZimbraPreAuthUrl($k{$domain},

print $cgi->redirect( -uri => $redir ); 

## @method private string buildZimbraPreAuthUrl(string key, string url, string account, string by)
# Build Zimbra PreAuth URL
# @param key PreAuthKey
# @param url URL
# @param account User account
# @param by Account type
# @return Zimbra PreAuth URL
sub buildZimbraPreAuthUrl {
  my ( $key, $url, $account, $by ) = splice @_;

  # Expiration time
  my $expires = 0;

  # Timestamp
  my $timestamp = time() * 1000;

  # Compute preauth value
  my $computed_value =
    hmac_sha1_hex( "$account|$by|$expires|$timestamp", $key );

  # Build PreAuth URL
  my $zimbra_url;
  $zimbra_url .= $url;
  $zimbra_url .= '?account=' . $account;
  $zimbra_url .= '&by=' . $by;
  $zimbra_url .= '&timestamp=' . $timestamp;
  $zimbra_url .= '&expires=' . $expires;
  $zimbra_url .= '&preauth=' . $computed_value;

  return $zimbra_url;

Zimbra can redirect unauthenticated users to our cgi

We can achive that with changing the domain attribute zimbraWebClientLoginURL.

Ubuntu grub setting when upgrading zimbra

zimbra on ubuntu upgrade woes

So I (and my co-worker) at my previous place wasted 4 hours because someone thought that skipping the boot prompt (in Ubuntu 10.04.4) is a good idea.

Try to do that in a virtual machine when you have to boot the server to init 1 because otherwise a service would start what you actually want to maintain. If that starts and mail clients connect your backup is not uptodate anymore...

The update process failed because of a stale pid file. We actually pull the 4 hours old backup, cleaned up that stale pid file and now everything is smooth.

... UPDATE: and now a kernel bug. Love you Ubuntu, really :-(

Ideas for the Perl BoF

This used to be a draft. Now it is part of the gobby document for the Perl BoF session.

my agenda regarding debian-perl

  • knowing the perl tools (used in the debian infrastructure) better
  • keeping Mojolicious in debian uptodate
  • promoting the use of it in debian
  • making enhancement to the perl tools
    • first I thought about collecting best practices and recommendations
      • dam encouraged me to just do it :-) (aka. shut up and hack)
    • it seems (I hope) that I will be able to fix some problems related to packages.d.o
Debconf13 with some pictures

I am at debconf13

First here are some pictures of debconf13 at Vaumarcus, Switzerland. The landmark with the nearby lake (Neuch√Ętel) is beautiful.

bar building, talk room2, front desk
lake and some buildings
main talk room, dining room
after sunset

I will do some posts about my experiences and some of the achievements I made.

Update: Joey also has some pictures from the cheese and wine party:

The idea of open access

Open vs. authenticated only access

I really liked the idea of providing open comment access to pages here. But today some spammer found the site and I had to disable it :-( .

Comments are still welcome, but one have to authenticate first.

Anonymous comments are moderated first, anonymous edit are not allowed. It should be easy to authenticate with with openid.

Non-Puppet best practice

Non-Puppet best practice

A friend of mine asked me how I use puppet and what I consider best practice. He thinks I still use puppet as I gave a talk about it 6 years ago (in Hungarian).
(Oh, that was quite a while ago :-) )

At that time I really thought Puppet is the way to go, but a few years ago I really did not have time to keep puppet up and running as I was reassigned at work to another organizational unit and many thing changed at once.

About a year ago I revisited the idea of reviving/redeploying puppet, but as my thinking changed recently I started to feel more disgust as I tried to use it again.

There are usability problems, upgrade incompatibilities, receipts requiring newer puppet etc... I will not go into the details as Martin summarized it quite well and I agree with him.

Slaughter instead

Instead of puppet I use slaughter now. Only for some basic things like:

  • deploying configuration files
  • installing packages
  • adding all admins with ssh keys to all machine

and I did not yet deployed it to all machine.
Still I feel confident because of Perl. There is no hidden magic involved. No DSL to learn. It has less power, but much more easier at the same time.

General ideas, may work with puppet...

My idea (that requires some work in Slaughter) is to use some external database/data structure and using that instead of defining the same multiple times.

What do I mean? I do not want a fancy way to configure DNS, Nagios, Graphite, PF and defining the same over and over again.
Instead define it once "here in my public http service running on host myhost.domain port 80" then the configuration management should generate a

  • DNS record for the host (if it does not have already)
  • configure the firewall to let port 80 throu
  • install apache on the host
  • monitor the service

Puppet has a mechanism (module?) called Hiera that lets you do this. I think with Chef this is built-in. (Chef is so hard to start with that I did not dared to try it at all.)

recent link