Viperfang [2E0VFN]

Digital Playground

Arch Linux as a Kiosk


So, what am I after with this? Thats simple! A secure computer running minimal software to allow a customer to browse the internet without leaving any files behind and without any customisations being saved. It would be nice to have a wallpaper and a slideshow screensaver, but no required. The browser must start with the system and go to a predefined web page. There must be no access to the underlying system.


I have to assume you have your OS installed, getting Arch onto a disk and booting is beyond what needs describing here as it would just be a replication of that arch wiki. Just a base install is what this guide builds off, notalot more!


If you would like the script thatthis page is based off, its here


All we want is to grab an IP from the DHCP server over ethernet, no other config is needed, so lets just enable and start a dhcp client:

systemctl enable dhcpcd
systemctl start dhcpcd

Install additional packages

Rat poison for the window manager, xorg and xorg-init for the display manager, chromium for the web browser, and a shed load of fonts to make it all look how it should! Oh yeah, and alsa-utils for unmuting audio :P

pacman -S xorg ratpoison xorg-xinit chromium alsa-utils xscreensaver $(pacman -Ssq ttf-)

Set up the keyboard and locale

Thank you again systemd!

localectl set-keymap uk
localectl set-locale LANG=en_GB.utf8

Create Guest User

You know this one! useradd -m guest

Automatic login of Guest

Systemd sorts this for us, aswell as running our cleanup script first! systemctl edit getty@tty1

ExecStartPre=/bin/bash /opt/kiosk/
ExecStart=-/usr/bin/agetty --autologin guest --noclear %I $TERM

Cleanup guest directory

How we guarantee its in a known state? Wipe it, start again... elegant in its simplicity! /opt/kiosk/ Rememeber to chmod o+x after creating it! This is run as root, so patch the sound levels too...

rm -rf /home/guest
cp -R /opt/kiosk/skel /home/guest
chown -R guest:guest /home/guest
chmod 755 /home/guest
amixer sset Master unmute
amixer sset Master 100%

Automatically start X

Pop this in /opt/kiosk/skel/.bash_profile, just chainload X...

