Links

Debian based systems (and derivatives such as Ubuntu) have a facility built into
PAM that can display a dynamically generated MOTD on login. Debian doesn’t use
this by default, but Ubuntu does. I wanted to add this to my Debian
testing/Jessie boxes, but the Ubuntu version performs horribly - if you’ve ever
wondered why Ubuntu hangs for a second or so upon login while displaying the
MOTD, this is why.

Taking a closer look at the Ubuntu /etc/update-motd.d/ files, it was clear to
me why the default Ubuntu implementation is so slow - Two reasons, in fact.
First, text that doesn’t change frequently is generated every time, such as the
hostname banner and the script to display the number of available updates. The
latter is horribly slow and something that doesn’t need to be checked at every
login anyway. Second, the script for truly dynamic content forks way more
processes than necessary and can be easily tuned and improved.

With my revisions to these scripts and process, my logins are instantaneous and
I’ve even added running the MOTD display on each invocation of
urxvt, the terminal program I
use.

Make static content static

What I did was separate the scripts into two configuration directories - one
containing dynamic content, generated on each execution (just like the default),
and a second for static content, which is only generated occasionally via cron
(every 30 minutes).

The cron job uses run-parts to run the static content scripts, which write to
/var/run. These files are then read directly via the dynamic content scripts.

Here’s a brief overview of the layout, but more detail about the scripts is
provided below as well.

/etc/update-motd.d/
contains the dynamic content scripts. These scripts are also responsible for
displaying the static files from /var/run. There must at least be one script
in this directory for each static script, but there can also be additional
dynamic content scripts with no corresponding static content. Note that scripts
that simply cat the statically generated files are simply symbolic links to
00-header.

Make dynamic content faster

As mentioned above, the default /etc/update-motd.d/10-sysinfo file from Ubuntu
does considerable more forking than is necessary - even doing things such as

cat foo | awk # Don't do this!

instead of:

awk <foo

The cat and pipe are entirely unnecessary.

Additionally, some of the awk scripts piped to other awk scripts, or were pipes
from grep to awk, which can all be handled via a single awk script. Also,
commands like “ps” or “free” were being run when the information is already
available in “/proc” My resulting script runs about 3 times faster than the
original, entirely excluding the static content improvements, and is
significantly nicer on system resources!

Where ssh would hang for a second or so on each login, it’s now instantaneous.

You’ll need figlet and update-notifier-common packages, if you don’t already
have them.

$ sudo aptitude install figlet update-notifier-common

A closer look at the scripts

The dynamic scripts

Here’s the updated /etc/update-motd.d/10-sysinfo:

#!/bin/bash## 10-sysinfo - generate the system information# Copyright (c) 2013 Nick Charlton## Authors: Nick Charlton <[email protected]>## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License along# with this program; if not, write to the Free Software Foundation, Inc.,# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.## The upstream version of this script was very inefficient - forking processes# when not needed. This version significantly reducses the number of processes# required to get the same info, and as a result is much, much faster.## Additionally, static-ish stuff like the hostname and packages to install# is only generated once every 30 minutes (or as configured in cron).## As a result, this shaves off the amount of time required to login to the system# by about 1 second or so, and when running as part of urxvt is nearly instant.load=`awk '{print $1}' /proc/loadavg`root_usage=`df -h / | awk '/\// {print $(NF-1)}'`memory_usage=`awk '/^MemTotal:/ {total=$2} /^MemFree:/ {free=$2} /^Buffers:/ {buffers=$2} /^Cached:/ {cached=$2} END { printf("%3.1f%%", (total-(free+buffers+cached))/total*100)}' /proc/meminfo`swap_usage=`awk '/^SwapTotal:/ { total=$2 } /^SwapFree:/ { free=$2} END { printf("%3.1f%%", (total-free)/total*100 )}' /proc/meminfo`users=`users | wc -w`time=`awk '{uptime=$1} END {days = int(uptime/86400); hours = int((uptime-(days*86400))/3600); printf("%d days, %d hours", days, hours)}' /proc/uptime`processes=`/bin/ls -d /proc/[0-9]* | wc -l`ip=`/sbin/ifconfig eth0 | awk -F"[: ]+"'/inet addr:/{print $4}'`printf"System load:\t%s\t\tIP Address:\t%s\n"$load$ipprintf"Memory usage:\t%s\t\tSystem uptime:\t%s\n"$memory_usage"$time"printf"Usage on /:\t%s\t\tSwap usage:\t%s\n"$root_usage$swap_usageprintf"Local Users:\t%s\t\tProcesses:\t%s\n"$users$processesecho

