255 lines
5.4 KiB
Bash
255 lines
5.4 KiB
Bash
SCRIPTPATH="$(dirname "$0")"
|
|
|
|
errormsg() {
|
|
echo "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
# Check deps
|
|
depcheck() {
|
|
for x in \
|
|
"dd" \
|
|
"fallocate" \
|
|
"sfdisk" \
|
|
"mkfs.vfat" \
|
|
"mkfs.ext4" \
|
|
"pvcreate" \
|
|
"vgcreate" \
|
|
"lvcreate" \
|
|
"vgchange" \
|
|
"mkfs.btrfs" \
|
|
"cryptsetup" \
|
|
"mktemp" \
|
|
"mount" \
|
|
"umount" \
|
|
"mkdir" \
|
|
"cat" \
|
|
"install" \
|
|
"apk" \
|
|
"bwrap" \
|
|
"patch" \
|
|
; do
|
|
if ! which "$x" >/dev/null 2>&1; then
|
|
errormsg "Missing dependency $x, exiting."
|
|
fi
|
|
done
|
|
}
|
|
|
|
splitargs() {
|
|
echo "$1" | sed 's/ /\n/g'
|
|
}
|
|
|
|
# BWRAP "chrooting"
|
|
wrapped() {
|
|
bwrap \
|
|
--new-session \
|
|
--die-with-parent \
|
|
--unshare-pid \
|
|
--unshare-uts \
|
|
--unshare-ipc \
|
|
--bind "$tmpdir" / \
|
|
--dev-bind /dev /dev \
|
|
--ro-bind /sys /sys \
|
|
--proc /proc \
|
|
--tmpfs /tmp \
|
|
--tmpfs /run \
|
|
-- $@
|
|
}
|
|
|
|
setup() {
|
|
: "${image:=nnd-rootfs}"
|
|
: "${arch:=x86_64}"
|
|
: "${kflav:=full}"
|
|
: "${svcs:=bundle.core bundle.net}"
|
|
: "${size:=1G}"
|
|
|
|
VGN="nnd"
|
|
LVN="rootlv"
|
|
CRYPT_DM="nnd-decrypt"
|
|
EFI_LABEL="nnd-efi"
|
|
BOOT_LABEL="nnd-boot"
|
|
CRYPT_LABEL="nnd-root-encrypted"
|
|
|
|
# Always clean up
|
|
trap cleanup_err INT TERM EXIT HUP
|
|
|
|
# Set up file as loopback
|
|
fallocate -v -l "$size" "$image"
|
|
if ! [ -r "$image" ]; then
|
|
errormsg "Something went wrong while preallocating sparse image"
|
|
fi
|
|
loopback="$(losetup --show -P -f "$image")"
|
|
if ! [ -r "$loopback" ]; then
|
|
errormsg "Something went wrong while setting up loopback image"
|
|
fi
|
|
|
|
# Create partition table
|
|
sfdisk "$loopback" <<-EOT
|
|
label: gpt
|
|
size=64MiB,name=$EFI_LABEL,type=U
|
|
size=512MiB,name=$BOOT_LABEL,type=L
|
|
type=L
|
|
EOT
|
|
|
|
# Format partitions
|
|
mkfs.vfat -n "$EFI_LABEL" "${loopback}p1"
|
|
mkfs.ext4 -L "$BOOT_LABEL" "${loopback}p2"
|
|
|
|
vgcreate "$VGN" "${loopback}p3"
|
|
lvcreate "$VGN" -n "$LVN" -l '100%FREE'
|
|
vgchange -a y "$VGN"
|
|
|
|
# Generate encryption keyfile
|
|
keyfile="$(mktemp "nnd-keyfile.XXXXXXXXX")"
|
|
touch "$keyfile"
|
|
chmod 400 "$keyfile"
|
|
chown root:root "$keyfile"
|
|
dd bs=512 count=4 if=/dev/urandom of="$keyfile" iflag=fullblock
|
|
|
|
# Create encrypted root
|
|
cryptsetup -q luksFormat "/dev/$VGN/$LVN" "$keyfile"
|
|
cryptsetup -q open -d "$keyfile" "/dev/$VGN/$LVN" "$CRYPT_DM"
|
|
|
|
mkfs.btrfs -L "$ROOT_LABEL" "/dev/mapper/$CRYPT_DM"
|
|
|
|
# Set up chroot
|
|
tmpdir="$(mktemp -d "nnd-image.XXXXXXXXX")"
|
|
if [ -z "$tmpdir" ]; then
|
|
errormsg "Something went wrong during working directory preparation, bailing out"
|
|
fi
|
|
mount -v -t btrfs "/dev/mapper/$CRYPT_DM" "$tmpdir"
|
|
|
|
mkdir -p "$tmpdir/boot"
|
|
mount -v -t ext4 "${loopback}p2" "$tmpdir/boot"
|
|
|
|
mkdir -p "$tmpdir/boot/efi"
|
|
mount -v -t vfat "${loopback}p1" "$tmpdir/boot/efi"
|
|
|
|
# Copy decryption key to well-known path
|
|
cp -v "$keyfile" "$tmpdir"/crypto_keyfile.bin
|
|
|
|
install -Dm444 "$SCRIPTPATH"/repositories "$tmpdir"/etc/apk/repositories
|
|
# Set up bootstrap rootfs
|
|
apk add \
|
|
-v \
|
|
--initdb \
|
|
--allow-untrusted \
|
|
--root "$tmpdir" \
|
|
--repositories-file "$tmpdir/etc/apk/repositories" \
|
|
--arch "$arch" \
|
|
lfsbase \
|
|
busybox \
|
|
nnd-signkey \
|
|
alpine-keys \
|
|
apk-tools
|
|
|
|
## Add btrfs and lvm to required initrd modules
|
|
# TODO: Only append and don't replace
|
|
install -Dm444 "$SCRIPTPATH"/mkinitfs.conf "$tmpdir"/etc/mkinitfs/mkinitfs.conf
|
|
|
|
## Provide temporary override for grub, TODO: provide our own grub cfgs eventually
|
|
install -Dm444 <(
|
|
cat <<-EOF
|
|
GRUB_DISTRIBUTOR="nnd"
|
|
GRUB_TIMEOUT=2
|
|
GRUB_DISABLE_SUBMENU=y
|
|
GRUB_DISABLE_RECOVERY=true
|
|
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3"
|
|
GRUB_CMDLINE_LINUX="cryptroot=/dev/mapper/$VGN-$LVN cryptdm=$CRYPT_DM cryptdiscards=yes cryptkey=yes rootfstype=btrfs root=/dev/mapper/$CRYPT_DM $kextparam"
|
|
EOF
|
|
) "$tmpdir"/etc/default/grub
|
|
|
|
# Set up default resolv.conf (in case no DNS server is configured via DHCP or otherwise)
|
|
## TODO: Maybe distribute this via packages?
|
|
install -Dm644 "$SCRIPTPATH"/resolv.conf "$tmpdir"/etc/resolv.conf
|
|
|
|
# Set up rest of rootfs
|
|
wrapped apk add -v \
|
|
nnd \
|
|
linux-"$kflav" \
|
|
nnd-s6-linux-init-default \
|
|
nnd-s6-services \
|
|
grub-efi \
|
|
iproute2 \
|
|
bcnm@edge \
|
|
mdevd \
|
|
mdev-conf \
|
|
utmps \
|
|
findmnt \
|
|
dosfstools \
|
|
e2fsprogs \
|
|
btrfs-progs \
|
|
cryptsetup \
|
|
net-predictable \
|
|
lvm2
|
|
|
|
# Add net-predictable to mdev.conf
|
|
(cd "$tmpdir" && patch -p0 < "$SCRIPTPATH"/mdev.patch)
|
|
|
|
# Install grub to ESP
|
|
wrapped grub-install --removable --efi-directory /boot/efi --boot-directory /boot
|
|
|
|
# Unlock root login
|
|
wrapped passwd -ud root
|
|
}
|
|
|
|
addpkg() {
|
|
wrapped apk add -v $@
|
|
}
|
|
|
|
addtty() {
|
|
for tty in $@; do
|
|
[ -z "$tty" ] && continue
|
|
cp -rv "$tmpdir"/usr/share/nnd/s6/dist/rc/getty.tty1 "$tmpdir"/etc/s6/rc/getty."$tty"
|
|
sed -i 's/tty1/'"$tty"'/g' "$tmpdir"/etc/s6/rc/getty."$tty"/run
|
|
|
|
wrapped nnd-s6 default bundle.tty
|
|
wrapped nnd-s6 custom bundle.tty
|
|
touch "$tmpdir"/etc/s6/rc/bundle.tty/contents.d/getty."$tty"
|
|
done
|
|
}
|
|
|
|
addsvc() {
|
|
# Set-up services
|
|
for bundle in $@; do
|
|
[ -z "$bundle" ] && continue
|
|
touch "$tmpdir"/etc/s6/rc/default/contents.d/"$bundle"
|
|
done
|
|
wrapped nnd-s6 dist
|
|
wrapped nnd-s6 generate
|
|
}
|
|
|
|
pack() {
|
|
# Set service set as default
|
|
wrapped nnd-s6 swap
|
|
cleanup
|
|
}
|
|
|
|
cleanup_err() {
|
|
cleanup
|
|
rm -v "$image"
|
|
}
|
|
|
|
cleanup() {
|
|
# Disable traps and cleanup
|
|
trap '' INT TERM EXIT HUP
|
|
umount -Rv "$tmpdir"
|
|
rmdir -v "$tmpdir"
|
|
rm -v "$keyfile"
|
|
cryptsetup -q close "$CRYPT_DM"
|
|
vgchange -a n "$VGN"
|
|
losetup -d "$loopback"
|
|
}
|
|
|
|
addsshkey() {
|
|
mkdir -vp "$tmpdir"/root/.ssh
|
|
cat "$1" >> "$tmpdir"/root/.ssh/authorized_keys
|
|
}
|
|
|
|
custom() {
|
|
echo "You are now entering your image's shell."
|
|
echo "Any customizations made here will remain in the image."
|
|
echo "Upon exit, the image will be packed."
|
|
wrapped sh || true # Handle graceful exit
|
|
}
|