cd /home/guest
[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec startx

Note how we give away the two most useful config files, after first logon they wont be ours...

Start X applications

This is what xinitrc is for! /etc/X11/xinit/xinitrc



# merge in defaults and keymaps

if [ -f $sysresources ]; then
    xrdb -merge $sysresources

if [ -f $sysmodmap ]; then
    xmodmap $sysmodmap

if [ -f "$userresources" ]; then
    xrdb -merge "$userresources"

if [ -f "$usermodmap" ]; then
    xmodmap "$usermodmap"

# start some nice programs
ratpoison &
xscreensaver &
while true; do
  chromium --bswi --start-maximized

Lock down Chromium

Lock down chrome using enterprise settings, drop in this file nano /etc/chromium/policies/managed/test_policy.json

  "HomepageLocation": "",
  "DriveDisabled": true,
  "ExtensionInstallBlacklist": ["*"],
  "HomepageIsNewTabPage": false,
  "SupervisedUsersEnabled": false,
  "PasswordManagerEnabled": false,
  "RestoreOnStartup": 5,
  "AllowFileSelectionDialogs": false,
  "AlternateErrorPagesEnabled": false,
  "AutoFillEnabled": false,
  "BookmarkBarEnabled": false,
  "BrowserAddPersonEnabled": false,
  "BrowserGuestModeEnabled": false,
  "DefaultBrowserSettingEnabled": true,
  "DeveloperToolsDisabled": true,
  "DisableSafeBrowsingProceedAnyway": true,
  "DisableScreenshots": true,
  "EditBookmarksEnabled": false,
  "ForceGoogleSafeSearch": true,
  "FullscreenAllowed": false,
  "HideWebStoreIcon": true,
  "ImportAutofillFormData": false,
  "ImportBookmarks": false,
  "ImportHistory": false,
  "ImportHomepage": false,
  "ImportSavedPasswords": false,
  "ImportSearchEngine": false,
  "IncognitoModeAvailability": 2,
  "SafeBrowsingEnabled": true,
  "SavingBrowserHistoryDisabled": true,
  "ShowHomeButton": true,
  "SyncDisabled": true,
  "DownloadDirectory": "/dev/null",
  "URLBlacklist": ["*.xxx","file://*"],

Make ratpoison all but uncontrollable

ratpoison is very good at allowing you to execute things... lets not do that, edit /usr/etc/ratpoisonrc

#go to ~

#Lets not give away any secrets
startup_message off

# You'll never hit this by mistake.... I hope
escape S-C-s-Return

# lets drop all the commands we can
unbind 0
unbind 1
unbind 2
unbind 3
unbind 4
unbind 5
unbind 6
unbind 7
unbind 8
unbind 9
unbind -
unbind A
unbind C-A
unbind K
unbind C-K
unbind Return
unbind C-Return
unbind a
unbind C-a
unbind b
unbind C-b
unbind C-c
unbind exclam
unbind C-exclam
unbind i
unbind C-i
unbind k
unbind C-k
unbind l
unbind C-l
unbind m
unbind C-m
unbind c
unbind C-n
unbind p
unbind C-p
unbind apostrophe
unbind C-apostrophe
unbind space
unbind C-space
unbind v
unbind C-v
unbind V
unbind C-V
unbind w
unbind C-w
unbind s
unbind C-s
unbind S
unbind C-S
unbind Tab
unbind M-Tab
unbind C-Left
unbind C-Right
unbind C-Up
unbind C-Down
unbind Left
unbind Right
unbind Up
unbind Down
unbind Q
unbind R
unbind f
unbind C-f
unbind f
unbind C-r
unbind question
unbind C-underscore
unbind u
unbind C-u
unbind U
unbind x
unbind C-x
unbind N
unbind P
unbind C-g
unbind t
unbind C-t
unbind minus
unbind n
unbind F
unbind r
unbind colon

Screensaver slideshow!

Might as well make it look cool, lets have a basic slideshow with some basic slogans on them. I put all the images in the home of admin, as I can easily ftp to it over ssh, and they are readonly to xscreensaver. /opt/kiosk/skel/.xscreensaver

# XScreenSaver Preferences File
# Written by xscreensaver-demo 5.34 for guest on Tue Feb 23 18:52:55 2016.

timeout:        0:02:00
cycle:          0:10:00
lock:           False
lockTimeout:    0:00:00
passwdTimeout:  0:00:30
visualID:       default
installColormap:    True
verbose:        False
timestamp:      True
splash:         False
splashDuration: 0:00:05
demoCommand:    xscreensaver-demo
prefsCommand:   xscreensaver-demo -prefs
nice:           10
memoryLimit:    0
fade:           True
unfade:         False
fadeSeconds:    0:00:03
fadeTicks:      20
captureStderr:  True
font:           *-medium-r-*-140-*-m-*
dpmsEnabled:    False
dpmsQuickOff:   False
dpmsStandby:    2:00:00
dpmsSuspend:    2:00:00
dpmsOff:        4:00:00
grabDesktopImages:  False
grabVideoFrames:    False
chooseRandomImages: True
imageDirectory: /opt/kiosk/xsaver

mode:           one
selected:       1

textMode:       file
textLiteral:    XScreenSaver
textProgram:    none
textURL:        none

programs:                                                                     \
- Default:                      glslideshow -root -delay 0 -zoom 100 -pan     \
                                  1 -fade 0 -no-letterbox                   \n\

pointerPollTime:    0:00:05
pointerHysteresis:  10
initialDelay:   0:00:00
procInterrupts: True
xinputExtensionDev: False
overlayStderr:  True
authWarningSlack:   20

Periodic reboot

Once again, systemd can do this! One service to define when to reboot, one service to execute it. /etc/systemd/system/reboot.service

ExecStart=/usr/bin/reboot now
ExecStop=/usr/bin/reboot now


Description=Daily Reboot



And start it up!

systemctl daemon-reload
systemctl enable reboot.timer
systemctl start reboot.timer

All being well, it should be listed in systemctl list-timers --all

Protecting guest

Disable password changing for the forseeable future, amost 274 years:

passwd -n 9999 guest

Further protection

Remember you need to protect grub and your bios, booting from an external stick makes this all pointless!