mirror of
https://github.com/YunoHost/install_script.git
synced 2024-09-03 20:06:25 +02:00
Merge 453702f51f
into 0b060404fc
This commit is contained in:
commit
093b6cf6c7
8 changed files with 882 additions and 0 deletions
|
@ -1,5 +1,7 @@
|
||||||
# YunoHost installation scripts
|
# 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
|
## Context
|
||||||
|
|
||||||
The script `install_yunohost` will install [YunoHost](https://yunohost.org/) on a Debian system.
|
The script `install_yunohost` will install [YunoHost](https://yunohost.org/) on a Debian system.
|
||||||
|
|
2
build_arm_image/.gitignore
vendored
Normal file
2
build_arm_image/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
_build_arm_steps
|
||||||
|
.*.swp
|
244
build_arm_image/01_create_sdcard.sh
Executable file
244
build_arm_image/01_create_sdcard.sh
Executable file
|
@ -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
|
252
build_arm_image/02_install_yunohost.sh
Executable file
252
build_arm_image/02_install_yunohost.sh
Executable file
|
@ -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
|
157
build_arm_image/03_copy_sdcard_to_img.sh
Executable file
157
build_arm_image/03_copy_sdcard_to_img.sh
Executable file
|
@ -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
|
152
build_arm_image/README.md
Normal file
152
build_arm_image/README.md
Normal file
|
@ -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
|
46
build_arm_image/autosizer.sh
Executable file
46
build_arm_image/autosizer.sh
Executable file
|
@ -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 <Image File>"
|
||||||
|
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
|
27
build_arm_image/etc/init.d/yunohost-firstboot
Executable file
27
build_arm_image/etc/init.d/yunohost-firstboot
Executable file
|
@ -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
|
Loading…
Add table
Reference in a new issue