Diskless Linux Kiosks: Theoretical Ubuntu Version
From July 2000 through August 2009, DNA Lounge featured a
number of flatscreen internet kiosks scattered around the club.
In the time before everyone had a cell phone, and everyone's cell
phone included a decent web browser, this was very convenient.
In This Modern World of 2009, however, I found that the kiosks
didn't really provide much. Also, they were a constant maintenance
headache, so in August 2009, we finally retired them, as described in
my Jul 5,
Aug 11, and
Aug 27 blog posts.
They were pretty cool, a unique and notable feature for a
night club, and a more-or-less interesting technical challenge.
But the time had come for them to join the dustbin of computing
The rest of this document describes my attempts at
getting the kiosks working using Ubuntu 7.10. I never
quite got that working reliably. For how they actually
worked, see the previous page.
Our goal for the kiosks was for them to be usable for web browsing,
IRC, AIM, and so on. (IRC was, in fact, still a going concern at the
time.) When most people set up kiosks, they tend to try and lock them
down so that you can only run a web browser, but that's a little too
limiting, since I want people to be able to run other applications too
(telnet, ssh, irc, and so on.) So really, I wanted to give access to
a complete desktop system. But do so safely and reliably.
I decided to set them up as Linux systems running the
GNOME desktop, preconfigured
with all the common applications people might want to run. However, I
needed to figure out a way to make the system robust enough that one
user couldn't screw it up for another, on purpose or accidentally. The
system would need to be locked down enough that it was easy to reset it
to a working state.
(Incidentally, though our kiosks themselves are hardwired, we also
provide free wireless network access within the club: 802.11b
SSID = "dnalounge", no registration required.)
So, I had the following goals:
- When the machine boots up, it should automatically log itself
in as ``guest'', and go to the desktop without requiring a login dialog.
- It should be possible to pull the plug on the machine at any
time without loss of data: at no time should fsck need to
- Logging out or rebooting should reset the machine to a default
state, clearing out any changes a previous user might have made.
- Small form factor: I wanted flat screens, and I wanted them
without spending a fortune.
Originally I was planning on using cheap laptops to do this: In
early 2000, one could obtain refurbished P90 laptops with 800x600
displays and PCMCIA ethernet for around $450 each.
I got the above goals (booting read-only, logging in, etc)
working with laptops; but it turned out to
be a a bad idea.
I came to the realization that laptop hardware is just too
flaky. Pretty much everything about a laptop is inferior to a desktop
machine, in terms of performance, reliability, and expense: their only
benefit is that they run off batteries, and that's not a concern in
this application. They're also hellaciously difficult to service: if
something goes wrong, you throw the whole thing away and get a new
So, we decided to spend a bit more money on the kiosks to get
something more reliable: diskless desktop computers for the kiosks,
plus external flatscreens. The benefits here are that: the machine
itself can be serviced; and if the machine gets toasted, I don't have
to buy a new screen too. The screens can be secured such that they
are fairly indestructible, and they also have a warranty. Plus,
commodity hardware is both cheaper and more reliable than laptop
Currently, the hardware we're using for the kiosks is:
KDS Radius S-3F 15" LCD screens (1024x768
resolution) which, in June 2001, we bought for around $580.
- Custom-welded steel enclosures for the monitors.
- Cheap keyboards ($5) and trackballs ($20), screwed down
to the enclosure's table.
MSI 6390 motherboard
with an Athlon 1200 CPU;
- 256MB of PC2100 DDR RAM;
- Enlight HPC-150-101
150W small form factor power supply;
- And (in some cases) enclosures made from $20 worth
plexiglass and misc. connectors.
From late 2000 through 2006, these machines ran as "fat client"
computers: the machines each ran all of their applications locally,
but had no local disks. Everything was mounted via NFS from a remote
file server. Users would auto-login as a "guest" user on the client
machine, which would run X11, a web browser, a basic GNOME desktop,
As much was mounted shared and read-only as possible; and when the
machine rebooted, everything was reset to a default state.
That worked reasonably well for six years, but it was
hellaciously complicated. We wasted a lot of
time fighting with stupid hardware compatibility problems (e.g., the
kernel not liking the onboard NIC, crap like that) and they often ran
out of RAM and crashed, especially if someone tried to run a Java
So, these days, they are "thin clients" instead of "fat clients".
The back-room server machine (which had been merely the file server
for the fat clients) is now a much beefier machine which runs all
of the applications for the kiosks. Each kiosk is, essentially, an X
terminal. All that the kiosks run locally is an X11 server; the
window managers and web browsers are all running on the same remote
host. That machine has a 1GHz processor and 1.2GB RAM, which
(it turns out) is plenty to run six copies of GNOME and Firefox
under the kind of light usage they get in our environment.
Here are the steps I followed in creating this system:
Configure a server machine.
Do a full install of
Also install DHCP, TFTP, and LTSP.
And whatever else tickles your fancy.
Create a passwordless user for each remote kiosk you will be using:
groupadd -g 666 guest
useradd -u 1001 -g guest -c 'Kiosk User' -p '' guest01
useradd -u 1002 -g guest -c 'Kiosk User' -p '' guest02
useradd -u 1003 -g guest -c 'Kiosk User' -p '' guest03
useradd -u 1004 -g guest -c 'Kiosk User' -p '' guest04
useradd -u 1005 -g guest -c 'Kiosk User' -p '' guest05
useradd -u 1006 -g guest -c 'Kiosk User' -p '' guest06
useradd -u 1007 -g guest -c 'Kiosk User' -p '' guest07
useradd -u 1000 -g guest -c 'Kiosk User Template' guest-ro
passwd -l guest-ro
However, to make the kiosk users truly have passwordless logins,
I had to hand-hack /etc/shadow and give each of them the
(encrypted) null password, U6aMy0wojraho -- I have no idea
why that was necessary.
Install and configure LTSP.
Linux Terminal Server Project
via the Package Manager. Then run ltsp-build-client to
actually finish the installation. This will install a bunch of stuff in
/opt/ltsp/i386/ and /tftpboot/.
Make sure the firewall on the server allows NFS (TCP
111, all UDP) and BOOTP and TFTP (TCP 67, 69, 4011 and 1759).
Run the GDM configurator and set GDM to allow remote logins.
At this point, when you boot one of the kiosks, it should
launch X and show you a login prompt. You should be able to
log in as a normal user. If that's not working, repeat until
Apparently later versions of LTSP try to use something called
"LDM" instead of GDM. If that isn't working for you, uninstall
the LDM packages to force GDM to be used instead.
If the X server on the clients isn't coming up right...
good luck. Start by trying to edit the settings in
X_HORZSYNC and X_VERTREFRESH). If that
doesn't work, have fun trying to make sense of the mess that is
Customize the kiosk startup sequence.
You can skip this part.
But, if there are any other applications you want to run on
the thin clients themselves, you can do that by creating a custom
LTSP "screen.d" file. In my environment, I need to run "gpm" on
the clients, and for debugging, I also run "sshd". I created
this dnakiosk file, which is
installed in /opt/ltsp/i386/usr/lib/ltsp/screen.d/.
To use it, edit /var/lib/tftpboot/ltsp/i386/lts.conf
to include SCREEN_01=dnakiosk.
Note that any time you change anything under
/opt/ltsp/i386/ you have to re-run
ltsp-update-image to get the client machines to see
your changes. (This takes forever...)
Here is the lts.conf
that we use. Note that it runs different X servers for different
kiosks (depending on what graphics chipsets they have) and that
it uses gpm.
- Getting sshd working is a little tricker:
cp -p /usr/sbin/sshd /opt/ltsp/i386/sbin/
ssh-keygen -q -t rsa1 -f ssh_host_key -C kiosks -N ''
ssh-keygen -q -t rsa -f ssh_host_rsa_key -C kiosks -N ''
ssh-keygen -q -t dsa -f ssh_host_dsa_key -C kiosks -N ''
(Yeah, this means that all kiosks will use the same host key.
Yeah, that's bad. So sue me.)
Then create /opt/ltsp/i386/etc/shadow
to give the local "root" user on the thin clients a password,
and to add a local "sshd" user.
Make it possible to remotely reboot the kiosks:
Create a file /opt/ltsp/i386/sbin/rebootme
that contains only two lines:
and in /opt/ltsp/i386/etc/passwd, add:
Now you can do "ssh reboot@kiosk07" to reboot it
without a password.
Allow the kiosks to send their log messages back
to the server by adding -r to
Right now, the kiosks are remote X terminals. The next step
is to make them be anonymous terminals. The basic idea
here is that instead of having GDM put up login prompt, we want it
to automatically log in as the user "guest" as soon as it starts
up. Or rather, we want the kiosk03 host to log in as the user
"guest03", and so on.
Furthermore, when a guest user logs in, their home directory
should be re-initialized from a read-only known state (so that
simply typing Ctrl-Alt-Backspace will reset things to a known
state, and get rid of any configuration changes and files that the
previous user of the terminal might have made.)
- Delete all the files in /etc/X11/gdm/Sessions/
except for "Default". Things get confused if a user ever selects a
non-default session-style, so make there be only one available.
The "Default" session is the one that runs ~/.xsession
to launch the user's applications.
- Since GDM will auto-login, avoid confusion by
removing the login box from the GDM greeter screen by using a
custom GDM theme that just leaves
out all the various text-areas and displays our
"loading, please wait" image.
Install this directory in /usr/share/gdm/themes/dnalounge/.
- Configure GDM itself: edit
/etc/X11/gdm/gdm.conf with these options:
Now, here's the tricky part! For GDM to know which user
to auto-login as, we set both the "AutomaticLogin" and
"TimedLogin" fields to /usr/local/sbin/kioskname|.
Note the bar at the end: that means that instead of being
a user name, this is a script to run that prints out
the name of the user to log in as.
That script is a shell
script that looks at $DISPLAY to figure out the
name/number of the kiosk in question, and prints out an
So this means, gdm will launch, and then 5 seconds later,
will run this script and then auto-login as (e.g.) "guest05".
Since this is a public space, people don't log in and log out.
They just walk up to the machine, start using it, and walk away
when they are done. Consequently, lots of applications tend to
be left running, consuming memory and cluttering the screen.
I've written some scripts that kill off "stale" programs.
If the kiosk is in use, nothing happens; but if the screen saver
is active, meaning the kiosk is idle, then we kill off any
unwanted processes. Install
these scripts into
|| The guest user's .xsession file.
It doesn't do much more than invoke gnome-session.
This script re-initializes the contents of the kiosk
directories with the template in /home/kiosk-ro/.
(It must be run as root, in order to set the ownerships
This script kills any processes owned by the various
"guestNN" users that don't match a list of
"allowed" executables. This is not only for security
reasons, as for cleanliness: if we run this script when the
screensaver activates, we can kill off any apps that other
users have left cluttering up the screen.
Set up the guest user's .xsession file:
ln -s /usr/local/sbin/xsession /home/guest-ro/.xsession
And set root's crontab to contain:
0,10,20,30,40,50 * * * * /usr/local/sbin/kiosk-nanny-ltsp
0 7 * * * /usr/local/sbin/kiosk-nanny-ltsp --reset
That will do a "light" reset of the kiosks every 10 minutes
if the screen saver is active; and will do an unconditional "hard"
reset every morning at 7AM.
Other usability tweaks.
After I installed these kiosks in the
club, I spent some time
standing around and looking over people's shoulders as they tried
to use them.
I found that there were five major usability problems.
I believe I have solved four of them...
- Using the machine too early.
People kept trying to start using the machines while they
were still starting X, and thrashing around. They, of course,
found that the machines weren't working very well and seemed
really slow. This was a bad way to introduce them!
I came up with a really simple solution to this: the first
thing my startup scripts do is set the root window image to be
one that has ``Loading, Please Wait'' written on it in
inch high letters. The last thing the startup scripts
do is set the background image to something prettier.
Of course, this problem went away when we upgraded to
newer machines that boot really fast.
- Mouse buttons.
The kiosks are set up with a three-button trackball as a
pointing device. Experience shows that people had no idea
which button to use: I watched people try to select things with
the right button (causing menus to pop up, and stay up,
cluttering the screen.) Then every now and then they'd hit the
left button, and something would work right; but then they'd go
back to using the right button or middle again.
This may be partly because people aren't familiar with
trackballs, and it may be partly because of the position of the
trackball; but the bottom line is, it wasn't working. We
needed all three buttons to do the same thing. Opening up the
trackball and rewiring it would have been a lot of work, so I
found a software solution.
(I decided that, for the applications we're using, it was
ok to discard the middle and right buttons: none of the apps
that we expect to be used require usage of the right
button to work properly, and people can always paste using
Edit/Paste on the menubar.)
Normally, the gpm program is used for making the
mouse work on the text console and things like that, but you
can also use it as a layer that sits between your actual mouse,
and the X server. And you can use it to re-map buttons! But,
not to re-map all buttons to the same button... For that you
need to patch the gpm source (as of gpm-1.20.1.)
--- startup.c.~1~ 2002-12-24 14:57:16.000000000 -0800
+++ startup.c 2004-04-15 23:36:45.000000000 -0700
@@ -60,6 +60,9 @@
Then run gpm like this:
gpm -m /dev/mouse -t ps2 -R msc -B 111
and add this to
XF86Config-4 to tell
X to read mouse events from gpm's socket instead of the
[ ...etc... ]
Option "Protocol" "MouseSystems"
Option "Device" "/dev/gpmdata"
Note that you have to be careful about the mouse protocol:
the -t option to gpm tells you what protocol your
actual mouse speaks, but the -R redirection stuff
seems to only work with the MouseSystems (msc) protocol,
so what the X server sees is MouseSystems data.
Every single person assumed that they had to double-click
on icons to launch programs, and so every single person ended
up launching multiple copies of it. And then that slowed the
machine down, so they assumed their click didn't work, and
clicked again. And so on.
I solved this by writing a program that sits between the
panel icons and the applications: It's called
and what it does is, notice when the program it's trying to
launch is already running, and in that case, simply raise
its window. It also keeps track of programs it has just
launched that haven't had time to map their windows yet.
Use it by editing the command executed by the panel icons
runonce XTerm xterm -fg black -bg white
Where ``XTerm'' is the application name, application class,
or window title of the window that the program maps; and the
rest of the line is the command-line used to launch the
The Gnome panel doesn't have text titles underneath the
icons: it only has tooltips that appear when the mouse hovers
over the icon for a while.
Nobody realizes this.
So what they do is, they click on the icons to see what
they do. Thus launching applications they don't need, and
slowing down the machine while five programs they don't even
really want to use try to start up at once.
I solved this by giving the applications different icons
that include text in them (``IRC'', ``AIM'', etc.) A better
solution, of course, would be for the panel to have an option
to display the tooltip text right in the panel. Then it would
be localized and everything.
Stale and bloated programs.
As described above.