The scripts that cat the static content look like the below, and actually,
there’s just one of these, the rest are simply symbolic links to the first, as
we use the script filename to determine which static file to show:

In my case, I have 00-header, 20-sysinfo, and 90-footer, matching the same
dynamic scripts.

The static scripts

The static scripts are 00-header, 20-sysinfo, and 90-footer, as listed
just above. There is not a 10-sysinfo script in the static scripts, since
that is dynamic only. Make sure you understand run-parts, as it is key to how
these scripts are executed.

Let’s take a look at 00-header next. This isn’t much different than the
original, except we dup the stdout file descriptor to write to our file in
/var/run (a partial filename is passed in as the first argument).

I also chose a figlet font that I like better as
well, which doesn’t take up quite as much space and, well, it looks spiffy.

#!/bin/sh## 00-header - create the header of the MOTD# Copyright (c) 2013 Nick Charlton# Copyright (c) 2009-2010 Canonical Ltd.## Authors: Nick Charlton <[email protected]># Dustin Kirkland <[email protected]>## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License along# with this program; if not, write to the Free Software Foundation, Inc.,# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.OUT=${1}$(basename $0)exec >${OUT}[ -r /etc/lsb-release ]&& . /etc/lsb-release
if[ -z "$DISTRIB_DESCRIPTION"]&&[ -x /usr/bin/lsb_release ]; then# Fall back to using the very slow lsb_release utilityDISTRIB_DESCRIPTION=$(lsb_release -s -d)fi
figlet -f smslant $(hostname)printf"Welcome to %s (%s).\n""$DISTRIB_DESCRIPTION""$(uname -r)"printf"\n"

Here’s 20-sysinfo - the most expensive part of the original script, which
determines how many packages are out of date and whether a system reboot is
needed:

#!/bin/bash## 20-sysinfo - generate the system information# Copyright (c) 2013 Nick Charlton## Authors: Nick Charlton <[email protected]>## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License along# with this program; if not, write to the Free Software Foundation, Inc.,# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.OUT=${1}$(basename $0)exec >${OUT}
/usr/lib/update-notifier/apt-check --human-readable
/usr/lib/update-notifier/update-motd-reboot-required
echo

And finally, the diminutive 90-footer which just appends the content of
/etc/motd.tail if it exists:

#!/bin/sh## 90-footer - write the admin's footer to the MOTD# Copyright (c) 2013 Nick Charlton# Copyright (c) 2009-2010 Canonical Ltd.## Authors: Nick Charlton <[email protected]># Dustin Kirkland <[email protected]>## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License along# with this program; if not, write to the Free Software Foundation, Inc.,# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.OUT=${1}$(basename $0)exec >${OUT}[ -f /etc/motd.tail ]&& cat /etc/motd.tail ||true

Those scripts could probably use some fencing, such as checking that the
directory argument is valid, and that the directory exists.

File layout in /etc

The layout of /etc/update-motd.d and /etc/update-motd_local.d should look
like the following:

A few weeks ago I discovered fwknop which
is a very clever mechanism to secure services. I’m using this so I can ssh into a
Linux server on my home network without opening the sshd port up to the world.

Single packet authorization works by sending a single, encrypted UDP packet to a
remote system. The packet is never ACKd or replied to, but if it’s validated by
the remote system, then it uses iptables to temporarily open up the service port
for access (the filter is limited to the client’s IP address). If the packet
isn’t valid, it is simply ignored. In either case, to an external observer the
packet appears to go into a black hole. After a user-configurable amount of time
(30 seconds by default), the service port is closed, but stateful iptable rules
keep existing connections active.

