This post appeared originally in our sysadvent series and has been moved here following the discontinuation of the sysadvent microsite

For the wallscreens within the operations department, we currently use Raspberry Pies and provision those using Ansible. We found that the USB sockets on a typical LCD TV do not provide enough power for a Raspberry Pi model 3, so we went for the cheaper – although a little less powerful – model 2. Since we have cabled network in place from before, this does not really pose any limitations.

The Inventory

  • Raspberry Pi 2 Model B
  • Chassis For Raspberry Pi 2 Model B
  • SanDisk Ultra MicroSDHC 8GB (SDHC adapter included)
  • HDMI Male/HDMI Male cable, 50cm
  • USB Type A Male/Micro-USB Type B Male cable, 50cm

Cost per unit: NOK 590 (i.e. ~$70/€65)

The Setup

The initial setup uses Raspbian Jessie Lite as the base image. On top of this we install a couple of dependencies to make it run Chromium (the open source/unbranded variant of Google Chrome) in kiosk mode. This gives us a root-file-system of just under 1.5GB and operational RAM in the 500Mb range, well within the limits of the 8GB SD card we got and the 1GB RAM provided by the board.

The Installation

  1. Download the Raspbian SD image and follow Installing Operating System Images to create a (bootable) SD card from the image.

  2. Boot your Raspberry Pi from the created SD card. Make sure it is connected to a network with DHCP enabled.

  3. Make a note of the IP address from your Raspberry Pi (it is displayed on-screen and available through bonjour as raspberrypi.local) and add it to the wallscreens section in your Ansible hosts configuration.

    [wallscreens]
    my_wallscreen ansible_host=<ip of raspberry> ansible_user=pi ansible_become=true
    
  4. Copy your (pre-generated) SSH public-key to the system, to allow for key-based authentication.

  5. Run the provided playbook to configure it for running Chromium in kiosk mode as its main application.

    ansible-playbook wallscreen.yaml
    

The Highlights

The Ansible playbook contains configuration for setting up the raspberry in its entiety. The following snippets shows some of the more interesting parts of the setup.

  • The DHCP client is configured to have it set the host name from DHCP.

     # /etc/dhcpcd.conf`
     env force_hostname=YES
    
  • The profile allows for booting the system without actually starting Chromium by removing ~pi/.autostart:

     [ -f ~/.autostart -a "$(tty)" == "/dev/tty1" ] && {
       XAUTHORITY=/tmp/.xauth startx
     }
    
  • ~pi/.xinitrc turns off any form of screensaving, starts unclutter to hide the mouse-pointer on inactivity and starts chromium in kiosk-mode with its resolution set to support 1080p:

     xset -dpms
     xset s off
     xset s noblank
     unclutter -idle 1 -root &
     exec chromium-browser --window-size=1920,1080 --no-first-run --noerrdialogs --kiosk --incognito https://wallscreen.i.bitbit.net/$(hostname --short)
    
  • We serve the content of a wallscreen from an internal web server. The URI includes the host-name of the system to make it easy to customize the content of each wallscreen.

  • The system starts up with a regular read-write root file-system. To prevent file-system corruption (and to limit the number of writes to the SD card) the root file-system is mounted read-only during boot in rc.local:

     mount -o remount,ro /
    
  • A number of directories have tmpfs-backed storage to workaround the read-only property of the main file-system:

     # /etc/fstab
     tmpfs /tmp tmpfs mode=1777 0 0
     /run/log /var/log none bind 0 0
     /tmp /home/pi/.config none bind 0 0
    

Systemd timers

The screensaver is deactivated on workdays at 07:00 and activated again at 18:00. This is done using systemd-timers. The following snippets configure the timers and the associated services:

# /etc/systemd/system/deactivate-screensaver@.service`
[Unit]
Description=Stop screensaver

[Service]
Type=oneshot
User=%I
Environment=DISPLAY=:0
Environment=XAUTHORITY=/tmp/.xauth
ExecStart=/usr/bin/xset s reset
# /etc/systemd/system/deactivate-screensaver.timer`
[Unit]
Description=Turn on screen

[Timer]
OnCalendar=Mon-Fri 07:00
Unit=deactivate-screensaver@pi.service

[Install]
WantedBy=timers.target
# /etc/systemd/system/activate-screensaver@.service`
[Unit]
Description=Start screensaver

[Service]
Type=oneshot
User=%I
Environment=DISPLAY=:0
Environment=XAUTHORITY=/tmp/.xauth
ExecStart=/usr/bin/xset s activate
# /etc/systemd/system/activate-screensaver.timer`
[Unit]
Description=Turn off screen

[Timer]
OnCalendar=Mon-Fri 18:00
Unit=activate-screensaver@pi.service

[Install]
WantedBy=timers.target

The Nitty Gritty

The playbook can be used as is. Note that this requires Ansible 2.2 (or later), since this version introduces the systemd module.


Updates

  • 2024-02-19 Updated the link to the raspberry image documentation.

Pip Oomen

OpenShift Solution Manager at Redpill Linpro

Pip – aka. Pepijn for his Dutch countrymen – started in Redpill Linpro in 2012. He is a Red Hat Certified Instructor, Examiner and OpenShift Specialist and – as developer turned system-administrator – always looking for ways to 'Automate all the Things'."

Containerized Development Environment

Do you spend days or weeks setting up your development environment just the way you like it when you get a new computer? Is your home directory a mess of dotfiles and metadata that you’re reluctant to clean up just in case they do something useful? Do you avoid trying new versions of software because of the effort to roll back software and settings if the new version doesn’t work?

Take control over your local development environment with containerization and Dev-Env-as-Code!

... [continue reading]

Ansible-runner

Published on February 27, 2024

Portable Java shell scripts with Java 21

Published on February 21, 2024