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 history.
The rest of this document describes how they used to work.
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
So, I had the following goals:
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 one.
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 hardware.
Currently, the hardware we're using for the kiosks is:
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, etc.
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 applet.
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:
Do a standard "Workstation" install of Red Hat 9. Also install NFS, DHCP, and TFTP.
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
Make sure the LTSP installer edited /etc/exports correctly.
Make sure the firewall on the server allows NFS (TCP 111, all UDP) and BOOTP and TFTP (TCP 67, 69, 4011 and 1759).
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 done.
If you need to tweak the X server configuration, it's in
/opt/
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/
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.
cp -p /usr/local/sbin/gpm /opt/ltsp-4.2/i386/sbin/
cp -p /usr/sbin/sshd /home/local/ltsp-4.2/i386/sbin/ mkdir /home/local/ltsp-4.2/i386/etc/ssh/ ssh-keygen -q -t rsa1 -f etc/ssh/ssh_host_key -C 'kiosks' -N '' ssh-keygen -q -t rsa -f etc/ssh/ssh_host_rsa_key -C 'kiosks' -N '' ssh-keygen -q -t dsa -f etc/ssh/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/
Create a file /opt/
#!/bin/sh exec /sbin/rebootand in /opt/ltsp-4.2/i386/etc/passwd, add:
reboot::0:0:root:/root:/sbin/rebootmeNow you can do "ssh reboot@kiosk07" to reboot it without a password.
ca::ctrlaltdel:/sbin/rebootto /usr/local/ltsp-4.2/i386/etc/inittab.base.
cd /home/local/ltsp-4.2/i386/etc ln -sf ../usr/share/zoneinfo/US/Pacific localtime cp -p /usr/sbin/hwclock /home/local/ltsp-4.2/i386/usr/sbin
and then for each kiosk:
ssh root@kioskNN date `date +%m%d%H%M.%S` ssh root@kioskNN hwclock --noadjfile --utc --systohc
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.)
cp -a /home/guest01 /home/guest/guest-ro chown -R guest-ro:guest /home/guest/guest-ro
AutomaticLoginEnable=true AutomaticLogin=/usr/local/sbin/kioskname| TimedLoginEnable=true TimedLogin=/usr/local/sbin/kioskname| TimedLoginDelay=5 RemoteGreeter=/usr/bin/gdmgreeter AllowRoot=false AllowRemoteRoot=false AllowRemoteAutoLogin=true Enable=true SystemMenu=false BackgroundType=1 BackgroundImage=/usr/local/etc/images/loading.gif BackgroundRemoteOnlyColor=false GraphicalTheme=dnalounge
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 appropriate user.
So this means, gdm will launch, and then 5 seconds later, will run this script and then auto-login as (e.g.) "guest05".
I was never able to get TimedLogin to run a script with the version of GDM (2.6) that shipped with Fedora Core 4. Nor was I able to get GDM 2.4.1 to build on FC4.
That is why I'm still running RH9 on the kiosks instead of something newer!
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 /usr/local/sbin:
| xsession | The guest user's .xsession file. It doesn't do much more than invoke gnome-session. |
| kiosk-home-reset-ltsp | 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 properly.) |
| kiosk-nanny-ltsp | 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:
rm /home/guest-ro/.xsession 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.
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...
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.
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 @@
{"231","02461357"},
{"312","04152637"},
{"321","04261537"},
+ {"111","04444444"},
+ {"222","02222222"},
+ {"333","01111111"},
{NULL,NULL}
};
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 real mouse:
Section "InputDevice"
[ ...etc... ]
Option "Protocol" "MouseSystems"
Option "Device" "/dev/gpmdata"
EndSection
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 runonce.c, 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 like so:
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 program.
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.
On two occasions, back in Aug 2008 and Jul 2009, I made an attempt to upgrade the kiosks to a more modern Linux, specifically from a 2003-vintage Red Hat 9 to a 2008-vintage Ubuntu 7.10. I almost got them to work, but they were too flaky to use. They crashed all the time (I suppose we can blame the video drivers for this) and it was a very inconvenient kind of crash. It was not the kind of crash where the machine reboots. It was the kind of crash where someone has to physically press the reset button. So that was pretty much a non-starter. But if you like, you can still read log of my Ubuntu installation adventures.