# Build your own raspberry pi image

Date: 2018-08-07

I had to build a private image of raspberry pi and after a talk with my brother, I thought it worth a post

<!--more-->

So we are going to create our own Cylon.<g class="gr_ gr\_4 gr-alert gr\_gramm gr\_inline\_cards gr\_disable\_anim_appear Grammar only-ins doubleReplace replaceWithoutSep" id="4" data-gr-id="4">pi</g> distro based on Raspian and [Cylon.js](https://cylonjs.com/).

This tutorial will use the [Installing Cylon.js for the Raspberry Pi](https://cylonjs.com/documentation/platforms/raspberry-pi/) guide in <g class="gr_ gr\_7 gr-alert gr\_gramm gr\_inline\_cards gr\_run\_anim Grammar only-ins doubleReplace replaceWithoutSep gr-progress" id="7" data-gr-id="7">cylon.js</g> website.  
This tutorial is tested only on Ubuntu because that's the system I currently use and It's easier for me.  
All the code of this tutorial will be available on a [<g class="gr_ gr\_8 gr-alert gr\_spell gr\_inline\_cards gr\_run\_anim ContextualSpelling ins-del multiReplace" id="8" data-gr-id="8">github</g> repo](https://github.com/EranGoldman/cylon.pi).

The logic of the script is to download the last version of <g class="gr_ gr\_5 gr-alert gr\_spell gr\_inline\_cards gr\_run\_anim ContextualSpelling" id="5" data-gr-id="5">raspbian</g>, extract and mount it, inject our files, unmount and compress  


The image is based on 2 scripts:  
Build.sh &#8211; to build the image &#8211; you run this script on your computer  
first-boot.sh &#8211; to install everything on the pi &#8211; the build script injecting this script to the image and the <g class="gr_ gr\_220 gr-alert gr\_spell gr\_inline\_cards gr\_disable\_anim_appear ContextualSpelling" id="220" data-gr-id="220">raspbian</g> will run it on the first reboot.  


## BUILD.SH

The script is split into 4 sections:  
Image Constants &#8211; parameters of the image file  
Installation Constants &#8211; where to do all the downloading, extracting and manipulating <g class="gr_ gr\_233 gr-alert sel gr\_gramm gr\_replaced gr\_inline\_cards gr\_disable\_anim\_appear Grammar multiReplace" id="233" data-gr-id="233">is happening</g>. I recommend that it'll be done in /<g class="gr_ gr\_289 gr-alert gr\_spell gr\_inline\_cards gr\_disable\_anim_appear ContextualSpelling" id="289" data-gr-id="289">tmp</g> directory  so it'll be deleted next boot  
Helpful functions &#8211; functions to print time, and manipulate text etc  
The script itself &#8211; here the magic happen

I'll focus on the building part because that the only interesting part:  
We start with updating and grubbing the dependencies needed.

```
apt-get update
apt-get --yes install git wget curl unzip kpartx libarchive-zip-perl dos2unix
```

Then creating the temporary directories 

```
mkdir -p $installation_dir
mkdir -p $installation_dir/boot $installation_dir/root
```

Downloading and extracting the latest raspbian

```
wget -nv -O $installation_dir/raspbian.zip "https://downloads.raspberrypi.org/raspbian_lite_latest" > /dev/null

unzip $installation_dir/raspbian.zip -d $installation_dir
mv $installation_dir/raspbian.img $imagefile
```

Than mounting the image to a temp folders

```
PARTITIONS=($(kpartx -asv $imagefile | grep -o 'loop[0-9][0-9]*p[0-9]'))
mount -o rw -t vfat /dev/mapper/${PARTITIONS[0]} $installation_dir/boot
mount -o rw -t ext4 /dev/mapper/${PARTITIONS[1]} $installation_dir/root
```

Injecting the data and files to the image  


```
sed -i "s/127.0.1.1.*/127.0.1.1 $hostname/" $installation_dir/root/etc/hosts
touch $installation_dir/boot/ssh
echo "$hostname" > $installation_dir/root/etc/hostname

cp image_files/rc.local $installation_dir/root/etc/rc.local
cp image_files/first-boot.sh $installation_dir/boot/first-boot.sh
touch $installation_dir/boot/first-boot.log
```

Closing wrapping and compressing

```
kpartx -u $imagefile
sleep 2
sync
sleep 2
umount $installation_dir/boot
umount $installation_dir/root
kpartx -dv $imagefile

shorthash=$(git log --pretty=format:'%h' -n 1)
crc32checksum=$(crc32 $imagefile)
destination="$hostname-$timestamp-git$shorthash-crc$crc32checksum.img"

mv -v $imagefile "$destination"
rm -rf $installation_dir

xz --verbose --compress --keep "$destination"
crc32checksum=$(crc32 "$destination.xz")
mv "$destination.xz" "$hostname-$timestamp-git$shorthash-crc$crc32checksum.img.xz"
```

And that's all after you finished just [write the image to an SD](https://www.instructables.com/id/How-To-Burn-Raspbian-Weezy-to-an-SD-Card-FULL-/)  
Any code that you put in the first-boot file will be executed when the raspbian started.  
I put inside the script to generate random password because fixed image passwords <g class="gr_ gr\_119 gr-alert gr\_gramm gr\_inline\_cards gr\_disable\_anim_appear Grammar multiReplace" id="119" data-gr-id="119">are</g> bad.  
And the script to install Cylon.js

The installation script is mostly copied from the Cylon.js site
