8 years ago, when I started working at Teevity, I discovered Amazon Web Services and a special init script for ubuntu images called "cloud init".
Let's see what we can do with this and how to do the same with a raspberry pi.
It was built for Amazon EC2 instances. Now it is available for all cloud providers including OpenStack :
Custom scripts are attached to instances to perform specific actions when the instance is launched. For example, if you are unable to install cloud-init inside a guest operating system, you can use a custom script to get a public key and add it to the user account. Type your script directly into the Customization Script field. If your browser supports the HTML5 File API, you may choose to load your script from a file. The size of your script should not exceed 16 Kb.
Cloud init is executed as the last step in the boot process. It calls the hypervisor to get metadata containing the script you typed. IE on Amazon EC2 it calls http://169.254.169.254 (check Instance Metadata and User Data documentation)
In many cases it can helps a lot for automation : no custom images, a good init script can install an entire instance with all your softwares without deploying orchestration tools such as ansible or salt.
INFO : Ansible, Juju, etc... are great and usefull tools
It is not a cloud init, but it tooks inspiration from. Build a custom image for a raspberry PI is not so easy to do.
For special projects, we need to build some prototypes with special configurations, easy and fast to deploy. I mean "easy" because we do not have any connection, so no SSH, no screen and no keyboard.
Working with a machine running Linux remove a big constraint : ext4 partitions are readables. With Windows or MacOS it could be a little different. On Raspbian SD card we have 2 partitions :
Raspbian has a feature called "headless" (https://www.raspberrypi.org/documentation/configuration/wireless/headless.md) for an easy setup. In other words, with 2 files we can connect to a wifi network and install a SSH server. Just put a wpa_supplicant.conf file directly in the /boot partition and an empty file "ssh" GREAT ! And a custom script ? No way they say...
From : https://www.raspberrypi.org/forums/viewtopic.php?t=28860
root@server:/tmp# fdisk -l 2018-06-27-raspbian-stretch-lite.img
Disk 2018-06-27-raspbian-stretch-lite.img: 1,8 GiB, 1862270976 bytes, 3637248 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x4d3ee428
Device Boot Start End Sectors Size Id Type
2018-06-27-raspbian-stretch-lite.img1 8192 96663 88472 43,2M c W95 FAT32 (LBA)
2018-06-27-raspbian-stretch-lite.img2 98304 3637247 3538944 1,7G 83 Linux
root@server:/tmp# mount -v -o offset=50331648 -t ext4 2018-06-27-raspbian-stretch-lite.img ./root
I edited rc.local file (/etc/rc.local) to find a start.sh script in /boot and execute it if exists :
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
if [ -f /boot/start.sh ]; then
printf "Launching a startup script"
/boot/start.sh
fi
exit 0
I have two distinct tasks :
To make a distinction, I simply use an empty file as a flag while the installation is fresh. If the file exists, I need to install.
#!/bin/sh
if [ -f /boot/initial ]; then
apt-get update
apt-get install -y python python-pip python-numpy ca-certificates
pip install RPi.GPIO
pip install requests
rm /boot/initial
fi
# try to download a new version
wget http://admin:PASSWORD@downloads.mathieupassenaud.fr/mystuff.py -O /opt/mystuff.py
python /opt/mystuff.py &
So I have now a generic raspbian image. With a simple copy/paste of a set of files (wpa_supplicant.conf, start.sh, initial). With some projects (more to come next month !) I put some configuration files. Anyone can deploy a software without SSH, mounting EXT4 partition... Just copy/paste files directly with the mouse in Windows :-)
My image is available here