diff --git a/README.md b/README.md index e532eaa..d66f9ec 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # YunoHost installation scripts +Forked version: some discussion available [here](https://forum.yunohost.org/t/building-a-new-image-for-raspberry-debian-jessie-fr-en/1101) + ## Context The script `install_yunohost` will install [YunoHost](https://yunohost.org/) on a Debian system. diff --git a/build_arm_image/.gitignore b/build_arm_image/.gitignore new file mode 100644 index 0000000..1bdecb0 --- /dev/null +++ b/build_arm_image/.gitignore @@ -0,0 +1,2 @@ +_build_arm_steps +.*.swp diff --git a/build_arm_image/01_create_sdcard.sh b/build_arm_image/01_create_sdcard.sh new file mode 100755 index 0000000..c975b34 --- /dev/null +++ b/build_arm_image/01_create_sdcard.sh @@ -0,0 +1,244 @@ +#!/bin/bash +# +# Create the sdcard on your PC with the latest debian raspbian. +# +# Usage: +# ./01_create_sdcard.sh downloaded_debian_image.zip /dev/sdcard_device +# ./01_create_sdcard.sh generated_yunohost.img /dev/sdcard_device +# +# HowTo: +# find your sdcard device: +# mount it first graphicaly +# next issue a df -h look for something "/dev/mmcblk0p1" +# create a totally new image: +# delete _build_arm_steps/ which is the cache folder. +# follows steps in README.md +# +# Status: functional +# Licence: GPLv3 +# Author: sylvain303@github +# SeeAlso: + +# informations about Raspbian image: +# Raspbian Jessie Lite Version: November 2015 Release date: 2015-11-21 +# version: SHA-1 of the .zip: 97888fcd9bfbbae2a359b0f1d199850852bf0104 +# Kernel version: 4.1 +# http://downloads.raspberrypi.org/raspbian/release_notes.txt + + +# DOWNLOAD_URL used only for echo a message +# SHA_DEBIAN_IMG_ZIP need to be updated to match your image +DOWNLOAD_URL=https://www.raspberrypi.org/downloads/raspbian/ +SHA_DEBIAN_IMG_ZIP="6741a30d674d39246302a791f1b7b2b0c50ef9b7" + +die() { + echo "$*" + exit 1 +} + +# helper, test if a shell program exists in PATH +test_tool() { + local cmd=$1 + if type $cmd > /dev/null + then + # OK + return 0 + else + die "tool missing: $cmd" + fi +} + +# skip if the file exists. +# usage: skip_if _build_arm_steps/somefile && return 2 +skip_if() { + if [[ -e "$1" ]] + then + echo "cached" + return 0 + fi + # echo -n "continue for $1" + return 1 +} + +sha_verify_zip() { + local zip=$DEBIAN_IMG_ZIP + + [[ -z "$zip" ]] && { echo "no zip refuse to run"; return 3; } + + local out=_build_arm_steps/sha_verify_zip + skip_if $out && return 2 + sha1sum $zip > $out + # read only sha check hash + local sha="$(sed -e 's/\(^[a-f0-9]\+\).*/\1/' $out)" + if [[ "$sha" != "$SHA_DEBIAN_IMG_ZIP" ]] + then + die "NOK: '$sha' != '$SHA_DEBIAN_IMG_ZIP'" + fi +} + +# unzip raspbian image in the cache folder +unzip_img() { + local img_filename=$(unzip -l $DEBIAN_IMG_ZIP | awk '/\.img$/ { print $4 }') + if ! skip_if _build_arm_steps/$img_filename + then + unzip -o $DEBIAN_IMG_ZIP -d _build_arm_steps + fi + + # get extrated image filename from zip file + DEBIAN_IMG="_build_arm_steps/$img_filename" +} + +# helper, try to guess top device name +# /dev/sdp2 => /dev/sdp +# /dev/mmcblk0p1 => /dev/mmcblk0 +# just some regexp, no smart thing +get_top_device() { + local device="$1" + local regexp1='^/dev/sd[a-z]' + local regexp2='^/dev/mmcblk[0-9]' + + if [[ "$device" =~ $regexp1 ]] + then + #echo sd + device="${device/[0-9]/}" + elif [[ "$device" =~ $regexp2 ]] + then + #echo mmcblk + device="${device/p[0-9]/}" + fi + + echo "$device" +} + +# helper, umount the sdcard partition if any +umount_sdcard_partition() { + [[ -z "$SDCARD" ]] && { echo '$SDCARD is empty refusing to run'; return; } + local p + # search and replace all occurence of / by . + local pattern=${SDCARD////.} + pattern=${pattern/p[0-9]/} + for p in $(df | awk "/^$pattern/ { print \$1 }") + do + sudo umount $p + done + echo "done device for sdcard=${pattern//.//}" +} + +dd_to_sdcard() { + [[ -z "$SDCARD" ]] && { echo '$SDCARD is empty refusing to run'; return; } + # ensure that sdcard partitions are unmounted with umount_sdcard_partition + echo "starting dd it will take some times…" + sudo dd bs=16M if="$DEBIAN_IMG" of=$SDCARD + sudo sync +} + +test_all_tools() { + for t in $* + do + test_tool $t + done +} + +# mount the .img so we can write on it before copying on the sdcard +mount_loopback_img() { + [[ -z "$DEBIAN_IMG" ]] && { echo '$DEBIAN_IMG is empty refusing to run'; return; } + mkdir -p _build_arm_steps/mnt + local dev_loop0=$(sudo losetup -f --show "$DEBIAN_IMG") + local part_offset=$(sudo fdisk -l $dev_loop0 | awk '/Linux/ { print $2 }') + # mount the ext4 partition at computed offset + local dev_loop1=$(sudo losetup -f --show -o $((512 * $part_offset)) "$DEBIAN_IMG") + sudo mount $dev_loop1 _build_arm_steps/mnt/ +} + +umount_loopback_img() { + # find mounted loopback + local dev_loop1=$(mount | awk '/_build_arm_steps/ { print $1 }') + # compute loop n-1 + local n=${dev_loop1#/dev/loop} + local dev_loop0="/dev/loop$(($n - 1))" + sudo umount _build_arm_steps/mnt + sudo losetup -d $dev_loop1 + sudo losetup -d $dev_loop0 +} + +# copy a local key for ssh without password later +# having an ssh-key pair to remote connect on the raspi will be used by the next step +add_ssh_key_to_img() { + mount_loopback_img + cd _build_arm_steps/mnt/home/pi/ + mkdir .ssh + local ssh_key=$OLDPWD/_build_arm_steps/nopasskey + # silently generate an ssh-key pair + yes | ssh-keygen -q -t rsa -C "nopasskey-install" -N "" -f $ssh_key > /dev/null + cp ${ssh_key}.pub .ssh/authorized_keys + # remove some permissions + chmod -R go= .ssh/ + # give to pi user id + sudo chown -R --reference . .ssh + # return to working folder + cd - > /dev/null + umount_loopback_img + echo "ssh-key added" +} + +# functions call in that order, edit remove a long running step if already done or if +# you want to skip it, step states are saved in folder _build_arm_steps and skipped automatically. +# STEPS is modifiy in main() if argument1 is an .img and not a .zip +STEPS=" +sha_verify_zip +unzip_img +add_ssh_key_to_img +umount_sdcard_partition +dd_to_sdcard" + +# main wrapper, so the script can be sourced for debuging purpose or unittesting +main() { + # positional argument must be script argument. + # init + if [[ -z "$1" ]] + then + echo "argument 1 error: expecting raspbian image file.zip or an img" + echo "can be downloaded here: $DOWNLOAD_URL" + exit 1 + fi + + local regexp='\.img$' + + # reading script argument + DEBIAN_IMG_ZIP=$1 + if [[ "$1" =~ $regexp ]] + then + DEBIAN_IMG="$1" + DEBIAN_IMG_ZIP="" + # write image verbatim without modification + STEPS=" + umount_sdcard_partition + dd_to_sdcard" + else + [[ -f "$DEBIAN_IMG_ZIP" ]] || die "error raspbian image not found: '$DEBIAN_IMG_ZIP'" + fi + + SDCARD=$(get_top_device "$2") + [[ -z "$SDCARD" ]] && die "argument 2 error: expecting sdcard_device" + + test_all_tools dd sync sudo losetup ssh-keygen + mkdir -p _build_arm_steps + + # actions loop + for s in $STEPS + do + echo -n "$s: " + eval $s + done +} + +# sourcing code detection, if code is sourced for debug purpose, main is not executed. +[[ $0 != "$BASH_SOURCE" ]] && sourced=1 || sourced=0 +if [[ $sourced -eq 0 ]] +then + # pass positional argument as is + main "$@" +else + # just print STEPS so I can copy/paste to call them interactivly + echo $STEPS +fi diff --git a/build_arm_image/02_install_yunohost.sh b/build_arm_image/02_install_yunohost.sh new file mode 100755 index 0000000..a441215 --- /dev/null +++ b/build_arm_image/02_install_yunohost.sh @@ -0,0 +1,252 @@ +#!/bin/bash +# +# Usage: ./02_install_yunohost.sh DHCP_IP_ADDRESS_OF_RASPBERRYPI +# +# Doc: See README.md +# +# STEPS: +# 1. enlarge filesystem with raspi-config --expand-rootfs and reboot +# 2. run install_yunohostv2 on the raspi +# 3. install an yunohost-firstboot script and shutdown +# +# Status: functional +# Licence: GPLv3 +# Author: sylvain303@github + +# wrapper to use ssh with our nopasskey +# Usage: sshpi "some remote commands" +sshpi() { + ssh -i _build_arm_steps/nopasskey pi@$PI_IP "$@" +} + +# harcoded test IP, you can change for yours for debuging. See main() +PI_IP=192.168.1.2 +# the installer script is used localy, no git clone else where. +YUNOHOST_INSTALL=../install_yunohostv2 +# the folder on the raspberrypi, where script are uploaded +YUNOHOST_REMOTE_DIR=/tmp/install_yunohost +# dummy password +PASSROOT='Free_money?yunomakeit' + +# used by main() See at the end. +ask_root_pass() { + echo "HINT: very good program to generate strong memorisable passwords: pwqgen" + echo "HINT: sudo apt-get install passwdqc" + echo -n "Enter a new root password for raspberrypi: " + read PASSROOT +} + +# helper to "scp" a local script to the raspberrypi +# Usage: scp_yunohost local_filename +scp_yunohost() { + if [[ -z "$1" ]] + then + echo "scp_yunohost: expect a local filename" + return 1 + fi + + if [[ ! -f "$1" ]] + then + echo "scp_yunohost: filename not found: '$1'" + return 1 + fi + + if [[ -z "$YUNOHOST_REMOTE_DIR" ]] + then + echo "scp_yunohost: error \$YUNOHOST_REMOTE_DIR is empty" + return 1 + fi + + local script="$1" + local scriptb="$(basename $script)" + + # no real scp, just wrap with sshpi + cat "$script" | \ + sshpi "mkdir -p $YUNOHOST_REMOTE_DIR && \ + cat > $YUNOHOST_REMOTE_DIR/$scriptb && \ + chmod a+x $YUNOHOST_REMOTE_DIR/$scriptb + " +} + +# helper, compute common remote_step script name so they can be skiped by do_step +make_step_file() { + local step_name="$1" + local step_file="yuno_step_${step_name}.sh" + echo $step_file +} + +# helper will create a local script and upload it to raspberrypi in $YUNOHOST_REMOTE_DIR +# Usage: create_remote_script $FUNCNAME "shell commands…" +create_remote_script() { + local step_file=$(make_step_file "$1") + local actions="$2" + local dst="_build_arm_steps/$step_file" + + echo '#!/bin/bash' > $dst + echo "# $1" >> $dst + echo "$actions" >> $dst + scp_yunohost $dst + + # the remote file on the raspi + echo $YUNOHOST_REMOTE_DIR/$step_file +} + +# ======================= ACTIONS - remote actions steps to be performed on the raspberrypi. + +init_sdcard_and_reboot() { + local actions=" +# fix locale warning +sudo sed -i -e '/\(en_US\|fr_FR\)\.UTF-8/ s/^# //' /etc/locale.gen +sudo locale-gen +# enlarge filesystem, we need more space to install yunohost +sudo raspi-config --expand-rootfs +echo 'rebooting raspberrypi…' +sudo reboot +" + create_remote_script $FUNCNAME "$actions" +} + +install_yunohostv2_on_sdcard() { + local actions=" +# change root password +echo 'root:$PASSROOT' | sudo chpasswd +# some packages +sudo apt-get -y install git +cat << ENDMSG +!!!!!!!!!!!!!!!!!!!!!!! sdcard builder !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Launching unattended install_yunohostv2 which will take some time to run… +You can watch using a new ssh connection to the raspberrypi. +By example issuing those commands: + cd $PWD + source 02_install_yunohost.sh + sshpi + tail -f /var/log/yunohost-installation.log +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +ENDMSG +# run yunohost installer unattended (scp previously with scp_yunohost) +cd /tmp/install_yunohost && sudo ./install_yunohostv2 -a +" + create_remote_script $FUNCNAME "$actions" +} + +finalize_yunohost() { + local actions=" +# uploaded modified or new config files to the raspberrypi +cd / +sudo tar xzf $YUNOHOST_REMOTE_DIR/etc.tgz +# yunohost-firstboot is an helper to cleanup and resizefs with srinked sdcard +# image +sudo chmod a+x /etc/init.d/yunohost-firstboot +sudo insserv /etc/init.d/yunohost-firstboot +cat << ENDMSG +================================================================================= +We are going to shutdown the raspberrypi now. +When it's done, the yunohost image is ready to be copied back on your comupter. +* Unplug raspberrypi +* remove the sdcard +* Go to next step! +================================================================================= +ENDMSG +# remove pi user, we will not be able to ssh connect anymore +# sudo userdel pi +sudo shutdown -h now +" + create_remote_script $FUNCNAME "$actions" +} + +reboot_pi() { + echo "${FUNCNAME}…" + sshpi "sudo reboot" +} + +# ======================= END ACTIONS + +# helper, simply visualy wait for raspberrypi to come up for ssh +# Usage: wait_raspberrypi || some_fail command +wait_raspberrypi() { + local max=30 + local n=1 + local up=false + while [[ $n -le $max ]] + do + sleep 1 + # remove redirect to /dev/null to debug + output=$(timeout 2 ssh -o "StrictHostKeyChecking=no" \ + -i _build_arm_steps/nopasskey pi@$PI_IP 'echo up' 2> /dev/null) + echo -n . + if [[ "$output" == 'up' ]] + then + up=true + break + fi + n=$(($n + 1)) + done + + if $up + then + echo up + return 0 + else + echo too_long + echo "something goes wrong for your raspberrypi or the timeout it too short" + echo "please retry" + return 1 + fi +} + +# wrapper, execute a step script on the raspberrypi or skip it +# Status: draft +do_step() { + local step=$1 + local step_file=$(make_step_file $step) + local remote_step + echo -n "$step: " + # skip if script already there + if [[ -e "_build_arm_steps/$step_file" ]] + then + echo "SKIPED" + return 1 + else + echo "RUNING" + remote_step=$(eval $step) + sshpi $remote_step + return 0 + fi +} + +# main script code, wrapped inside a function, so the whole script can also be +# sourced as a lib, for debug or unittesting purpose. +main() { + # you can comment the 2 lines, for debuging. Fix PI_IP with your dhcp IP. + PI_IP=$1 + ask_root_pass + + do_step init_sdcard_and_reboot + + wait_raspberrypi || return 1 + + scp_yunohost $YUNOHOST_INSTALL + NEED_REBOOT=false + do_step install_yunohostv2_on_sdcard && { NEED_REBOOT=true; } + + # backup the installation.log on the PC + sshpi "cat /var/log/yunohost-installation.log" > \ + _build_arm_steps/yunohost-installation.log + + $NEED_REBOOT && reboot_pi + + wait_raspberrypi || return 1 + + # was ./intsall_arm.sh + tar czf _build_arm_steps/etc.tgz etc + scp_yunohost _build_arm_steps/etc.tgz + do_step finalize_yunohost +} + +# sourcing code detection, if code is sourced for debug purpose, main is not executed. +[[ $0 != "$BASH_SOURCE" ]] && sourced=1 || sourced=0 +if [[ $sourced -eq 0 ]] +then + # pass positional argument as is + main "$@" +fi diff --git a/build_arm_image/03_copy_sdcard_to_img.sh b/build_arm_image/03_copy_sdcard_to_img.sh new file mode 100755 index 0000000..760fc61 --- /dev/null +++ b/build_arm_image/03_copy_sdcard_to_img.sh @@ -0,0 +1,157 @@ +#!/bin/bash +# +# Create the image file from the sdcard +# +# Usage: +# ./03_copy_sdcard_to_img.sh /dev/sdcard_device +# +# the resulting image will be stored in _build_arm_steps +# +# Status: prototype +# Licence: GPLv3 +# Author: sylvain303@github + +die() { + echo "$*" + exit 1 +} + +# helper, test if a shell program exists in PATH +test_tool() { + local cmd=$1 + if type $cmd > /dev/null + then + # OK + return 0 + else + die "tool missing: $cmd" + fi +} + +# helper, try to guess top device name +# /dev/sdp2 => /dev/sdp +# /dev/mmcblk0p1 => /dev/mmcblk0 +# just some regexp, no smart thing +get_top_device() { + local device="$1" + local regexp1='^/dev/sd[a-z]' + local regexp2='^/dev/mmcblk[0-9]' + + if [[ "$device" =~ $regexp1 ]] + then + #echo sd + device="${device/[0-9]/}" + elif [[ "$device" =~ $regexp2 ]] + then + #echo mmcblk + device="${device/p[0-9]/}" + fi + + echo "$device" +} + +# helper, umount the sdcard partition if any +umount_sdcard_partition() { + [[ -z "$SDCARD" ]] && { echo '$SDCARD is empty refusing to run'; return; } + local p + # search and replace all occurence of / by . + local pattern=${SDCARD////.} + pattern=${pattern/p[0-9]/} + for p in $(df | awk "/^$pattern/ { print \$1 }") + do + sudo umount $p + done + echo "done device for sdcard=${pattern//.//}" +} + +dd_from_sdcard() { + [[ -z "$SDCARD" ]] && { echo '$SDCARD is empty refusing to run'; return; } + [[ -z "$OUTPUT_IMG" ]] && { echo '$OUTPUT_IMG is empty refusing to run'; return; } + local count + if [[ ! -z "$1" ]] + then + count="count=$1" + fi + # ensure that sdcard partitions are unmounted with umount_sdcard_partition + sudo dd bs=16M if=$SDCARD of=_build_arm_steps/$OUTPUT_IMG $count +} + +test_all_tools() { + for t in $* + do + test_tool $t + done +} + +# debug, not used +mount_sdcard_data_partition() { + local part_data=2 + [[ ! -d _build_arm_steps/sdcard ]] && mkdir _build_arm_steps/sdcard + sudo mount ${SDCARD}p2 _build_arm_steps/sdcard +} + +# prototype, not used. Wanna test if I can d.d only used part of the partion, and fix it back on the PC +# not working yet, may be not achieved anyway… +get_used_partition_size() { + local start_offset=$(sudo fdisk -l /dev/mmcblk0 | awk '/Linux/ { print $2 * 512 }') + local used=$(df -B1 _build_arm_steps/sdcard | awk '/dev.mmcblk0p2/ { print $3 }') + + echo "start_offset=$start_offset" + echo "used =$used" + + local count=$(($start_offset + $used)) + echo "count =$count" + local div=$(($count / (16 * 1048576) )) + echo "16M =$(($count / (16 * 1048576) ))" + echo "verif =$(( ($div + 1) * (16 * 1048576) ))" +} + +shrink_img() { + echo "shrinking _build_arm_steps/$OUTPUT_IMG" + sudo ./autosizer.sh _build_arm_steps/$OUTPUT_IMG +} + +# functions call in that order, edit remove a long running step if already done or if +# you want to skip it, step states are saved in folder _build_arm_steps and skipped automatically. +STEPS=" +umount_sdcard_partition +dd_from_sdcard +shrink_img" + +# main wrapper, so the script can be sourced for debuging purpose or unittesting +main() { + # positional argument must be script argument. + # init + if [[ -z "$1" ]] + then + echo "argument 1 error: expecting sdcard_device" + exit 1 + fi + + test_all_tools dd sync sudo losetup + if [[ ! -d _build_arm_steps ]] + then + die "cannot find _build_arm_steps/ folder are you following build step?" + fi + # reading script argument + SDCARD=$(get_top_device "$1") + OUTPUT_IMG="$(date "+%Y-%m-%d")_yunohost_rasbian-jessie.img" + + # actions loop + for s in $STEPS + do + echo -n "$s: " + eval $s + done +} + +# sourcing code detection, if code is sourced for debug purpose, main is not executed. +[[ $0 != "$BASH_SOURCE" ]] && sourced=1 || sourced=0 +if [[ $sourced -eq 0 ]] +then + # pass positional argument as is + main "$@" +else + # just print STEPS so I can copy/paste to call them interactivly + echo $STEPS +fi diff --git a/build_arm_image/README.md b/build_arm_image/README.md new file mode 100644 index 0000000..f5ac192 --- /dev/null +++ b/build_arm_image/README.md @@ -0,0 +1,152 @@ +# Build your own yunohost image for Raspberry Pi + +This folder contains helper scripts to build an arm image of yunohost for raspberry. +The files here are for builder. They are not needed to install your yunohost, the purpose is to reproduce the .img. +Of course you can try the step exlained here, and you will get a fresh yunohost at the end. + +The folder etc/ structure maps debian OS folders, shell script here are helpers. +Files in etc/ subfolders will be copied on the sdcard when installation is finished. + +Those scripts are following the steps provided here: https://yunohost.org/#/build_arm_image + +### Notes: + +`01_create_sdcard.sh` can be used to copy raspbian image to a sdcard and stop here, without yunohost. +An ssh key is added to remote access pi@raspbian account without passphrase. + +Ex: +``` +ssh -i _build_arm_steps/nopasskey pi@DHCP_IP +``` + +Don't forget to at first: `sudo raspbi-config` + enlarge file-system to have full size sdcard for your raspberry. +(also accomplished by: `sudo raspi-config --expand-rootfs`) +Enjoy. + +## License +All the content here is distributed under [GPLv3](http://www.gnu.org/licenses/gpl-3.0.txt). + +## See also +* https://forum.yunohost.org/t/building-a-new-image-for-raspberry-debian-jessie-fr-en/1101/13 - discussion about building a new image for Raspberry Pi. +* http://build.yunohost.org/ - some build here + +## Files + +Description of the files available here. + +All step stripts are using your PC to store some files in the folder `_build_arm_steps/`. This folder will be created by `01_create_sdcard.sh`. You can wipe it, or remove selected script data form it, to redo a step. + +All step scripts are designed to run in this folder on your PC: + +~~~bash +git clone this_repos +cd path_to/build_arm_image/ +./01_create_sdcard.sh raspbian-jessie.zip /dev/mmcblk0 +# plug and boot raspberrypi +./02_install_yunohost.sh 192.168.1.200 +# unplug raspberrypi and connect the sdcard back to the PC +./03_copy_sdcard_to_img.sh /dev/mmcblk0 +~~~ + +### Steps + +Scripts are prefixed by a number which is the order they must be ran. + +#### 01_create_sdcard.sh + +Create a bootable image for raspbian. You have to download the .zip of the raspbian image. +([See:](https://www.raspberrypi.org/downloads/raspbian/) + +This script embeds sudo call for using `dd` to copy the raw image to the sdcard. +It will add an ssh key to `pi` default rasbian user in order to connect later to continue automated installation (See `02_install_yunohost.sh`) +The pi user will be removed at the end (Not yet, See #4). The ssh key-pair is generated only for you, in `_build_arm_steps/` + +Usage: + +~~~ +./01_create_sdcard.sh image_rasbian.zip /dev/device_to_sdcard +~~~ + +It takes some minutes to perform all the steps (~ 2m3.867s at last run). Be patient. + +Use commend like `df` or `lsblk` to find the name of your sdcard device. The script is taking care of umonting the partition if any. +It also guesses the disk's name if you gave a partition's name instead of entire disk device's name. i +(ex: /dev/mmcblk0p2 --> /dev/mmcblk0) + +BE CAREFULL not to wipe the wrong device! + +#### 02_install_yunohost.sh + +Should I say: you have to plug the new sdcard freshly created and boot the Raspberry PI pluged on the same network as your PC? + +The Raspberry has hopefully booted and is displaying a console's prompt, which looks like: + +~~~ +Raspbian GNU/Linux 8 raspberrypi tty1 + +raspberrypi login: +~~~ + +If DHCP has done its job well, you also have an IP address on the Raspberry PI console screen: + +~~~ +My IP address is 192.168.1.123 +~~~ + +Or what ever your DHCP is giving… + +Run (on the PC, not the raspberry): + +~~~bash +./02_install_yunohost.sh 192.168.1.123 +~~~ + +This step is quite long. It took ~24min on my Raspberry. Be patient. +A message will be displayed on the screen to explain how you can watch it if you want. + +If you got ssh `Host key verification failed.`, to fix it then: + +~~~bash +rm _build_arm_steps/yuno_step* +# retry +./02_install_yunohost.sh 192.168.1.123 +~~~ + +#### 03_copy_sdcard_to_img.sh + +When the build is finished, the Raspberry will shutdown. Unplug and insert the sdcard back in the computer. + +~~~bash +./03_copy_sdcard_to_img.sh /dev/sdcard_device +~~~ + +This will ask your sudo password and `dd` the resulting img from the sdcard back to your PC. +Stored in `_build_arm_steps/` folder. It takes arround 6min on my PC to copy an sdcard of 8G. + +The image will be automaticly shrinked to its minimal size using autosizer.sh. + + +#### test the image back + +You can test the resutling image back again with `01_create_sdcard.sh`. + +~~~bash +./01_create_sdcard.sh _build_arm_steps/newly_created_image.img /dev/sdcard_device +~~~ + +#### share + +You can zip, bzip2, or…, and share your freshly created yunohost image on the [forum](https://forum.yunohost.org). + +Enjoy! + +### Helper + +#### autosizer.sh + +Used on your PC to compact the dd image you will copy back after the rapsbian has been built. +This script requier root privilege to run and modify the local sdcard image. + + +## See also +* https://github.com/likeitneverwentaway/rpi_buildbot diff --git a/build_arm_image/autosizer.sh b/build_arm_image/autosizer.sh new file mode 100755 index 0000000..f7726bc --- /dev/null +++ b/build_arm_image/autosizer.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Automatic Image file resizer +# Written by SirLagz +# +# got from: http://sirlagz.net/2013/03/10/script-automatic-rpi-image-downsizer/ +# +# Usage: sudo autosizer.sh sdcard.img + +strImgFile=$1 + +if [[ ! $(whoami) =~ "root" ]]; then + echo "" + echo "**********************************" + echo "*** This should be run as root ***" + echo "**********************************" + echo "" + exit +fi + +if [[ -z $strImgFile ]]; then + echo "Usage: ./autosizer.sh " + exit +fi + +if [[ ! -e $strImgFile || ! $(file $strImgFile) =~ "DOS/MBR boot sector" ]]; then + echo "Error : Not an image file, or file doesn't exist" + exit +fi + +partinfo=`parted -m $strImgFile unit B print` +partnumber=`echo "$partinfo" | grep ext4 | awk -F: ' { print $strImgFile } '` +partstart=`echo "$partinfo" | grep ext4 | awk -F: ' { print substr($2,0,length($2)-1) } '` +loopback=`losetup -f --show -o $partstart $strImgFile` +e2fsck -f $loopback +minsize=`resize2fs -P $loopback | awk -F': ' ' { print $2 } '` +minsize=`echo $minsize+1000 | bc` +resize2fs -p $loopback $minsize +sleep 1 +losetup -d $loopback +partnewsize=`echo "$minsize * 4096" | bc` +newpartend=`echo "$partstart + $partnewsize" | bc` +# TODO: 2 is probably $partnumber +part1=`parted $strImgFile rm 2` +part2=`parted $strImgFile unit B mkpart primary $partstart $newpartend` +endresult=`parted -m $strImgFile unit B print free | tail -1 | awk -F: ' { print substr($2,0,length($2)-1) } '` +truncate -s $endresult $strImgFile diff --git a/build_arm_image/etc/init.d/yunohost-firstboot b/build_arm_image/etc/init.d/yunohost-firstboot new file mode 100755 index 0000000..78c9ac3 --- /dev/null +++ b/build_arm_image/etc/init.d/yunohost-firstboot @@ -0,0 +1,27 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: expand rootfs and Generates new ssh host keys on first boot +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: +# Short-Description: Generates new ssh host keys on first boot +# Description: Generatesapt-get --purge clean new ssh host keys on $ +### END INIT INFO +echo "Expanding rootfs ..." +raspi-config --expand-rootfs +echo "Generating new ssh keys ..." +# Delete SSH keys +rm -f /etc/ssh/ssh_host_* +yes | ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa +yes | ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa +yes | ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key -N '' -t ecdsa -b 521 +echo "Deleting logs ..." +find /var/log -type f -exec echo > {} \; +echo "Purging apt ..." +apt-get --purge clean +echo "Removing myself ..." +insserv -r /etc/init.d/yunohost-firstboot +rm -f /etc/init.d/yunohost-firstboot +echo "Rebooting ..." +reboot