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...
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