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 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.
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 full install of Ubuntu 7.10. 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.
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 done.
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 /var/lib/tftpboot/ltsp/i386/lts.conf (e.g., X_HORZSYNC and X_VERTREFRESH). If that doesn't work, have fun trying to make sense of the mess that is /opt/ltsp/i386/usr/lib/ltsp/configure-x.sh.
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.
cp -p /usr/local/sbin/gpm /opt/ltsp/i386/sbin/
cp -p /usr/sbin/sshd /opt/ltsp/i386/sbin/ mkdir /opt/ltsp/i386/var/run/sshd mkdir /opt/ltsp/i386/etc/ssh/ cd /opt/ltsp/i386/etc/ssh/ 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 ''
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.
Create a file /opt/ltsp/i386/sbin/rebootme that contains only two lines:
#!/bin/sh exec /sbin/rebootand in /opt/ltsp/i386/etc/passwd, add:
reboot::0:0:root:/root:/sbin/rebootmeNow you can do "ssh reboot@kiosk07" to reboot it without a password.
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".
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.