initial commit
This commit is contained in:
commit
1b63fd18b7
6
.gitignore
vendored
Executable file
6
.gitignore
vendored
Executable file
@ -0,0 +1,6 @@
|
||||
*~
|
||||
.DS_Store
|
||||
*.swp
|
||||
*.lock*
|
||||
.void-mklive
|
||||
void-pbp.img.xz
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sebastian Hugentobler <sebastian@vanwa.ch>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
79
README.md
Normal file
79
README.md
Normal file
@ -0,0 +1,79 @@
|
||||
# Install Scripts for Void Linux on Pinebook Pro
|
||||
Before using either of the scripts in this repository, read through them to
|
||||
clearly understand what they do. They are very opinionated and specifically
|
||||
written to cater to my own needs (for example the use of `sudo`, other people
|
||||
might have different setups). It is, however, easy to change things around.
|
||||
|
||||
By default, the `bootstrap` script creates a minimal installation on the emmc storage,
|
||||
with full disk encryption via lvm on luks. Two volumes `swap` and `root` are created,
|
||||
the latter is formatted with an xfs filesystem. Additionally one user is created
|
||||
(with access to sudo via the wheel group) and keymap, hostname and timezone get set.
|
||||
|
||||
This gets you to a booting system, going on from there is out of scope here
|
||||
as there are many ways to do that (for myself, I use `stow` to set up everything).
|
||||
|
||||
An important thing to keep in mind is that not all commands in the `bootstrap`
|
||||
script are idempotent, that makes it all the more important to understand what they
|
||||
do and to be sure to backup all important data.
|
||||
|
||||
# Scripts
|
||||
## mk_pbp_img
|
||||
Create a live image to boot void linux on the pinebook pro. Needs to be run on an
|
||||
existing void linux system (docker might be possible with a working buildx and some adaptions with the mounting of filesystems).
|
||||
|
||||
A copy of the [void-mklive](https://github.com/void-linux/void-mklive.git)
|
||||
repository is downloaded next to the script into `.void-mklive` and used for
|
||||
building the image.
|
||||
|
||||
The script assumes it is running on an `x86_64` architecture, if that is not the case,
|
||||
it needs to be changed (this applies to the use of `qemu-aarch64-static` to get a chroot).
|
||||
|
||||
The following tools need to be accessible in `PATH`:
|
||||
|
||||
- git
|
||||
- make
|
||||
- qemu-aarch64-static
|
||||
- sudo
|
||||
- xz
|
||||
|
||||
If there is an argument provided to the script, it is treated as the folder to where
|
||||
the compressed image is written, if no argument is given, the current working
|
||||
directory is used.
|
||||
|
||||
After a successful build, the finished image can be found in the directory described
|
||||
above with a filename of `void-pbp.img.xz`
|
||||
|
||||
Write it to a microSD card as such:
|
||||
- `xz -d < void-pbp.img.xz | sudo dd of=/dev/mmcblk0 bs=4M status=progress`
|
||||
- `sudo sync`
|
||||
|
||||
Be ***very*** careful to get the parameter for `of` right, otherwise you can destroy your system.
|
||||
|
||||
MicroSD cards can be fickle, it sometimes is helpful to not take them out immediately, even after running `sync`.
|
||||
If booting from the card hangs, write the image again onto it or use a different card.
|
||||
|
||||
## bootstrap
|
||||
Install void linux to the internal mmc storage of the pinebook pro or use it for some
|
||||
maintenance task.
|
||||
|
||||
Run it in either of two ways:
|
||||
|
||||
### non-interactive
|
||||
`bootstrap full`
|
||||
|
||||
Run a full installation, this will overwrite all data on the storage.
|
||||
|
||||
Runs the `full_install` command internally.
|
||||
|
||||
### interactive
|
||||
`bootstrap`
|
||||
|
||||
Run `help` to get a list of commands you can run and quit interactive mode
|
||||
with typing `exit`.
|
||||
|
||||
A useful thing to do here is the `repair` command. Sets up all the needed filesystems
|
||||
and opens a chroot.
|
||||
|
||||
Again, it is highly recommended to read what the respective commands do and to adapt
|
||||
them to your own needs.
|
||||
|
367
bootstrap
Executable file
367
bootstrap
Executable file
@ -0,0 +1,367 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
CONFIG="$(mktemp)"
|
||||
declare -rgA default_values=(
|
||||
["wifi_if"]="wlan0"
|
||||
["install_dev"]="/dev/mmcblk2"
|
||||
["repo"]="https://alpha.de.repo.voidlinux.org/current/aarch64"
|
||||
["arch"]="aarch64"
|
||||
["timezone"]="Europe/Zurich"
|
||||
["keymap"]="uk"
|
||||
["locale"]="en_US.UTF-8 UTF-8"
|
||||
)
|
||||
|
||||
get_value() {
|
||||
local white=$'\e[97m'
|
||||
local nocolour=$'\e[0m'
|
||||
|
||||
local var_name="$1"
|
||||
local prompt="$2"
|
||||
local secure=""
|
||||
|
||||
if [ -n "$3" ]; then
|
||||
secure="s"
|
||||
fi
|
||||
|
||||
. "$CONFIG"
|
||||
if [ -z "${!var_name}" ]; then
|
||||
local def_val="${default_values[$var_name]}"
|
||||
read -${secure}rp "$white$prompt [$def_val]:$nocolour " value
|
||||
|
||||
echo "export $var_name=\"${value:-$def_val}\"" >> "$CONFIG"
|
||||
. "$CONFIG"
|
||||
fi
|
||||
|
||||
echo "${!var_name}"
|
||||
|
||||
}
|
||||
|
||||
network() {
|
||||
local wifi_if
|
||||
wifi_if="$(get_value "wifi_if" "wifi interface name")"
|
||||
|
||||
ip link set "$wifi_if" up
|
||||
|
||||
local wifi_ssid
|
||||
wifi_ssid="$(get_value "wifi_ssid" "wifi ssid")"
|
||||
local wifi_pw
|
||||
wifi_pw="$(get_value "wifi_pw" "wifi password" 1)"
|
||||
|
||||
wpa_supplicant -B -i "$wifi_if" -c <(wpa_passphrase "$wifi_ssid" "$wifi_pw")
|
||||
sv restart dhcpcd
|
||||
}
|
||||
|
||||
datetime() {
|
||||
local datetime
|
||||
datetime="$(get_value "datetime" "date and time now (like 2020-01-01 12:00)")"
|
||||
|
||||
date "+%Y--%m-%d %T" --set="$datetime"
|
||||
hwclock --systohc
|
||||
}
|
||||
|
||||
partition() {
|
||||
local install_dev
|
||||
install_dev="$(get_value "install_dev" "installation device")"
|
||||
|
||||
if [ ! -e "$install_dev" ]; then
|
||||
echo "device node $install_dev does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sfdisk --force "$install_dev" << EOF
|
||||
label: gpt
|
||||
|
||||
start=16MiB size=512MiB, type=bc13c2ff-59e6-4262-a352-b275fd6f7172
|
||||
type=b921b045-1df0-41c3-af44-4c6f280d3fae
|
||||
EOF
|
||||
|
||||
mkfs.vfat -F32 "$install_dev"p1
|
||||
|
||||
}
|
||||
|
||||
create_luks() {
|
||||
local install_dev
|
||||
install_dev="$(get_value "install_dev" "installation device")"
|
||||
|
||||
cryptsetup luksFormat "$install_dev"p2
|
||||
}
|
||||
|
||||
open_luks() {
|
||||
local install_dev
|
||||
install_dev="$(get_value "install_dev" "installation device")"
|
||||
|
||||
cryptsetup open "$install_dev"p2 void
|
||||
}
|
||||
|
||||
create_lvm() {
|
||||
pvcreate /dev/mapper/void
|
||||
vgcreate void /dev/mapper/void
|
||||
|
||||
lvcreate -L 4G void -n swap
|
||||
lvcreate -l 100%FREE void -n root
|
||||
}
|
||||
|
||||
open_lvm() {
|
||||
vgchange --activate y
|
||||
}
|
||||
|
||||
make_filesystems() {
|
||||
mkswap -L SWAP /dev/void/swap
|
||||
mkfs.xfs -f -L ROOT /dev/void/root
|
||||
}
|
||||
|
||||
mount_filesystems() {
|
||||
local install_dev
|
||||
install_dev="$(get_value "install_dev" "installation device")"
|
||||
|
||||
mount /dev/void/root /mnt
|
||||
mkdir -p /mnt/boot
|
||||
mount "$install_dev"p1 /mnt/boot
|
||||
|
||||
swapon /dev/void/swap
|
||||
}
|
||||
|
||||
install_basesystem() {
|
||||
local repo
|
||||
repo="$(get_value "repo" "package repository")"
|
||||
local arch
|
||||
arch="$(get_value "arch" "installation architecture")"
|
||||
|
||||
XBPS_ARCH=$arch xbps-install -S -y -r /mnt -R "$repo" base-system pinebookpro-base dracut lvm2 cryptsetup sudo stow << 'EOF'
|
||||
y
|
||||
EOF
|
||||
cp /etc/resolv.conf /mnt/etc/
|
||||
}
|
||||
|
||||
mount_special_filesystems() {
|
||||
mount --rbind /sys /mnt/sys && mount --make-rslave /mnt/sys
|
||||
mount --rbind /dev /mnt/dev && mount --make-rslave /mnt/dev
|
||||
mount --rbind /proc /mnt/proc && mount --make-rslave /mnt/proc
|
||||
mount --rbind /tmp /mnt/tmp && mount --make-rslave /mnt/tmp
|
||||
}
|
||||
|
||||
set_fstab() {
|
||||
local install_dev
|
||||
install_dev="$(get_value "install_dev" "installation device")"
|
||||
|
||||
local boot_uuid="$(blkid | grep ${install_dev}p1 | awk '{print $2}')"
|
||||
cat >/mnt/etc/fstab <<EOF
|
||||
tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0
|
||||
$boot_uuid /boot vfat defaults 0 0
|
||||
/dev/void/root / xfs defaults 0 0
|
||||
/dev/void/swap swap swap defaults 0 0
|
||||
EOF
|
||||
}
|
||||
|
||||
set_boot_scr() {
|
||||
local install_dev
|
||||
install_dev="$(get_value "install_dev" "installation device")"
|
||||
|
||||
local boot_txt="/mnt/boot/boot.txt"
|
||||
local boot_scr="/mnt/boot/boot.scr"
|
||||
local boot_txt_mine="/mnt/boot/boot.txt.mine"
|
||||
|
||||
local root_uuid="$(blkid | grep ${install_dev}p2 | awk '{print $2}' | sed 's/"//g')"
|
||||
|
||||
sed -i "s|root=PARTUUID=|root=/dev/void/root rd.auto=1 cryptdevice=${root_uuid}:lvm|g" "$boot_txt"
|
||||
cp "$boot_txt" "$boot_txt_mine"
|
||||
|
||||
mkimage -A arm -O linux -T script -C none -n "boot script" -d "$boot_txt" "$boot_scr"
|
||||
}
|
||||
|
||||
set_sudoers() {
|
||||
sed -i 's/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g' /mnt/etc/sudoers
|
||||
}
|
||||
|
||||
set_user() {
|
||||
local user_name
|
||||
user_name="$(get_value "user_name" "username")"
|
||||
|
||||
local user_pw
|
||||
user_pw="$(get_value "user_pw" "user password")"
|
||||
|
||||
chroot /mnt /bin/env -i \
|
||||
user_name="$user_name" \
|
||||
user_pw="$user_pw" \
|
||||
/bin/bash <<"EOT"
|
||||
useradd --groups wheel --create-home --shell /bin/bash --user-group $user_name
|
||||
echo "$user_name:$user_pw" | chpasswd
|
||||
EOT
|
||||
}
|
||||
|
||||
set_base_conf() {
|
||||
local timezone
|
||||
timezone="$(get_value "timezone" "timezone")"
|
||||
|
||||
local keymap
|
||||
keymap="$(get_value "keymap" "keymap")"
|
||||
|
||||
local hostname
|
||||
hostname="$(get_value "hostname" "hostname")"
|
||||
|
||||
local locale
|
||||
locale="$(get_value "locale" "locale")"
|
||||
|
||||
echo "$locale" >> /etc/default/libc-locales
|
||||
|
||||
chroot /mnt /bin/env -i \
|
||||
timezone="$timezone" \
|
||||
/bin/bash <<"EOT"
|
||||
xbps-reconfigure -f glibc-locales
|
||||
ln -sf /usr/share/zoneinfo/$timezone /etc/localtime
|
||||
EOT
|
||||
|
||||
echo "$hostname" > /mnt/etc/hostname
|
||||
|
||||
cat >/mnt/etc/hosts <<EOF
|
||||
#
|
||||
# /etc/hosts: static lookup table for host names
|
||||
#
|
||||
|
||||
#<ip-address> <hostname.domain.org> <hostname>
|
||||
127.0.0.1 localhost.localdomain localhost $hostname
|
||||
::1 localhost.localdomain localhost ip6-localhost $hostname
|
||||
|
||||
# End of file
|
||||
EOF
|
||||
|
||||
cat >/mnt/etc/rc.conf <<EOF
|
||||
# /etc/rc.conf - system configuration for void
|
||||
|
||||
# Set the host name.
|
||||
#
|
||||
# NOTE: it's preferred to declare the hostname in /etc/hostname instead:
|
||||
# - echo myhost > /etc/hostname
|
||||
#
|
||||
#HOSTNAME="void-live"
|
||||
|
||||
# Set RTC to UTC or localtime.
|
||||
#HARDWARECLOCK="UTC"
|
||||
|
||||
# Set timezone, availables timezones at /usr/share/zoneinfo.
|
||||
TIMEZONE="$timezone"
|
||||
|
||||
# Keymap to load, see loadkeys(8).
|
||||
KEYMAP="$keymap"
|
||||
|
||||
# Console font to load, see setfont(8).
|
||||
#FONT="lat9w-16"
|
||||
|
||||
# Console map to load, see setfont(8).
|
||||
#FONT_MAP=
|
||||
|
||||
# Font unimap to load, see setfont(8).
|
||||
#FONT_UNIMAP=
|
||||
|
||||
# Amount of ttys which should be setup.
|
||||
#TTYS=
|
||||
EOF
|
||||
}
|
||||
|
||||
tidy_up() {
|
||||
umount -R /mnt
|
||||
}
|
||||
|
||||
full_install() {
|
||||
datetime
|
||||
network
|
||||
partition
|
||||
create_luks
|
||||
open_luks
|
||||
create_lvm
|
||||
open_lvm
|
||||
make_filesystems
|
||||
mount_filesystems
|
||||
install_basesystem
|
||||
mount_special_filesystems
|
||||
set_fstab
|
||||
set_boot_scr
|
||||
set_sudoers
|
||||
set_user
|
||||
set_base_conf
|
||||
tidy_up
|
||||
}
|
||||
|
||||
repair() {
|
||||
open_luks
|
||||
open_lvm
|
||||
mount_filesystems
|
||||
mount_special_filesystems
|
||||
|
||||
chroot /mnt bash
|
||||
tidy_up
|
||||
}
|
||||
|
||||
help() {
|
||||
cat << EOF
|
||||
the following commands are available:
|
||||
|
||||
datetime
|
||||
network
|
||||
partition
|
||||
create_luks
|
||||
open_luks
|
||||
create_lvm
|
||||
open_lvm
|
||||
make_filesystems
|
||||
mount_filesystems
|
||||
install_basesystem
|
||||
mount_special_filesystems
|
||||
set_fstab
|
||||
set_boot_scr
|
||||
set_sudoers
|
||||
set_user
|
||||
set_base_conf
|
||||
full_install
|
||||
repair
|
||||
tidy_up
|
||||
help
|
||||
|
||||
ensure to understand what they are doing before using them
|
||||
EOF
|
||||
}
|
||||
|
||||
commands=(
|
||||
"datetime"
|
||||
"network"
|
||||
"partition"
|
||||
"create_luks"
|
||||
"open_luks"
|
||||
"open_lvm"
|
||||
"make_filesystems"
|
||||
"mount_filesystems"
|
||||
"set_fstab"
|
||||
"set_boot_scr"
|
||||
"set_sudoers"
|
||||
"set_user"
|
||||
"set_base_conf"
|
||||
"full_install"
|
||||
"repair"
|
||||
"tidy_up"
|
||||
"help"
|
||||
)
|
||||
|
||||
cmd_loop() {
|
||||
local cmd
|
||||
|
||||
while [[ "$cmd" != "exit" ]]; do
|
||||
read -rp "${white}>$nocolour " cmd
|
||||
|
||||
if [[ " ${commands[@]} " =~ " ${cmd} " ]]; then
|
||||
$cmd
|
||||
else
|
||||
if [ "$cmd" != "exit" ]; then
|
||||
echo "no such command"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
if [ "$1" == "full" ]; then
|
||||
full_install
|
||||
else
|
||||
cmd_loop
|
||||
fi
|
107
mk_pbp_img
Executable file
107
mk_pbp_img
Executable file
@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
ROOT_DIR="$(dirname "$(readlink -f "$0")")"
|
||||
OUT_DIR="${1:-$(pwd)}"
|
||||
|
||||
TMP_DIR="$(mktemp --directory)"
|
||||
TMP_DIR_PFS="$(mktemp --directory)"
|
||||
TMP_DIR_MOUNT="$(mktemp --directory)"
|
||||
|
||||
TOOLS=(git make sudo qemu-aarch64-static xz)
|
||||
|
||||
GIT_REPO=https://github.com/void-linux/void-mklive.git
|
||||
GIT_REV=f71eb4bb81004b50884011ef5e0d00f99bc2892a
|
||||
GIT_DIR="$ROOT_DIR/.void-mklive"
|
||||
|
||||
cleanup() {
|
||||
cleanup_mounts
|
||||
sudo rm -r "$TMP_DIR" "$TMP_DIR_PFS" "$TMP_DIR_MOUNT"
|
||||
}
|
||||
|
||||
cleanup_mounts() {
|
||||
sudo losetup -D
|
||||
sudo umount --recursive "$TMP_DIR_MOUNT" || true
|
||||
}
|
||||
|
||||
check_tools() {
|
||||
for tool in ${TOOLS[@]}; do
|
||||
if ! command -v "$tool" &> /dev/null
|
||||
then
|
||||
echo "$tool could not be found"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
init_void_mklive() {
|
||||
if [ ! -d "$GIT_DIR" ]; then
|
||||
git clone "$GIT_REPO" "$GIT_DIR"
|
||||
cd "$GIT_DIR" && git checkout "$GIT_REV"
|
||||
fi
|
||||
|
||||
cd "$GIT_DIR"
|
||||
|
||||
if [ "$(git rev-parse HEAD)" != "$GIT_REV" ]; then
|
||||
git fetch
|
||||
git checkout "$GIT_REV"
|
||||
fi
|
||||
|
||||
make
|
||||
sed -i 's/ROOTFS_TARBALL#void-/ROOTFS_TARBALL#*void-/g' "$GIT_DIR/mkimage.sh"
|
||||
}
|
||||
|
||||
build_img() {
|
||||
local rootfs_file="$TMP_DIR/rootfs.tar.xz"
|
||||
local platformfs_file="$TMP_DIR/void-pinebookpro-PLATFORMFS.tar.xz"
|
||||
local img="$TMP_DIR/void-pbp.img"
|
||||
|
||||
cd "$GIT_DIR"
|
||||
|
||||
sudo ./mkrootfs.sh -o "$rootfs_file" aarch64
|
||||
sudo ./mkplatformfs.sh -p "dracut lvm2 cryptsetup" -o "$platformfs_file" pinebookpro "$rootfs_file"
|
||||
sudo ./mkimage.sh -B 256MiB -o "$img" "$platformfs_file"
|
||||
|
||||
sudo xz --decompress --stdout "$img.xz" > "$img"
|
||||
local loop_dev="$(sudo losetup --show -f -P "$img")"
|
||||
|
||||
if [ ! -z "$DISCOVER_DEV" ]; then # needed if building inside a docker container
|
||||
local partitions=$(lsblk --raw --output "MAJ:MIN" --noheadings ${loop_dev} | tail -n +2)
|
||||
counter=1
|
||||
for i in $partitions; do
|
||||
local maj=$(echo $i | cut -d: -f1)
|
||||
local min=$(echo $i | cut -d: -f2)
|
||||
if [ ! -e "${loop_dev}p${counter}" ]; then mknod ${loop_dev}p${counter} b $maj $min; fi
|
||||
counter=$((counter + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
sudo mount "$loop_dev"p2 "$TMP_DIR_MOUNT"
|
||||
sudo mount "$loop_dev"p1 "$TMP_DIR_MOUNT"/boot
|
||||
|
||||
sudo cp "$ROOT_DIR/bootstrap" "$TMP_DIR_MOUNT/usr/bin/bootstrap"
|
||||
sudo chmod +x "$TMP_DIR_MOUNT/bin/bootstrap"
|
||||
|
||||
sudo cp "$(which qemu-aarch64-static)" "$TMP_DIR_MOUNT/usr/bin/"
|
||||
|
||||
sudo chroot "$TMP_DIR_MOUNT" qemu-aarch64-static /bin/bash <<"EOT"
|
||||
ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default/
|
||||
EOT
|
||||
|
||||
sudo rm "$TMP_DIR_MOUNT/usr/bin/qemu-aarch64-static"
|
||||
cleanup_mounts
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
xz --threads=0 --compress --stdout "$img" > "$OUT_DIR/$(basename $img.xz)"
|
||||
|
||||
echo "built pinebookpro image: $OUT_DIR/$(basename $img.xz)"
|
||||
}
|
||||
|
||||
trap cleanup 0 SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
|
||||
|
||||
check_tools
|
||||
init_void_mklive
|
||||
build_img
|
Loading…
Reference in New Issue
Block a user