Deploying a Raspberry Pi Chromium Kiosk using Ansible

Posted on 2019-02-05 in sysadmin

Years ago, at a previous job, i was asked to put up a monitoring display showing details from our service desk. I was given a TV and a Raspberry Pi, and told to go at it.

I hacked around a bit, eventually had something that sort of worked, noted down how i'd done it, and moved on. When a friend asked me for more details i passed on my notes, and after a couple of years of poking around between a few of us, we have a pretty good idea how to implement this. Tas has documented it in great detail on her blog here and here.

So, at work i've set up a new monitoring system for our servers and services.
And i've found a nice dashboard that hooks into it and gives a ten-foot view.
And i have a spare raspberry pi and projector. Hmm.

I decided this time though, i'd do it properly. I've faffed about running through those instructions too many times in the past few years, and i'm now pretty handy with ansible for automation. Seems logical to implement it using that right?

So to start with, we have a raspberry pi running raspbian lite. We don't need all the full everything installed on it, just the few bits we want to display a browser full screen. We need to specify the user we plan on running as, and the url to display. I do this in host_vars/kiosk.example.com

1
2
3
kiosk:
  url: http://example.com/monitoring-dashboard
  user: pi

Then we have a role set up to actually do the thing. This is the playbook itself, at roles/chromium-kiosk/tasks/main.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
- name: Install X etc
  apt:
    name: "{{item}}"
    state: present
    install_recommends: no
  with_items:
    - xserver-xorg
    - xinit
    - xserver-xorg-video-fbdev
    - lightdm
    - chromium-browser
    - unclutter

- name: Enable auto-login to x for user
  lineinfile:
    regexp: "{{item.r}}"
    line: "{{item.l}}"
    path: /etc/lightdm/lightdm.conf
  with_items:
    - {'r': "^#?autologin-user=", 'l':"autologin-user={{kiosk.user}}"}
    - {'r': "^#?autologin-user-timeout=", 'l':"autologin-user-timeout=0"}
  notify: restart lightdm

- name: Set up xsession for user
  template:
    src: xsession.j2
    dest: "/home/{{kiosk.user}}/.xsession"
  notify: restart lightdm

- name: Make sure user has passwordless sudo for running fbset command
  copy:
    content: "{{kiosk.user}} ALL=(ALL:ALL) NOPASSWD: /bin/fbset\n"
    dest: "/etc/sudoers.d/kiosk-user"
    owner: root
    group: root
    mode: 0444
  notify: restart lightdm

- stat:
    path: /boot/config.txt
  register: pi_config

- name: disable overscan if we're on a pi
  lineinfile:
    regexp: "{{item.r}}"
    line: "{{item.l}}"
    path: /etc/lightdm/lightdm.conf
  with_items:
    - {'r': "^#?disable_overscan=", 'l':"disable_overscan=1"}
  notify: restart lightdm
  when: pi_config.stat.exists

We then have a handler to restart lightdm when we change any settings. This will cause the kiosk display to restart. It sits at roles/chromium-kiosk/handlers/main.yml

1
2
3
4
- name: restart lightdm
  service:
    name: lightdm
    state: restarted

And finally, the template for the xsession, this has a few modifications, it will automatically detect your screen size, and checks that it can see a http 200 code from the specified URL before starting the browser. It lives at roles/chromium-kiosk/templates/xsession.j2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Set this to your URL - it must return a 200 OK when called, not a redirect.
export URL={{kiosk.url}}

# Dont want screensavers or screen blanking
xset s off &
xset -dpms &
xset s noblank &

# Hide the mouse cursor
unclutter -idle 10 -noevents &

# Sit and wait until you can hit the URL you'll be showing in the kiosk
while ! curl -s -o /dev/null -w "%{http_code}" ${URL} | grep -q "200"; do
  sleep 1
done

# get screen resolution
WIDTH=`sudo fbset -s | grep "geometry" | cut -d " " -f6`
HEIGHT=`sudo fbset -s | grep "geometry" | cut -d " " -f7`

# Open chrome in incognito mode + kiosk mode
/usr/bin/chromium-browser --window-size=${WIDTH},${HEIGHT} --window-position=0,0 --hide-scrollbars --incognito --kiosk ${URL}