How-To: Ubuntu Kiosk
This article first appeared in Full Circle Magazine, issue #93.
If you work in a place open to the public, for example a library or a hospital, sometimes it could be useful to provide a computer to the visitors. Such a computer, even if equipped with a mouse and a keyboard, must be configured in a way that people should not be able to use all the system functions, but only a limited set of them. For instance, people could use the computer to access the Internet, or only an internal website providing information related to your company or your activity. And you must configure the system in order to prevent shell access, and inhibit the launch of all the other programs you don't wish to offer to the visitors.
Such a computer is a kiosk. (
http://en.wikipedia.org/wiki/Interactive_kiosk).
You can eventually configure a PC attached to a large TV, without keyboard and mouse, in order to show information slides or videos. To achieve this last goal, you can take a look to Xibo instead, which is a digital signage content management system (
http://xibo.org.uk/).
Installing
Let's start with installing Ubuntu server 14.04 LTS. Why Ubuntu server? Well, because, in your kiosk, you don't need a lot of software. Also note the use of the –no-install-recommends parameter used with apt-get.
Please keep in mind that after the configuration of the kiosk environment, it is supposed that you will access the computer from SSH, and not from the terminal.
So, let's install Ubuntu, enabling automatic security updates and installing Openssh server.
After the first reboot, log in as the (administrator) user you have created during the installation and then upgrade the system:
sudo apt update
sudo apt upgrade
And install these packages:
sudo apt install --no-install-recommends xorg openbox firefox xscreensaver plymouth-theme-sabily cups
Install CUPS if you plan to allow printing to your visitors.
Create a user, the kiosk user.
sudo useradd -m kiosk
sudo mkdir /opt/kiosk
Set up the environment
In this configuration, you will not launch a desktop manager, but you will invoke X11 and start only the Firefox executable.
sudo vi /opt/kiosk/kiosk.sh
#!/bin/bash
home_tar="/opt/kiosk/kiosk_home.tar"
rewritehome() {
echo $home_tar
if [ -f $home_tar ]
then
rm -rf $HOME/*
tar xvf $home_tar -C /
fi
}
xset -dpms
xset s
off
openbox-session &
rewritehome
xscreensaver -nosplash &
while true;
do
rewritehome
/usr/bin/firefox
done
The script shown above will be invoked by upstart when the system boots up. It essentially replaces the kiosk user home directory before starting Firefox. And the Firefox executable is placed inside a loop, in order to relaunch it whenever it is closed.
sudo chmod +x /opt/kiosk/kiosk.sh
Now you need to create an upstart script:
sudo vi /etc/init/kiosk.conf
start on (filesystem and stopped udevtrigger)
stop on runlevel [06]
console output
emits starting-x
respawn
exec sudo -u kiosk startx /etc/X11/Xsession /opt/kiosk/kiosk.sh
Since X needs root privileges to start, you need to issue this command and select “Anybody”.
sudo dpkg-reconfigure x11-common
At this point we are nearly finished. You need to reboot the machine.
sudo reboot
And Firefox should start automatically.
Make the desired changes now, like adding CA certificates, security devices, adding some kind of extensions, etc.
Finally you need to install the srkiosk extension
https://addons.mozilla.org/en-US/firefox/addon/srkiosk/
Please carefully read the documents (
http://blogoless.blogspot.it/2012/07/firefox-srkiosk-add-on-full-screen.html), in order to understand this handcrafted item and better suit it to your needs, like changing the home page, or showing the address bar.
Close Firefox. At this point Firefox will restart in a locked-down kiosk mode.
To continue the configuration, you have to remotely log in via SSH.
Last steps.
The use of the screensaver can be useful – not only to have a nice effect on the screen after an amount of time. It is useful to “reset” the session after a period of inactivity. For instance, it is nice to go to the home page, instead of leaving the kiosk in the last visited page by the last user. So you need to configure the screensaver only if you need to reset your kiosk periodically.
Place the xscreensaver configuration file in the kiosk user home directory. The timeout option is the one you need to change in order to suit your needs (in this example the kiosk will be reloaded every quarter of an hour).
sudo vi /home/kiosk/.xscreensaver
timeout: 0:15:00
lock: False
verbose: False
splash: False
captureStderr: True
dpmsEnabled: False
dpmsQuickOff: False
mode: one
selected: 0
programs: resetkiosk.sh -root
\n\
Next, you need the script that xscreensaver will invoke after the period of inactivity (Listing 4). As said, xscreensaver, instead of launching a real screen saver, will actually run this script.
sudo vi /usr/lib/xscreensaver/resetkiosk.sh
#!/bin/bash
PID=`ps -u $UID -f |grep firefox |grep -v grep | awk '{ print $3 }'`
kill $PID
Snapshot Time
Finally, you need to take a snapshot of the kiosk user home directory. Such snapshot will overwrite the home directory every time the machine reboots, or when the kiosk session is reset, or when Firefox is closed.
So, remember that every time you make changes to the kiosk user home directory, you will need to make a tar of that directory, and place it in the appropriate place: take a look at the kiosk.sh script (previous page, top right).
rm -rf /home/kiosk/.cache/
tar cpvf /opt/kiosk/kiosk_home.tar /home/kiosk/
Configuring GRUB and disabling ttys
Another useful task to accomplish is related to some hardening of the system. For instance, you can prevent naughty users from booting the system into single-user mode, or from switching between virtual consoles (the terminals you can use by pressing functions keys like CTRL+ALT+F1).
Let's start with GRUB. First of all, it needs to be as quiet (less verbose) as possible, just for aesthetic purposes (Listing 5).
sudo vi /etc/default/grub
...
GRUB_TIMEOUT=0
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash vga=current loglevel=0"
...
Then, you can set a password in order to disallow users to boot Linux into single-user mode. Use the command grub-mkpasswd-pbkdf2 to create an encrypted password, then edit some files.
Put the following lines at the end of
/etc/grub.d/00_header
cat << EOF
set superusers="root"
password_pbkdf2 root <the_sting_obtained_from_the_grub-mkpasswd-pbkdf2_command>
EOF
At this point, a user and a password will be requested for each GRUB menu entry, even for booting Linux in the normal way; that is what we don't want. So add the –unrestricted parameter (shown below in black) in each menuentry line of the configuration files. For instance in
/etc/grub.d/10_linux
...
echo "menuentry '$(echo "$title" | grub_quote)'
--unrestricted ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s /^/$submenu_indentation/"
else
echo "menuentry '$(echo "$os" | grub_quote)'
--unrestricted ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu _indentation/"
...
In this way, a user and a password will be asked only if the user tries to edit the GRUB menu entries, using the 'e' key.
Now you must issue the sudo update-grub command to make the changes effective.
At the end, you can disable virtual terminal consoles by deleting the tty files under the /etc/init directory:
sudo rm /etc/init/tty*
Further works and conclusion
In order to harden the machine, you should set up a password in the BIOS, and prevent boot from CD/DVD or USB ports. And about USB, you should prevent the use of such ports at least by making the PC inaccessible from the users.
Other things to do? Configure a custom theme for the boot screen. Look at ways to disable possible keyboard shortcuts.
Instead of running Firefox, you might wish to run a video player or a pictures slide-show: you can give it a try by putting some other command in the while loop.
This paper is based on a post found on
https://thepcspy.com/read/building-a-kiosk-computer-ubuntu-1404-chrome/
Maybe a kiosk solution could be better achieved, but as far as I know, I have not found any better alternatives. This solution works for my needs: maybe it could be useful to you or it could be a starting point for a better implementation.