This is really great because all ports to my home IP address appear, from the
internet, to be black holes - my router firewall drops all incoming packets, and
the specific ports open for fwknop are dropped via iptables on my Linux server.

Configuring this solution isn’t too difficult if you are familiar with networking
and Linux network and system administration, but it can be a bit tricky to test.

Server Configuration

There are four areas that need to be configured on the server-side:

Fwknop needs to be configured with appropriate ports and security keys

iptables policy needs to be created for each service port

Services need to listen on appropriate ports

Router firewall needs to forward fwknop and service ports to the server

Note the order of rules is important. Make sure that the FWKNOP_INPUT rule is
before the port-specific rules. Likewise, make sure the ESTABLISHED,RELATED
rule for each service is before the DROP rule for that service port.
The last rule is subtle. fwknopd does not bind to the SPA socket port -
it transparently sniffs for UDP traffic, hence we drop traffic in keeping with
the rest of my general firewall rules to blackhole all inbound traffic.

Before you start fwknop, and open up ports on your firewall, don’t forget to make sure these
rules are in place. In that case, if you create these rules manually, use rule order “1”
instead of “2”, as you are creating the rules before fwknop has added it’s rule.

/etc/fwknop/fwknopd.conf excerpt from the server:

PCAP_FILTER udp port 12345;

On my debian testing/Jessie server I also had to add this line to fwknopd.conf:

From this config, you can see that the fwknop port is 12345, and sshd is
listening on 54321 (though these aren’t the real ports or FQDN in use). The
KEY_BASE64 and HMAC_KEY_BASE64 values need to match between client and server. I
chose to use
symmetric keys
but you can use asymmetric keys via GPG if you prefer.

See the fwknop documentation for more information on configuring everything.
There are a lot of options, so you’ll have to figure out what to do based on
your individual needs.

I’m using a free dynamic DNS service so that I don’t have to remember the
dynamic IP address assigned by my ISP.

This has been tested with Debian on both stable/Wheezy and testing/Jessie. For Wheezy,
make sure you are using the latest version from wheezy-backports.

Further Reading

The documentation
is decent, and I’ve found this solution works very nicely for me, without
exposing any detectible open ports on my network. Unlike with simple port
knocking, it is virtually impossible for someone to use packet capture replay to
access the system. Because all packets are dropped unless the authorization
packet opens up the service port, it is completely undetectable via port
scanning that fwknop is even in use.

A large part of the reason for this is diversification away from Google. As
much as I love Google for many reasons (and will continue to be a faithful
Android user for the near future), I am moving most of my stuff off Google
infrastructure.

I’ll write more about the reasons for this later, as well as mention which
services I’ve migrated to (email, search, browser, etc).

Please bear with me as I finish migrating all the content and fix up some formatting, images, and such here and there…

Update: Please see newer posts as I have abandoned Octopress for straight
Jekyll. Octopress, as it turns out, makes things harder, not simpler.

After kicking around a few different desktop environments and
window managers, I've settled in with i3 as my window manager of choice - and
no desktop environment at all. This is by far the most
productive user interface I've used and is now in residence on
my home laptop, work laptop, work desktop, and shiny new
Intel-based Chromebook (as well as it's predecessor - an
ARM-based Chromebook). I'm still using the Debian distribution of Linux (mostly Wheezy, but also one Jessie/Testing), which has been
fantastic - and I can't recommend it enough.

You can read my previous blog for the few weeks that I used a
BlueTile-derived xmonad
configuration on top of the xfce desktop environment. While this
worked pretty well most of the time, and was fairly productive,
xmonad is a pain as it requires writing haskell code to change
the configuration. A found this to be a bit burdensome over
time - when I just want to tweak a setting I'd much rather just
tweak the setting, and not have to debug code.

i3 is just about as flexible as xmonad, but everything is in a
regular configuration file, so it doesn't require users to
write their own window manager in haskell to get the
configuration you want.

