AWK is a web kiosk based on Alpine Linux (3.23)
with this repo, you can (quickly and easily) set up a web kiosk based on Alpine Linux and Chromium web browser : « a web kiosk is a self-service computer terminal accessible to the public that allows users to view informations or perform actions via web interfaces in a limited and controlled manner »
changes may be necessary (keyboard
fr, disksda, …)
be sure to select correct disk if there are multiple available
installation must be performed under EFI/UEFI mode
Secure Boot must be disabled on EFI/UEFI platform
- boot Alpine Linux ISO image on PC containing media storage for the future web kiosk
- login as
rootwithout a password (empty password) - start installation with
KERNELOPTS="quiet mitigations=off" \
DISKLABEL=gpt \
BOOTLOADER=grub \
BOOTFS=vfat \
ROOTFS=btrfs \
setup-alpine- and then set
- keymap
fr - keyboard layout
fr - hostname
AWK - initialize interface
eth0 - ip address
dhcp - root password
********** - timezone
Europe - sub timezone
Paris - proxy
none - ntp client
busybox - apk mirror
c(community)1(mirros.ircam.fr) - user
browser - full name
Chromium - password
chromium - retype password
chromium - ssh key or URL
none - ssh server
openssh - allow root ssh
prohibit-password - ssh key or URL
none - disk
sda - type
sys - erase
y
- keymap
- reboot
reboot
changes may be necessary (SSH public key, disk
sda, …)
be sure to select correct disk if there are multiple available
- boot AWK from media storage selected during installation
- login as
rootwith defined password - update and upgrade system
apk update && apk upgrade
💡 entire configuration process described below can be automated using setup-AWK script 🚀
- change domain name resolution
simple AD blocker can be easily added
apk add dnsmasq
rc-update add dnsmasq
cat > /etc/dnsmasq.conf << 'xxxxxxxx'
resolv-file=/etc/resolv.dnsmasq
domain-needed
bogus-priv
interface=lo
no-dhcp-interface=lo
listen-address=127.0.0.1,::1
bind-interfaces
cache-size=2048
xxxxxxxx
chattr -i /etc/resolv.conf
cat > /etc/resolv.conf << 'xxxxxxxx'
nameserver 127.0.0.1
nameserver ::1
xxxxxxxx
chattr +i /etc/resolv.conf
rc-service dnsmasq start
echo 'RESOLV_CONF="/etc/resolv.dnsmasq"' > /etc/udhcpc/udhcpc.conf
rc-service networking restart- modify EFI System Partition (ESP)
apk add sgdisk mtools dosfstools
mkdir -p /boot/efi
if [ -b /dev/sda4 ]; then
boot=/dev/sda2
sgdisk /dev/sda \
--typecode=1:ef02 --change-name=1:GRUB \
--typecode=2:0700 --change-name=2:AWK \
--typecode=3:8200 --change-name=3:SWAP \
--typecode=4:8300 --change-name=4:ROOT
else
boot=/dev/sda1
sgdisk /dev/sda \
--typecode=1:0700 --change-name=1:AWK \
--typecode=2:8200 --change-name=2:SWAP \
--typecode=3:8300 --change-name=3:ROOT
fi
echo "drive x: file=\"$boot\"" > /etc/mtools.conf
mattrib +h +s x:/efi 2> /dev/null
dosfslabel "$boot" AWK > /dev/null 2>&1- make few minor changes
: | tee /etc/issue > /etc/motd
sed -i 's/^wheel:x:10:root,browser/wheel:x:10:root/' /etc/group
sed -i -E \
-e '/^\/dev\/(cdrom|usb)/d' \
-e 's/iocharset=utf8/iocharset=iso8859-1,utf8/' \
/etc/fstab
cat > /etc/network/interfaces << 'xxxxxxxxxx'
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
udhcpc_opts -t 1 -b -S
xxxxxxxxxx- add widest hardware support (AWK on a USB device)
apk add linux-firmware- modify GRUB loader (quiet boot)
chmod -x /etc/grub.d/*
chmod +x /etc/grub.d/00_header
chmod +x /etc/grub.d/10_linux
if ! grep -q '^GRUB_TIMEOUT_STYLE=hidden' /etc/default/grub; then
cat >> /etc/default/grub << 'xxxxxxxx'
GRUB_TIMEOUT_STYLE=hidden
GRUB_DISABLE_OS_PROBER=true
xxxxxxxx
fi
rc-update add local default
cat > /etc/local.d/grub.echo.stop << 'xxxxxxxx'
#!/bin/sh
if grep -q 'Loading Linux lts' /boot/grub/grub.cfg; then
sed -i /boot/grub/grub.cfg \
-e "s/'Loading Linux lts/; echo ' Loading AWK/" \
-e '/Loading initial ramdisk/d'
fi
xxxxxxxx
chmod +x /etc/local.d/grub.echo.stop- make dynamic hostname (MAC based / multiple kiosks on same LAN)
cat > /etc/init.d/machostname << 'xxxxxxxx'
#!/sbin/openrc-run
depend()
{
after hostname
}
start()
{
host="AWK-$( tr -d ':' < /sys/class/net/eth0/address )"
echo "$host" > /etc/hostname
hostname "$host"
cat > /etc/hosts << oooooooo
127.0.0.1 $host.localdomain $host localhost.localdomain localhost
::1 localhost localhost.localdomain
oooooooo
}
xxxxxxxx
chmod +x /etc/init.d/machostname
rc-update add machostname boot
rc-service machostname start- configure remote access (remote administration)
generate an SSH key pair from administration workstation
ssh-keygen -t ed25519 -C comment -f ./AWK.key
use content of public keycat ./AWK.key.pubbelow or copy public key to~/.ssh/authorized_keysat AWK
mkdir -p ~/.ssh/
echo "ssh-ed25519 … … … … … comment" > ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys- install graphics server, applications and extensions
setup-xorg-base
apk add setxkbmap
apk add font-dejavu font-inconsolata font-liberation font-linux-libertine font-noto-emoji ttf-freefont
apk add jwm
apk add chromium chromium-lang
cat > /etc/X11/xorg.conf << 'xxxxxxxx'
Section "ServerFlags"
Option "DontVTSwitch" "true"
Option "DontZap" "true"
EndSection
Section "InputClass"
Identifier "touchpad"
MatchDriver "libinput"
MatchIsTouchpad "on"
Option "Tapping" "on"
Option "NaturalScrolling" "on"
EndSection
xxxxxxxx- setup default web page
cat > /etc/local.d/default.web.page.start << 'xxxxxxxx'
#!/bin/sh
mkdir -p "${root:=/boot/efi/www}"
ln -sf "$root" /
if [ ! -f "${index:=$root/AWK.html}" ]; then
cat > "$index" << 'oooooooo'
<html style="background-color:#0E5980;color:#00ccff;font-family:sans;font-style:italic;font-weight:bold">
<title>AWK</title>
<div style="font-size:4em;text-align:center"><br/><br/>
<svg width="256" height="132" xmlns="http://www.w3.org/2000/svg">
<path style="fill:#0e5980;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-linecap:round;stroke-linejoin:round;paint-order:fill markers stroke" d="M16 0h224c8.864 0 16 7.136 16 16v100c0 8.864-7.136 16-16 16H16c-8.864 0-16-7.136-16-16V16C0 7.136 7.136 0 16 0Z"/>
<g stroke="#000" stroke-linejoin="round" stroke-width="16.83"><path d="m9.662 93.904 85.171-83.137 85.171 83.137M248.142 93.904 171.487 19.08l-17.034 16.628M79.282 68.963v24.941" style="fill:none;stroke:#fff;stroke-opacity:1" transform="translate(-.902 -1.227)"/></g>
<path stroke="#000" stroke-linejoin="round" d="m62.975 115.321-11.9 11.9" stroke-width="13.804" style="fill:none;stroke:#1b93c0;stroke-opacity:1" transform="translate(0 -1.227)"/>
<path style="fill:none;stroke:#1b93c0;stroke-width:17.0001;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="M22.684 114.909h210.632Z" transform="translate(0 -1.227)"/>
<text xml:space="preserve" style="font-size:85.3333px;line-height:1.25;font-family:sans-serif;fill:#0cf" x="17.313" y="103.104"><tspan x="17.313" y="103.104" style="font-style:oblique;font-variant:normal;font-weight:700;font-stretch:normal;font-size:85.3333px;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans Bold Oblique';fill:#0cf;fill-opacity:1">AWK</tspan></text>
</svg>
</br>Alpine Web Kiosk
</div>
</html>
oooooooo
fi
xxxxxxxx
chmod +x /etc/local.d/default.web.page.start
rc-service local start- configure system initialization (minimum, silent, and auto-login for
browseruser)
no console access with this
/etc/inittabconfiguration
uncomment#tty2::respawn:/sbin/getty 38400 tty2to retain console access
and/or uncomment#ttyS0::respawn:/sbin/getty -L 0 ttyS0 vt100for serial console access
and/or access AWK via secure shell (prefered)
sleep may be added (uncomment) to make it easier to read assigned network address (see also conky)
cat > /etc/inittab << 'xxxxxxxx'
::sysinit:clear
::sysinit:printf '\n\n Starting AWK ...\n\n'
::sysinit:/sbin/openrc sysinit -q > /dev/null
::sysinit:/sbin/openrc boot -q > /dev/null
#::sysinit:sleep 3s
::wait:/sbin/openrc default -q > /dev/null
tty1::respawn:/bin/login -f browser
#tty2::respawn:/sbin/getty 38400 tty2
#ttyS0::respawn:/sbin/getty -L 0 ttyS0 vt100
::ctrlaltdel:clear
::ctrlaltdel:/sbin/reboot > /dev/null 2>&1
::shutdown:clear
::shutdown:/sbin/openrc shutdown -q > /dev/null 2>&1
xxxxxxxx- configure login for
browseruser (graphics server automatic startup at login)
~/.chromium.tgzis a pre-configuration for Chromium (view file in repository)
cat > /home/browser/.profile << 'xxxxxxxx'
clear
printf '\n\n Starting browser ...\n'
export LANG=fr
export LC_COLLATE=C
rm -rf \
~/.Xauthority* \
~/.serverauth.* \
~/.cache/chromium \
~/.config/chromium \
> /dev/null 2>&1
tar -C ~ -xf ~/.chromium.tgz > /dev/null 2>&1
exec startx > /dev/null 2>&1
xxxxxxxx- configure window manager's startup
cat > /home/browser/.xinitrc << 'xxxxxxxx'
setxkbmap fr
xset -dpms
xset s off
xset s noblank
exec jwm
xxxxxxxx- set up web browser auto-start
cat > /home/browser/.jwmrc << 'xxxxxxxx'
<?xml version="1.0" encoding="UTF-8"?>
<JWM>
<StartupCommand>
clear > /dev/tty1
if [ -f "${urls:=/boot/efi/urls.txt}" ]; then
urls=$( grep -E -o '^(file|http(s)?)://[^ ]+' "$urls" )
else
urls=file:///www/AWK.html
fi
chromium \
--start-maximized \
--no-first-run \
--autoplay-policy=no-user-gesture-required \
--disable-infobars \
--disable-session-crashed-bubble \
--disable-restore-session-state \
--disable-component-update \
--check-for-update-interval=315360000 \
--disable-pinch \
--disable-features=TranslateUI \
--disable-extensions \
--disable-background-networking \
--disable-sync \
--disable-default-apps \
--process-per-site \
--disk-cache-size=0 \
--password-store=basic \
--noerrdialogs \
$urls
rm -rf \
~/.serverauth.* \
~/.cache/chromium \
~/.config/chromium
jwm -exit
</StartupCommand>
</JWM>
xxxxxxxx- disable
file://scheme (except for default web page) et fix download directory
mkdir -p /etc/chromium/policies/managed/
cat > /etc/chromium/policies/managed/AWK.json << 'xxxxxxxx'
{
"URLAllowlist": ["file:///www/"],
"URLBlocklist": ["file://"],
"DownloadRestrictions": 3,
"DownloadDirectory": "/tmp/"
}
xxxxxxxx- install provided pre-configuration (optional)
this file is used in
/home/browser/.profile
wget -O /home/browser/.chromium.tgz \
https://github.com/patatetom/AWK/raw/refs/heads/main/chromium.config.tgz
# check tgz file
# tar tvzf /home/browser/.chromium.tgz
/boot/efi/urls.txton AWK
urls.txt file, located in root directory of first partition, tells browser which web page(s) to open and can be easily installed and configured
# default updated web page for kiosk user guide
file:///www/AWK.html
# DuckDuckGo
https://duckduckgo.com/
# AWK ;-)
https://github.com/patatetom/AWK/
/boot/efi/www/AWK.htmlor/www/AWK.html(symlink) on AWK
AWK.html file, stored in /www/ folder located in root of first partition, is default web page opened by browser and can be easily updated and expanded
- AWK is « French-oriented »
- ESP partition is redesigned when installing on removable USB media (Windows with portable kiosk)
- BTRFS file system is preferred over EXT4 when installing on removable USB media (portable kiosk)
- audio and printing functions are not built-in but can be easily added
- WiFi connectivity is not built-in but can be easily added
- press
ESCat boot to access GRUB bootloader and pressEto edit/add/change kernel parameters - transferring AWK from one media storage to another usually requires fixing GPT (some EFI/UEFI platforms refuse to boot if backup GPT is not valid)
