aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2015-09-15 14:42:37 +0200
committerJakob Odersky <jodersky@gmail.com>2015-09-15 14:42:37 +0200
commit8c4d00155e324c774af19f137d805ca920219a6d (patch)
treef95840a8a640cecb30f454741ddb6f48fea20756
downloadpistrap-debian-8c4d00155e324c774af19f137d805ca920219a6d.tar.gz
pistrap-debian-8c4d00155e324c774af19f137d805ca920219a6d.tar.bz2
pistrap-debian-8c4d00155e324c774af19f137d805ca920219a6d.zip
initial commit
-rw-r--r--README.md49
-rwxr-xr-xpistrap-debian236
2 files changed, 285 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ac8df11
--- /dev/null
+++ b/README.md
@@ -0,0 +1,49 @@
+# pistrap-debian
+
+Create a bootable Debian SD card for the RaspberryPi 2.
+
+Pistrap-debian is a shell script that partitions and mounts an SD card and subsequently creates a bootable root file system for the RaspberryPi 2.
+
+The root filesystem is that of a minimal Debian Jessie distribution with the kernel pulled in from the Raspbian archive. Furthermore, hostnames, timezones, passwords, networking and SSH are setup as to remove the need of any additional screen-and-keyboard configuration.
+
+## Requirements
+Debian-based host system with the following packages:
+
+- qemu-user-static
+- parted
+
+The resulting image is only compatible with ARMv7 processors (armhf Debian distribution), hence the requirement of a RaspberryPi 2.
+
+## Usage
+```
+Usage: pistrap-debian [OPTION]... DEVICE
+
+Create a bootable image for a RaspberryPi 2 on DEVICE.
+
+Options:
+ --force Don't ask for any confirmations.
+ --mirror=<$MIRROR> Use a debian mirror, such as "fr" or "ch"
+ --hostname=<$HOSTNAME> Use a given hostname for the device.
+ --timezone=<$TIMEZONE> Set timezone data as listed in /usr/share/zoneinfo
+ --wpa-essid=<$WPA_ESSID> Use a given wireless ESSID. Sets up wireless networking.
+ --wpa-psk=<$WPA_PSK> Use a given WPA pre-shared key.
+ --password=<$ROOT_PASWORD> Set the given root password.
+ --ssh-key=<$SSH_KEY> Add the given SSH key to root's authorized_keys file. If invalid, password login will be enabled.
+ --root-fs=<$ROOTFS> Use given directory as mount point during installation.
+```
+
+## Caveats
+- The script is very fragile. Should anything unexpected happen during the installation process, the script will abort and manual unmounting will be required.
+Also, the script must be run on an unmounted SD card and, in case of interruption, cannot resume.
+
+## Origin
+The commands run by the script are adapted from two documents on creating bootable file systems:
+
+- USB Armory, https://github.com/inversepath/usbarmory/wiki/Preparing-a-bootable-microSD-image, by Andrea Barisani and others
+
+- Stock Debian Jessie on the Raspberry Pi 2, https://0xstubs.org/stock-debian-jessie-on-the-raspberry-pi-2/, by Michael Laß
+
+## Copying
+Copyright (c) 2015 Jakob Odersky
+
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation.
diff --git a/pistrap-debian b/pistrap-debian
new file mode 100755
index 0000000..eefaa9a
--- /dev/null
+++ b/pistrap-debian
@@ -0,0 +1,236 @@
+#!/bin/bash
+set -e
+
+# Variables set through command-line arguments
+# the assigned values are used as defaults if no matching argument is provided
+FORCE=0
+MIRROR=""
+HOSTNAME="pi"
+TIMEZONE="UTC"
+WPA_ESSID=""
+WPA_PSK=""
+ROOT_PASSWORD="toor"
+SSH_KEY="$HOME/.ssh/id_rsa.pub"
+
+# Paths for installation
+DEVICE=/dev/nonexisting
+PARTITION1="$DEVICE"p1
+PARTITION2="$DEVICE"p2
+ROOTFS=/mnt/pi
+
+print_usage() {
+ cat 1>&2 <<EOF
+Usage: $0 [OPTION]... DEVICE
+Create a bootable image for a RaspberryPi 2 on DEVICE.
+
+Options:
+ --force Don't ask for any confirmations.
+ --mirror=<$MIRROR> Use a debian mirror, such as "fr" or "ch"
+ --hostname=<$HOSTNAME> Use a given hostname for the device.
+ --timezone=<$TIMEZONE> Set timezone data as listed in /usr/share/zoneinfo
+ --wpa-essid=<$WPA_ESSID> Use a given wireless ESSID. Sets up wireless networking.
+ --wpa-psk=<$WPA_PSK> Use a given WPA pre-shared key.
+ --password=<$ROOT_PASWORD> Set the given root password.
+ --ssh-key=<$SSH_KEY> Add the given SSH key to root's authorized_keys file. If invalid, password login will be enabled.
+ --root-fs=<$ROOTFS> Use given directory as mount point during installation.
+EOF
+
+}
+
+
+# Process options
+while [ $# -gt 1 ]
+do
+ case "$1" in
+ -f|--force)
+ FORCE=1
+ ;;
+ --mirror=*)
+ MIRROR=."${1#*=}"
+ ;;
+ --hostname=*)
+ HOSTNAME="${1#*=}"
+ ;;
+ --timezone=*)
+ TIMEZONE="${1#*=}"
+ ;;
+ --wpa-essid=*)
+ WPA_ESSID="${1#*=}"
+ ;;
+ --wpa-psk=*)
+ WPA_PSK="${1#*=}"
+ ;;
+ --password=*)
+ ROOT_PASSWORD="${1#*=}"
+ ;;
+ --ssh-key=*)
+ SSH_KEY="${1#*=}"
+ ;;
+ --root-fs=*)
+ ROOTFS="${1#*=}"
+ ;;
+ *)
+ echo "Unknown argument: $1" 1>&2
+ exit 1
+ esac
+ shift
+done
+
+# Process last argument, the device to use
+if [ -z "$1" ] || [ "$1" = -h ] || [ "$1" = --help ]; then
+ print_usage
+ exit 1
+fi
+if [ ! -e "$1" ]; then
+ echo "Device not found: $1" 1>&2
+ exit 1
+fi
+if [ ! -b "$1" ]; then
+ echo "Specified device is not a block device: $1" 1>&2
+ exit 1
+fi
+DEVICE="$1"
+PARTITION1="$DEVICE"p1
+PARTITION2="$DEVICE"p2
+
+# Check environment
+if [ "$EUID" != 0 ]; then
+ echo "This script must be run as root." 1>&2
+ exit 1
+fi
+
+# Argument processing and enivronment check are done at this point
+# Start with actual script
+
+# Setup partitions on SD card
+partition() {
+ parted "$DEVICE" --script mklabel msdos &&
+ parted "$DEVICE" --script mkpart primary fat32 1M 200M &&
+ parted "$DEVICE" --script mkpart primary ext4 200M 100% &&
+ mkfs.vfat -F 32 "$PARTITION1" &&
+ mkfs.ext4 "$PARTITION2"
+}
+
+mountrootfs() {
+ mkdir "$ROOTFS" &&
+ mount "$PARTITION2" "$ROOTFS" &&
+
+ mkdir "$ROOTFS"/boot &&
+ mount "$PARTITION1" "$ROOTFS"/boot
+}
+
+mkrootfs() {
+ # Create initial debian filesystem
+ qemu-debootstrap --arch=armhf \
+ --include=ssh,sudo,ntpdate,fake-hwclock,openssl,ca-certificates,vim,nano,cryptsetup,lvm2,locales,less,cpufrequtils,wireless-tools,wpasupplicant \
+ jessie \
+ "$ROOTFS" \
+ "http://ftp${MIRROR}.debian.org/debian/"
+
+ # Set package configuration to use raspberrypi.org archive for kernel package
+ cat > "$ROOTFS"/etc/apt/sources.list <<EOF
+deb http://ftp${MIRROR}.debian.org/debian jessie main contrib non-free
+deb http://ftp${MIRROR}.debian.org/debian jessie-updates main contrib non-free
+deb http://security.debian.org jessie/updates main contrib non-free
+deb http://archive.raspberrypi.org/debian wheezy main
+EOF
+
+ cat > "$ROOTFS"/etc/apt/preferences.d/raspberrypi <<EOF
+Package: *
+Pin: origin archive.raspberrypi.org
+Pin-Priority: 1
+
+Package: raspberrypi-bootloader
+Pin: origin archive.raspberrypi.org
+Pin-Priority: 1000
+
+Package: libraspberrypi0
+Pin: origin archive.raspberrypi.org
+Pin-Priority: 1000
+
+Package: libraspberrypi-bin
+Pin: origin archive.raspberrypi.org
+Pin-Priority: 1000
+EOF
+
+ chroot "$ROOTFS" /bin/sh -c "wget https://archive.raspberrypi.org/debian/raspberrypi.gpg.key -O - | apt-key add -"
+
+ chroot "$ROOTFS" apt-get update
+
+ # libraspberrypi-bin contains kernel, firmware and some binary tools
+ chroot "$ROOTFS" apt-get install locales dbus openssh-server dosfstools libraspberrypi-bin
+
+ cat > "$ROOTFS"/boot/config.txt <<EOF
+gpu_mem=128
+start_file=start_x.elf
+fixup_file=fixup_x.dat
+EOF
+
+ # Set up network
+ if [ -n "$WPA_ESSID" ]; then
+ cat > "$ROOTFS"/etc/network/interfaces.d/wlan0 <<EOF
+auto wlan0
+iface wlan0 inet dhcp
+ wpa-essid "$WPA_ESSID"
+ wpa-psk "$WPA_PSK"
+EOF
+ chmod 660 "$ROOTFS"/etc/network/interfaces.d/wlan0
+ chroot "$ROOTFS" apt-get install firmware-realtek
+ else
+ cat > "$ROOTFS"/etc/network/interfaces.d/eth0 <<EOF
+auto eth0
+iface eth0 inet dhcp
+EOF
+ fi
+
+ # Set up file mounts
+ cat > "$ROOTFS"/etc/fstab <<EOF
+UUID=$(blkid -s UUID -o value "$PARTITION1") /boot vfat noatime 0 2
+UUID=$(blkid -s UUID -o value "$PARTITION2") / ext4 noatime 0 1
+tmpfs /tmp tmpfs defaults 0 0
+EOF
+
+ # Set timezone
+ echo "$TIMEZONE" > "$ROOTFS"/etc/timezone
+ ln -sf /usr/share/zoneinfo/"$TIMEZONE" "$ROOTFS"/etc/localtime
+
+ # Set host configuration
+ echo "$HOSTNAME" > "$ROOTFS"/etc/hostname
+ sed -i "/^127.0.0.1/ s/\$/ $HOSTNAME/" "$ROOTFS"/etc/hosts
+ sed -i "/^::1/ s/\$/ $HOSTNAME/" > "$ROOTFS"/etc/hosts
+
+ # Login options
+ chroot "$ROOTFS" /bin/sh -c "echo root:$ROOT_PASSWORD | chpasswd"
+
+ if [ -e "$SSH_KEY" ]; then
+ mkdir "$ROOTFS"/root/.ssh
+ chmod 600 "$ROOTFS"/root/.ssh
+ cat "$SSH_KEY" >> "$ROOTFS"/root/.ssh/authorized_keys
+ chmod 600 "$ROOTFS"/root/.ssh/authorized_keys
+ sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' "$ROOTFS"/etc/ssh/sshd_config
+ echo "Success: SSH password login was disabled! Use the key in $SSH_KEY to login." 1>&2
+ else
+ sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/g' "$ROOTFS"/etc/ssh/sshd_config
+ echo "Warning: no SSH key found, SSH password login has been enabled for root! Please enable key-login only as soon as possible." 1>&2
+ fi
+}
+
+umountrootfs() {
+ rm -f "$ROOTFS"/usr/bin/qemu-arm-static
+ umount "$ROOTFS"/boot
+ umount "$ROOTFS"
+ rm -r "$ROOTFS"
+}
+
+
+if [ "$FORCE" != 1 ]; then
+ echo "WARNING: The following operations may have destructive consequences." 1>&2
+ echo "Partition device $DEVICE and create bootable root file system on $ROOTFS" 1>&2
+ read -p "Continue? [Y,n] " yn
+ if [ "$yn" != "Y" ] && [ "$yn" != "y" ]; then
+ echo "Aborting." 1>&2
+ exit 1
+ fi
+fi
+
+partition && mountrootfs && mkrootfs && umountrootfs