It's easy to plug-in different implementations in i3 for cases
where the configuration isn't sufficient - for example I found
the default i3 status bar to be a bit limiting for the
configuration I wanted, so I handle that via conky, outputting in JSON
(i.e. not using conky's X integration at all) to i3. System
notifications come via dunst. dmenu is used as a
launcher. Everything plays nicely together, and configuration
is a snap.

Not running a regular desktop environment has not in any way
been an issue. I can still use any application (for example,
see "gnome-screenshot" used in the screenshot above, although more
recently I've switched to "scrot"). I don't
use graphical file managers as a general rule, and while I
could probably install nautilus or thunar, I've found rox-filer
works just as well and doesn't require many dependencies.
Debian already includes the necessary wiring such that
installing i3-wm sets up a lightdm session.

Suspend, shutdown, reboot, logout is handled via simple
keybindings in i3 or from a terminal - I have no problem typing
"sudo shutdown -h now", and I can type it just as fast as
navigating to some menu.

I found that I was comfortable and productive in i3 within just
a few days - you definitely have to make a commitment to learn
keybindings and modes, and understand the container model, but
once you do it's amazing how quickly you can navigate
applications, workspaces, and desktops without ever having to
take your hands off the keyboard. Learning how to effectively
use workspaces for your workflow is super important - i3 allows
several different layouts and each workspace can have it's own.
Switching between layouts is a snap, and I find myself
switching, for example, from a tiling layout to a tabbed layout
to get a larger window. i3 remembers layouts, so switching back
to tiling puts everything back how it was before. Very
nice.

Anyone who's ever seen my desktop knows that I like to have a
lot of terminal windows open, very specifically placed. In a
traditional window manager doing this is painful - either I
open a bunch of terminals, and manually move them around and
resize them (I absolutely hate doing this), or write a
script that starts all the terminals with the right geometry
(also a painful operation, working out the geometry of each
window). With i3, and a tiling layout, you never worry about
window geometry or location - which is awesome. If I want 4
equally sized terminals on a workspace (with a horizontal
tiling default layout), I use the following keystrokes -
Super-Enter, Super-Enter, Super-v, Super-Enter, Super-Left,
Super-v, Super-Enter. Once you learn the keybindings and
container model, this sort of sequence becomes second nature
and takes just a few seconds.

This configuration is really great and runs fast, with low
resource usage - very important when running on a Chromebook
(my install only requires around 2GB of disk) and gives more
resources to things such as Java VMs when running on my fat
work desktop.

I've decided not to dump my configuration in this post - code
in blogger doesn't work all that well (see my previous post)
and the configuration gets stale when I don't bother to update
it (also see my previous post, which does not reflect my final
configuration). Although it won't help with the latter, you can
find my configs, at least some version of it, on github.

UPDATE:
I've switched to the i3 window manager as of a couple of months back.
i3 is really great - I recall someone
saying something along the lines of "xmonad is not a window
manager - it's a library for people who want to write their
own". This is very true, and I don't miss hacking around in
haskell since switching away from xmonad. Additionally, i3
doesn't require working around deficiencies in xmonad such as
spoofing the window manager to make Java applications
work

For the past couple of months I've been playing with several
different Linux distributions, desktop environments, and window
managers. I can backup, reinstall, and restore to a fully
working state - even when changing distributions - within two
or three hours, so the barrier of entry is fairly low for me. I
do limit myself to the world of Debian-based systems, since apt
is great and familiar, and there are lots of good reasons to
live somewhere in the Debian ecosystem.

For several years I used Kubuntu, until KDE4 came out. KDE4 was
released way before it was ready, and while I slogged along
with it for about 6 months until I finally gave up and switched
to Xubuntu with XFCE. I really like XFCE for the most part -
it's simple and fast, but sometimes lacking in features and
feels a bit old. When Unity came out, I gave it a try. A very
short one. Unity is an unusable disaster. At this point I
decided to abandon Ubuntu and give LinuxMint a try, which I did
moving back to XFCE. I switched to Cinnamon when it came out,
and I have to say I really like Cinnamon in general - it's
based on Gnome Shell so is up-to-date, but it looks and works
like Gnome2, making it super accessible and usable.

Although I think LinuxMint has some good points, it's based on
Ubuntu and there's very little reason to use it over Ubuntu (if
that's what you want to use), especially now that CInnamon is
available for several different distributions, including Ubuntu
as a PPA. So, I went back to Xubuntu with Cinnamon.

But, I'm really not very happy with Ubuntu. Go take a look at
ubuntu.com - you won't find the word "linux" anywhere on that
page. That's not acceptable. Ubuntu is a Linux distribution and
they should advertise that fact. Ubuntu has shown poor
direction in other ways as well, for example the horrid Unity
interface and writing their own display system, Mir, to replace
Xorg.

Ubuntu is a Debian distribution, so why not just install
Debian? I probably should have thought about this a long time
ago!

I'm now running Debian testing (Jessie) on 4 different
computers - 3 are amd64 systems, 1 (the one I'm typing this on)
an arm based Chromebook.

Debian was just as easy as LinuxMint or Ubuntu for installation
- and supports LUKS so I can run with full disk encryption on
my laptops (though not the Chromebook, unfortunately).
LUKS/dm-crypt is the only way to go - encfs and ecryptfs are
horrible hacks, in general. And all the packages I want are
available in base Debian.

Jessie, even though it's "testing", does still lag a bit behind
other distributions in some ways, but I've found it recent
enough for everything I do - and not as risky as Debian
unstable, Sid. I wasn't interested in Debian stable, as it's
just too far behind for me.

OK, so after installing Debian I went with XFCE, which is a
nice choice because all my hardware supports it, so I can use
the same configuration and setup everywhere, even the
Chromebook. XFCE is also familiar to me, having used it for a
couple of years, generally happily.

For fun, I decided to give Gnome Shell a try. Many people have
been pretty negative about Gnome Shell, but I actually found it
to be pretty nice and usable, after I installed several
extensions to get some better usability. With Gnome Shell you
have to think a little bit differently about window management
and make good use of workspaces to organize things. One thing I
didn't like about Gnome Shell was how much I had to move the
mouse to do things.

Still, I managed to get a pretty usable workflow out of Gnome
Shell, and played with some nice tiling extensions - shellshape
and shelltile, which sort of worked. However shellshape doesn't
support multiple monitors (which I like on my work system), and
shelltile was too mousy though a nice idea. If you are
interesting in tiling window managers on Gnome Shell, and only
have one monitor, give shellshape a try - it's pretty nice,
with some shortcomings.

One issue with Gnome Shell is that it doesn't work on my
Chromebook, since it doesn't have accelerated video (currently,
until I get armsoc running on it). The fallback mode is usable,
much like Gnome 2, but then I also couldn't run the nifty Gnome
Shell extensions I discovered.

I've always been intrigued by tiling window managers, which
automatically arrange windows such that nothing overlaps, and
which typically have very simple interfaces that maximize
screen real estate (for example, by not having title bars on
windows). They also tend to be driven by keyboard, minimizing
mouse usage.

I've tried xmonad before, but was scared away by having to
basically write a configuration in haskell. I tried a few other
tiling window managers as well, but never found any that I
really liked or felt like I wanted to invest the time in
them.

This takes me back to shellshape - which uses the same
keybindings for BlueTile, a xmonad-based tiling window manager.
I liked the key bindings in shellshape, so I thought maybe that
would make BlueTile accessible. I was also curious if I could
run xmonad it with XFCE so I could have my usual panels and a
nice menu (the menu plugins for xmonad are... primitive at
best).

So how did my experience go? Well, here I am typing this on my
Chromebook, running XFCE and xmonad with a BlueTile based
configuration. I used this same configuration on my work laptop
and desktop all day today as well, and found it very productive
and fast, but I sure have a lot of new keybindings to
remember!

Below is my .xmonad/xmonad.hs file. In order to use this
in Debian, all I needed to do was install the xmonad
package, as it already has BlueTile in the base xmonad package!
Note that there is a separate bluetile package - you can
install this, but you will not be able to apply my customized
settings, if you so desire.

It took me many hours to get this configuration working and
looking the way I wanted to. I'm not completely happy with my
approach to eliminating the window title bars, but it does
work, though it's a bit hackish - and relies on having certain
colors configured in XFCE (you may need to change "#cecece"
below).