Skip to content

Instantly share code, notes, and snippets.

@foucault
Created September 6, 2017 11:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save foucault/1ec7c9c49730999078ad8d0f15476792 to your computer and use it in GitHub Desktop.
Save foucault/1ec7c9c49730999078ad8d0f15476792 to your computer and use it in GitHub Desktop.
#!/bin/bash
ARCH="x86_64"
TARGET="/tmp/alpinefs"
ROOTGZ="/tmp/alpine-rootfs.tar.gz"
MIRROR="http://dl-cdn.alpinelinux.org/alpine"
echoerr() {
printf "%s\n" "$*" >&2;
}
if [[ "$#" == "0" ]]; then
echoerr "Usage: $0 RELEASE [DEVICE]"
echoerr "Omitting DEVICE will set alpine rootfs up, but WILL NOT burn the image"
exit 1
fi
RELEASE=$1
USBDEV=$2
MAJOR_RELEASE=$(echo $RELEASE | awk -F"." '{ print "v"$1"."$2 }')
RELURL="${MIRROR}/${MAJOR_RELEASE}/releases/${ARCH}/alpine-minirootfs-${RELEASE}-${ARCH}.tar.gz"
RELSHA=$(wget --quiet "http://dl-cdn.alpinelinux.org/alpine/${MAJOR_RELEASE}/releases/${ARCH}/alpine-minirootfs-${RELEASE}-${ARCH}.tar.gz.sha256" -O - | awk ' { print $1 } ')
ISOURL="${MIRROR}/${MAJOR_RELEASE}/releases/${ARCH}/alpine-standard-${RELEASE}-${ARCH}.iso"
ISOSHA=$(wget --quiet "http://dl-cdn.alpinelinux.org/alpine/${MAJOR_RELEASE}/releases/${ARCH}/alpine-standard-${RELEASE}-${ARCH}.iso.sha256" -O - | awk '{ print $1 }')
# Check if unpacking is already finished
if [[ ! -f "${TARGET}/unpack-ok" ]]; then
echo "Downloading alpine rootfs"
wget -q --show-progress -c "${RELURL}" -O "${ROOTGZ}"
if [[ "$?" != "0" ]]; then
echoerr "Download failed; aborting"
exit 1
fi
DLRELSHA=$(sha256sum "${ROOTGZ}" | awk '{ print $1 }')
shopt -s nocasematch
if [[ "${RELSHA}" != "${DLRELSHA}" ]]; then
echoerr "SHA256 checksum of rootfs failed; aborting"
exit 1
else
echo "rootfs SHA256 checked out"
fi
shopt -u nocasematch
echo "Unpacking alpine rootfs to ${TARGET}"
if [[ ! -d "${TARGET}" && -f "${TARGET}" ]]; then
echoerr "Target \"${TARGET}\" is not a directory"
exit 1
else
mkdir ${TARGET}
fi
tar xfz "${ROOTGZ}" -C "${TARGET}"
#if [[ "$?" != "0" ]]; then
# echoerr "Unpacking rootfs failed; aborting"
# exit 1
#fi
touch "${TARGET}/unpack-ok"
else
echo "Rootfs already unpacked; continuing..."
fi
if [[ ! -f "${TARGET}/config-ok" ]]; then
echo "Adjusting inittab"
sed '/tty[0-9]:/ s/^/#/' -i "${TARGET}/etc/inittab"
printf 'console::respawn:/sbin/getty 38400 console\n' >> "${TARGET}/etc/inittab"
echo "Adding mirror"
printf '%s/%s/main\n' "${MIRROR}" "${MAJOR_RELEASE}" >| "${TARGET}/etc/apk/repositories"
touch "${TARGET}/config-ok"
fi
echo "Initial configuration finished"
echo "Updating rootfs to the latest version"
systemd-nspawn -D "${TARGET}" /sbin/apk update
systemd-nspawn -D "${TARGET}" /sbin/apk upgrade
echo "Downloading alpine ${ARCH} ISO"
wget -q --show-progress -c "${ISOURL}" -O "${TARGET}/alpine-${ARCH}.iso"
DLISOSHA=$(sha256sum "${TARGET}/alpine-${ARCH}.iso" | awk '{ print $1 }')
shopt -s nocasematch
if [[ "${ISOSHA}" != "${DLISOSHA}" ]]; then
echoerr "SHA256 checksum of rootfs failed; aborting"
exit 1
else
echo "ISO SHA256 checked out"
fi
shopt -u nocasematch
if [[ ! -d "${TARGET}/iso" ]]; then
mkdir "${TARGET}/iso"
fi
echo "Adding required packages"
systemd-nspawn -D "${TARGET}" /sbin/apk add alpine-conf parted syslinux dosfstools e2fsprogs p7zip
echo "Extracting ISO"
if [[ ! -f "${TARGET}/iso-extract-ok" ]]; then
# Do not extract any MBR info, there will be recreated by setup-bootable anyway
systemd-nspawn -D "${TARGET}" /usr/bin/7z x -x!'[BOOT]/*' -o'/iso' "/alpine-${ARCH}.iso"
if [[ "$?" != "0" ]]; then
echoerr "Failed to unzip iso; aborting"
exit 1
else
touch "${TARGET}/iso-extract-ok"
fi
else
echo "ISO is already extracted"
fi
echo "Enabling console output to /dev/ttyS0 for syslinux.cfg"
# Get the APPEND line that has the options
APPENDLINE=$(tail -n1 "${TARGET}/iso/boot/syslinux/syslinux.cfg")
# Split them up into an arry
OPTS=($APPENDLINE)
NEWAPPEND=""
# Reassemble them but drop any existing "console=" parts
for o in "${OPTS[@]}"; do
if [[ ${o} =~ "console=" ]]; then
echo "Ignoring existing console line"
else
NEWAPPEND=$(printf "%s %s" "${NEWAPPEND}" "${o}")
fi
done
# Add the "console=" bit
NEWAPPEND=$(printf "%s console=ttyS0,115200" "${NEWAPPEND}")
# Replace last line in syslinux.cfg with the new one
head -n -1 "${TARGET}/iso/boot/syslinux/syslinux.cfg" >| "${TARGET}/iso/boot/syslinux/syslinux.new.cfg"
mv "${TARGET}/iso/boot/syslinux/syslinux.new.cfg" "${TARGET}/iso/boot/syslinux/syslinux.cfg"
echo "${NEWAPPEND}" | sed -e 's/^[[:space:]]*//' >> "${TARGET}/iso/boot/syslinux/syslinux.cfg"
if [[ "${USBDEV}" != "" ]]; then
if [[ ! -b "${USBDEV}" ]]; then
echoerr "${USBDEV} does not appear to be a block device; aborting"
exit 1
fi
echo "Preparing partitions on ${USBDEV}"
systemd-nspawn --bind ${USBDEV} -D "${TARGET}" /usr/sbin/parted ${USBDEV} --script \
mklabel msdos \
mkpart primary fat32 1MiB 100% \
set 1 boot on
if [[ "$?" != "0" ]]; then
echoerr "Preparting partitions on ${USBDEV} failed; aborting"
fi
echo "Formatting ${USBDEV}1"
systemd-nspawn --bind ""${USBDEV}"" --bind "${USBDEV}1" -D "${TARGET}" /sbin/mkdosfs -F32 "${USBDEV}1"
if [[ "$?" != "0" ]]; then
echoerr "mkdosfs -F32 ${USBDEV}1 failed; aborting"
exit 1
fi
echo "Running /sbin/setup-bootable /iso ${USBDEV}1"
systemd-nspawn --bind ${USBDEV} --bind "${USBDEV}1" -D "${TARGET}" /sbin/setup-bootable /iso "${USBDEV}1"
if [[ "$?" != "0" ]]; then
echoerr "setup-bootable failed; inspect ${USBDEV} manually"
exit 1
fi
else
echoerr "No device provided; nothing more to do"
fi
echo "Script finished!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment