Skip to content

Commit

Permalink
Merge pull request #162 from jareware/raspbian-bullseye
Browse files Browse the repository at this point in the history
Raspbian Bullseye
  • Loading branch information
jareware authored Dec 28, 2021
2 parents 799e1b3 + 1d13602 commit bace55a
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 61 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ Note: You can user `${SERIAL}` to get Pi's serial number into URL.
### Automatic WiFi setup

1. After flashing remount your SD card.
2. Create a wpa_supplicant.conf in your SD cards boot folder
2. Create a `wpa_supplicant.conf` in your SD cards boot folder
3. Copy the [sample wpa_supplicant.conf](#sample-wpasupplicantconf) file into the boot folder on the SD card.
4. Replace `WiFi-SSID` and `WiFi-PASSWORD` with your WiFi configuration.
5. *Optional*: Set the country code to your country code e.g. DE.
5. Optional: Set the country code to your country code e.g. `DE`.

#### Sample wpa_supplicant.conf
```
Expand All @@ -56,15 +56,15 @@ update_config=1
country=US
network={
ssid="WiFi-SSID"
psk="WiFi-PASSWORD"
key_mgmt=WPA-PSK
ssid="WiFi-SSID"
psk="WiFi-PASSWORD"
key_mgmt=WPA-PSK
}
```

## Hardware

Works with [Raspberry Pi versions 1, 2 & 3](https://www.raspberrypi.org/products/). The 3 series is recommended, as it's the most powerful, and comes with built-in WiFi (though both [official](https://www.raspberrypi.org/products/raspberry-pi-usb-wifi-dongle/) and [off-the-shelf](https://elinux.org/RPi_USB_Wi-Fi_Adapters) USB WiFi dongles can work equally well).
Works with [all Raspberry Pi versions](https://www.raspberrypi.org/products/). Versions 3 and 4 are recommended, though, since the smaller ones can be a bit underpowered for rendering complex dashboards. The 3 and 4 also come with built-in WiFi, which is convenient (though both [official](https://www.raspberrypi.org/products/raspberry-pi-usb-wifi-dongle/) and [off-the-shelf](https://elinux.org/RPi_USB_Wi-Fi_Adapters) USB WiFi dongles can work equally well).

Make sure you have a [compatible 4+ GB SD card](http://elinux.org/RPi_SD_cards). In general, any Class 10 card will work, as they're fast enough and of high enough quality.

Expand Down
11 changes: 10 additions & 1 deletion docs/first-boot.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ Finally, further tweaks can be made by changing the [Chromium command line switc

Adding these options will allow you to mix secure (i.e. HTTPS) origins with insecure ones (you need to specifically white-list them). Sometimes you need stuff like this to pull together all the bits and pieces of your dashboard from different origins. We're not saying you should. But you can.

## Controlling the kiosk remotely

Sometimes you need to do basic remote adjustments, like changing the URL that's displayed.

- If you need a lot of flexibility, [you can install VNC](https://github.com/futurice/chilipie-kiosk/issues/38#issuecomment-442031274) to get a full remote desktop
- If you just need to set the URL, you can SSH over (not enabled by default; see above), and e.g. [run something like](https://github.com/futurice/chilipie-kiosk/issues/71#issuecomment-522035239): `export DISPLAY=:0; xdotool key F11 sleep 1 key ctrl+l sleep 1 type 'https://google.com'; xdotool sleep 1 key KP_Enter; xdotool key F11`. Very crude. Very effective.

## Username and password

If you need to login to a shell, the default username and password are `pi` and `raspberry`, as is tradition for Raspberry Pi. The `pi` user also has `sudo` access.
Expand All @@ -69,13 +76,15 @@ Press `Ctrl + Alt + F3` to get to a virtual terminal, and use your favorite edit

Save the file, and `sudo reboot`.

Note that on the Pi 4, you'll need to disable the `dtoverlay=vc4-fkms-v3d` line in `/boot/config.txt` for this to work. But then that [may cause other issues](https://www.reddit.com/r/raspberry_pi/comments/dw1376/dtoverlayvc4fkmsv3d_causes_display_to_shift_right/). This is hopefully fixed in a future Raspbian release.

Exotic screens may require a bit more fiddling. See issues [#41](https://github.com/futurice/chilipie-kiosk/issues/41) and [#58](https://github.com/futurice/chilipie-kiosk/issues/58) for ideas.

## Replacing the boot graphics

The image that's displayed while the kiosk is starting can be changed by just replacing `~/background.png`.

To change the default chilipie-kiosk boot graphics to a nice doge, for example, try `wget -O background.png bit.ly/2w1P4Il`.
To change the default chilipie-kiosk boot graphics to a [nice Windoge one](https://mcdn.wallpapersafari.com/medium/93/77/8xKLeg.png), for example, try `wget -O background.png https://bit.ly/2Q4GF1t`.

## Increasing boot show delay

Expand Down
184 changes: 135 additions & 49 deletions docs/image-setup.sh
Original file line number Diff line number Diff line change
@@ -1,29 +1,77 @@
#!/bin/bash

MOUNTED_BOOT_VOLUME="boot" # i.e. under which name is the SD card mounted under /Volumes on macOS
BOOT_CMDLINE_TXT="/Volumes/$MOUNTED_BOOT_VOLUME/cmdline.txt"
BOOT_CONFIG_TXT="/Volumes/$MOUNTED_BOOT_VOLUME/config.txt"
# exit on error; treat unset variables as errors; exit on errors in piped commands
set -euo pipefail

# Ensure we operate from consistent pwd for the rest of the script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" # Figure out the ABSOLUTE PATH of this script without relying on the realpath command, which may not always be available
cd "$DIR"

if [ "$OSTYPE" == "linux-gnu" ]; then
MOUNTED_BOOT_VOLUME="/media/$(whoami)/boot" # i.e. under which name is the SD card mounted under /media in Linux (Ubuntu)
elif [[ "$OSTYPE" == darwin* ]]; then
MOUNTED_BOOT_VOLUME="/Volumes/boot" # i.e. under which name is the SD card mounted under /Volumes on macOS
else
echo "Error: Unsupported platform $OSTYPE, sorry" && exit 1
fi

BOOT_CMDLINE_TXT="$MOUNTED_BOOT_VOLUME/cmdline.txt"
BOOT_CONFIG_TXT="$MOUNTED_BOOT_VOLUME/config.txt"
SD_SIZE_REAL=2500 # this is in MB
SD_SIZE_SAFE=2800 # this is in MB
SD_SIZE_ZERO=3200 # this is in MB
PUBKEY="$(cat ~/.ssh/id_rsa.pub)"
SSH_PUBKEY="$(cat ~/.ssh/id_rsa.pub)"
SSH_CONNECT_TIMEOUT=30
LOCALE="en_US.UTF-8 UTF-8" # or e.g. "fi_FI.UTF-8 UTF-8" for Finland
LANGUAGE="en_US.UTF-8" # should match above
KEYBOARD="us" # or e.g. "fi" for Finnish
TIMEZONE="Etc/UTC" # or e.g. "Europe/Helsinki"; see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

function echo-bold {
echo -e "$(tput -Txterm-256color bold)$1$(tput -Txterm-256color sgr 0)" # https://unix.stackexchange.com/a/269085; the -T arg accounts for $ENV not being set
}
function working {
echo -e "\n $1"
echo-bold "\n[WORKING] $1"
}
function question {
echo -e "\n🛑 $1"
echo-bold "\n[QUESTION] $1"
}
function ssh {
/usr/bin/ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 "pi@$IP" "$1"
/usr/bin/ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout="$SSH_CONNECT_TIMEOUT" "pi@$IP" "$1"
}
function scp {
/usr/bin/scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$@" "pi@$IP:/home/pi"
}
function figureOutSdCard {
if [ "$OSTYPE" == "linux-gnu" ]; then
lsblk --fs
DISK="/dev/$(lsblk -l | grep "$MOUNTED_BOOT_VOLUME" | sed 's/[0-9].*//')"
DISK_SAMPLE="/dev/sda"
elif [[ "$OSTYPE" == darwin* ]]; then
diskutil list
DISK="$(diskutil list | grep /dev/ | grep external | grep physical | cut -d ' ' -f 1 | head -n 1)"
DISK_SAMPLE="/dev/disk2"
else
echo "Error: Unsupported platform $OSTYPE, sorry" && exit 1
fi
}
function unmountSdCard {
if [ "$OSTYPE" == "linux-gnu" ]; then
for part in $(lsblk --list "$DISK" | grep part | sed 's/ .*//'); do
udisksctl unmount -b "/dev/$part"
done
elif [[ "$OSTYPE" == darwin* ]]; then
diskutil unmountDisk "$DISK"
else
echo "Error: Unsupported platform $OSTYPE, sorry" && exit 1
fi
}

question "Enter version (e.g. \"1.2.3\") being built:"
question "Enter version (e.g. \"1.2.3\") being built"
echo "Omit the \"v\" prefix, it'll be added where needed"
echo "For alpha/beta builds, use a \"-betaN\" suffic"
echo "For RC builds, DO NOT use any suffix, as then the same image can't be promoted to stable without rebuilding"
echo "Enter version:"
read TAG

working "Updating version file"
Expand All @@ -40,28 +88,38 @@ cp ../docs/first-boot.md md-input
./node_modules/.bin/html-inline -i md-output/first-boot.html > ../home/first-boot.html
rm -rf md-input md-output

question "Mount the SD card (press enter when ready)"
question "Physically mount the SD card to this machine "
echo "(press enter when ready)"
read

working "Figuring out SD card device"
diskutil list
DISK="$(diskutil list | grep /dev/ | grep external | grep physical | cut -d ' ' -f 1 | head -n 1)"
figureOutSdCard

question "Based on the above, SD card determined to be \"$DISK\" (should be e.g. \"/dev/disk2\"), press enter to continue"
question "Based on the above, SD card determined to be \"$DISK\""
echo "Should be e.g. \"$DISK_SAMPLE\""
echo "(press enter to confirm)"
read

working "Safely unmounting the card"
diskutil unmountDisk "$DISK"
unmountSdCard

working "Writing the card full of zeros (for security and compressibility reasons)"
working "Writing the card full of zeros"
# ...for security and compressibility reasons
echo "This may take a long time"
echo "You may be prompted for your password by sudo"
sudo dd bs=1m count="$SD_SIZE_ZERO" if=/dev/zero of="$DISK"
if [ "$OSTYPE" == "linux-gnu" ]; then
sudo dd bs=1M count="$SD_SIZE_ZERO" if=/dev/zero of="$DISK" status=progress
elif [[ "$OSTYPE" == darwin* ]]; then
sudo dd bs=1m count="$SD_SIZE_ZERO" if=/dev/zero of="$DISK"
else
echo "Error: Unsupported platform $OSTYPE, sorry" && exit 1
fi

question "Prepare baseline Raspbian:"
echo "* Flash Raspbian Lite with Etcher"
question "Prepare baseline Raspberry Pi OS Lite:"
echo "* Flash the OS with Raspberry Pi Imager"
echo "* Eject the SD card"
echo "* Mount the card back"
echo "* Wait for your OS to mount it"
echo "(press enter when ready)"
read

Expand All @@ -76,10 +134,10 @@ mv temp "$BOOT_CMDLINE_TXT"

working "Enabling SSH for first boot"
# https://www.raspberrypi.org/documentation/remote-access/ssh/
touch "/Volumes/$MOUNTED_BOOT_VOLUME/ssh"
touch "$MOUNTED_BOOT_VOLUME/ssh"

working "Safely unmounting the card"
diskutil unmountDisk "$DISK"
unmountSdCard

question "Do initial Pi setup:"
echo "* Eject the card"
Expand All @@ -91,63 +149,79 @@ read IP

working "Installing temporary SSH pubkey"
echo -e "Password hint: \"raspberry\""
ssh "mkdir .ssh && echo '$PUBKEY' > .ssh/authorized_keys"
ssh "mkdir .ssh && echo '$SSH_PUBKEY' > .ssh/authorized_keys"

working "Figuring out partition start"
ssh "echo -e 'p\nq\n' | sudo fdisk /dev/mmcblk0 | grep /dev/mmcblk0p2 | tr -s ' ' | cut -d ' ' -f 2" > temp
START="$(cat temp)"
rm temp

question "Partition start determined to be \"$START\" (should be e.g. \"98304\"), press enter to continue"
question "Partition start determined to be \"$START\""
echo "Should be e.g. \"98304\""
echo "(press enter to confirm)"
read

working "Resizing the root partition on the Pi"
working "Resizing the root partition"
ssh "echo -e 'd\n2\nn\np\n2\n$START\n+${SD_SIZE_REAL}M\ny\nw\n' | sudo fdisk /dev/mmcblk0"

working "Setting locale"
# We want to do this as early as possible, so perl et al won't complain about misconfigured locales for the rest of the image prep
ssh "echo $LOCALE | sudo tee /etc/locale.gen"
ssh "sudo locale-gen"
ssh "echo -e \"LANGUAGE=$LANGUAGE\nLC_ALL=$LANGUAGE\" | sudo tee /etc/environment"

working "Setting hostname"
# We want to do this right before reboot, so we don't get a lot of unnecessary complaints about "sudo: unable to resolve host chilipie-kiosk" (https://askubuntu.com/a/59517)
ssh "sudo hostnamectl set-hostname chilipie-kiosk"
ssh "sudo sed -i 's/raspberrypi/chilipie-kiosk/g' /etc/hosts"
ssh "sudo perl -i -p0e 's/raspberrypi/chilipie-kiosk/g' /etc/hosts" # "perl" is more cross-platform than "sed -i"

# From now on, some ssh commands will exit non-0, which should be fine
set +e

working "Rebooting the Pi"
ssh "sudo reboot"

echo "Waiting for host to come back up..."
until ssh "echo OK"
until SSH_CONNECT_TIMEOUT=5 ssh "echo OK"
do
sleep 1
done

working "Finishing the root partition resize"
ssh "df -h . && sudo resize2fs /dev/mmcblk0p2 && df -h ."

# From raspi-config: https://github.com/RPi-Distro/raspi-config/blob/d98686647ced7c0c0490dc123432834735d1c13d/raspi-config#L1313-L1321
# See also: https://github.com/futurice/chilipie-kiosk/issues/61#issuecomment-524622522
working "Enabling auto-login to CLI"
# From: https://github.com/RPi-Distro/raspi-config/blob/985548d7ca00cab11eccbb734b63750761c1f08a/raspi-config#L955
SUDO_USER=pi
ssh "sudo systemctl set-default multi-user.target"
ssh "sudo sed /etc/systemd/system/autologin@.service -i -e \"s#^ExecStart=-/sbin/agetty --autologin [^[:space:]]*#ExecStart=-/sbin/agetty --autologin $SUDO_USER#\""
# Set auto-login for TTY's 1-3
ssh "sudo ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service"
ssh "sudo ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty2.service"
ssh "sudo ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty3.service"
ssh "sudo ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service"
ssh "sudo ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty2.service"
ssh "sudo ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty3.service"
ssh "sudo mkdir -p /etc/systemd/system/getty@tty1.service.d"
ssh "sudo mkdir -p /etc/systemd/system/getty@tty2.service.d"
ssh "sudo mkdir -p /etc/systemd/system/getty@tty3.service.d"
ssh "echo -e '[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin pi --noclear %I \$TERM\n' | sudo tee /etc/systemd/system/getty@tty1.service.d/autologin.conf"
ssh "echo -e '[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin pi --noclear %I \$TERM\n' | sudo tee /etc/systemd/system/getty@tty2.service.d/autologin.conf"
ssh "echo -e '[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin pi --noclear %I \$TERM\n' | sudo tee /etc/systemd/system/getty@tty3.service.d/autologin.conf"

working "Setting timezone"
ssh "(echo '$TIMEZONE' | sudo tee /etc/timezone) && sudo dpkg-reconfigure --frontend noninteractive tzdata"

working "Setting keyboard layout"
ssh "(echo -e 'XKBMODEL="pc105"\nXKBLAYOUT="$KEYBOARD"\nXKBVARIANT=""\nXKBOPTIONS=""\nBACKSPACE="guess"\n' | sudo tee /etc/default/keyboard) && sudo dpkg-reconfigure --frontend noninteractive keyboard-configuration"

working "Shortening message-of-the-day for logins"
ssh "sudo rm /etc/profile.d/sshpwd.sh"
ssh "echo | sudo tee /etc/motd"
working "Silencing console logins" # this is to avoid a brief flash of the console login before X comes up
ssh "sudo rm /etc/profile.d/sshpwd.sh /etc/profile.d/wifi-check.sh" # remove warnings about default password and WiFi country (https://raspberrypi.stackexchange.com/a/105234)
ssh "touch .hushlogin" # https://scribles.net/silent-boot-on-raspbian-stretch-in-console-mode/
ssh "sudo perl -i -p0e 's#--autologin pi#--skip-login --noissue --login-options \"-f pi\"#g' /etc/systemd/system/getty@tty1.service.d/autologin.conf" # "perl" is more cross-platform than "sed -i"

working "Installing packages"
ssh "sudo apt-get update && sudo apt-get install -y vim matchbox-window-manager unclutter mailutils nitrogen jq chromium-browser xserver-xorg xinit rpd-plym-splash xdotool cec-utils"
ssh "sudo apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get install -y vim matchbox-window-manager unclutter mailutils nitrogen jq chromium-browser xserver-xorg xinit rpd-plym-splash xdotool rng-tools xinput-calibrator cec-utils"
# We install mailutils just so that you can check "mail" for cronjob output

working "Setting home directory default content"
ssh "rm -rfv /home/pi/*"
scp $(find ../home -type file)
scp $(find ../home -type f)

working "Setting splash screen background"
ssh "sudo rm /usr/share/plymouth/themes/pix/splash.png && sudo ln -s /home/pi/background.png /usr/share/plymouth/themes/pix/splash.png"
Expand All @@ -161,6 +235,10 @@ ssh "sudo reboot"
question "Once the Pi has rebooted into Chromium:"
echo "* Tell Chromium we don't want to sign in"
echo "* Configure Chromium to start \"where you left off\""
echo " * F11 to exit full screen"
echo " * Alt + F, then S to go to Settings"
echo " * Type \"continue\" to filter the options"
echo " * Tab to select \"Continue where you left off\""
echo "* Navigate to \"file:///home/pi/first-boot.html\""
echo "(press enter when ready)"
read
Expand All @@ -174,26 +252,28 @@ ssh "chromium-browser --version | cut -d ' ' -f 1-2" > temp
VERSION_CHROMIUM="$(cat temp)"
rm temp

working "Removing SSH host keys & enable regeneration"
ssh "sudo rm -f -v /etc/ssh/ssh_host_*_key* && sudo systemctl enable regenerate_ssh_host_keys"
working "Disabling SSH access & restoring safe defaults & shutting down"
tempFile="$(ssh mktemp)" # need to do this via a temp file on the host, otherwise disabling SSH while using SSH ends up being problematic
ssh "chmod a+x $tempFile"
ssh "echo 'rm -f /etc/ssh/ssh_host_*_key*; systemctl enable regenerate_ssh_host_keys; rm .ssh/authorized_keys; systemctl disable ssh; poweroff' > $tempFile"
ssh "sudo nohup $tempFile"

working "Removing temporary SSH pubkey, disabling SSH & shutting down"
ssh "(echo > .ssh/authorized_keys) && sudo systemctl disable ssh && sudo shutdown -h now"

question "Eject the SD card from the Pi, and mount it back to this computer (press enter when ready)"
question "Eject the SD card from the Pi, and mount it back to this computer"
echo "(press enter when ready)"
read

working "Figuring out SD card device"
# We do this again now just to be safe
diskutil list
DISK="$(diskutil list | grep /dev/ | grep external | grep physical | cut -d ' ' -f 1 | head -n 1)"
working "Figuring out SD card device"
figureOutSdCard

question "Based on the above, SD card determined to be \"$DISK\" (should be e.g. \"/dev/disk2\"), press enter to continue"
question "Based on the above, SD card determined to be \"$DISK\""
echo "Should be e.g. \"$DISK_SAMPLE\""
echo "(press enter to confirm)"
read

working "Making boot quieter (part 1)" # https://scribles.net/customizing-boot-up-screen-on-raspberry-pi/
echo "Updating: $BOOT_CONFIG_TXT"
sed -i "" "s/#disable_overscan=1/disable_overscan=1/g" "$BOOT_CONFIG_TXT"
perl -i -p0e "s/#disable_overscan=1/disable_overscan=1/g" "$BOOT_CONFIG_TXT" # "perl" is more cross-platform than "sed -i"
echo -e "\ndisable_splash=1" >> "$BOOT_CONFIG_TXT"

working "Making boot quieter (part 2)" # https://scribles.net/customizing-boot-up-screen-on-raspberry-pi/
Expand All @@ -206,13 +286,19 @@ cat "$BOOT_CMDLINE_TXT" \
mv temp "$BOOT_CMDLINE_TXT"

working "Safely unmounting the card"
diskutil unmountDisk "$DISK"
unmountSdCard

working "Dumping the image from the card"
cd ..
echo "This may take a long time"
echo "You may be prompted for your password by sudo"
sudo dd bs=1m count="$SD_SIZE_SAFE" if="$DISK" of="chilipie-kiosk-$TAG.img"
if [ "$OSTYPE" == "linux-gnu" ]; then
sudo dd bs=1M count="$SD_SIZE_ZERO" if="$DISK" of="chilipie-kiosk-$TAG.img" status=progress
elif [[ "$OSTYPE" == darwin* ]]; then
sudo dd bs=1m count="$SD_SIZE_ZERO" if="$DISK" of="chilipie-kiosk-$TAG.img"
else
echo "Error: Unsupported platform $OSTYPE, sorry" && exit 1
fi

working "Compressing image"
COPYFILE_DISABLE=1 tar -zcvf chilipie-kiosk-$TAG.img.tar.gz chilipie-kiosk-$TAG.img
Expand Down
2 changes: 1 addition & 1 deletion home/.chilipie-kiosk-version
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
2.1.0
3.0.0

https://github.com/futurice/chilipie-kiosk
Loading

0 comments on commit bace55a

Please sign in to comment.