2023-06-11 18:02:38 +07:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
# this step requires either root access or access to fuse
|
|
|
|
# nix builder doesnt have access to either
|
|
|
|
# i could run this in a vm, but that's slow as fuck because i'm building this on x86_64-linux
|
|
|
|
# usage: image.sh [path to image.nix output]
|
|
|
|
|
|
|
|
set -euxo pipefail
|
|
|
|
|
2023-06-24 07:12:11 +07:00
|
|
|
which zstd || exit 1
|
2023-06-11 18:02:38 +07:00
|
|
|
|
|
|
|
userspace="$(which lklfuse >/dev/null && echo -n 1 || echo -n)"
|
|
|
|
use_rsync="$(which rsync >/dev/null && echo -n 1 || echo -n)"
|
|
|
|
function Mount() {
|
|
|
|
if [[ "$userspace" == "1" ]]; then
|
|
|
|
if [[ "${4-}" == "ro" ]]; then
|
|
|
|
lklfuse -o "type=$1" -o "$4" "$2" "$3"
|
|
|
|
elif [ -n "${4-}" ]; then
|
|
|
|
lklfuse -o "type=$1" -o "opts=$4" "$2" "$3"
|
|
|
|
else
|
|
|
|
lklfuse -o "type=$1" "$2" "$3"
|
|
|
|
fi
|
|
|
|
elif [ -n "${4-}" ]; then
|
|
|
|
sudo -A mount -t "$1" -o "loop,$4" "$2" "$3"
|
|
|
|
else
|
|
|
|
sudo -A mount -t "$1" -o loop "$2" "$3"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function run() {
|
|
|
|
if [[ "$userspace" == "1" ]]; then
|
|
|
|
"$@"
|
|
|
|
else
|
|
|
|
sudo -A "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function cpr() {
|
|
|
|
if [[ "$use_rsync" == "1" ]]; then
|
|
|
|
run rsync -a --info=progress2 "$1/" "$2/"
|
|
|
|
else
|
|
|
|
run cp -rv "$1"/* "$2/"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
if [ -z "$1" ]; then
|
|
|
|
echo "missing argument"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
rootfs="$1/rootfs.ext4"
|
2023-06-24 09:49:57 +07:00
|
|
|
template="$1/template.btrfs.zst"
|
|
|
|
image="$1/image.img.zst"
|
2023-06-11 18:02:38 +07:00
|
|
|
boot="$1/boot"
|
|
|
|
|
|
|
|
metadata0="$(head -n1 "$1/metadata")"
|
|
|
|
metadata1="$(head -n2 "$1/metadata" | tail -n1)"
|
|
|
|
if [ -z "$metadata0" ] || [ -z "$metadata1" ] || [[ "$metadata0" == "$metadata1" ]]; then
|
|
|
|
echo "invalid metadata"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
tmp=$(mktemp -d)
|
2023-06-24 09:49:57 +07:00
|
|
|
cp "$template" "$tmp/template.btrfs.zst"
|
|
|
|
cp "$image" "$tmp/image.img.zst"
|
2023-06-11 18:02:38 +07:00
|
|
|
template="$tmp/template.btrfs"
|
|
|
|
image="$tmp/image.img"
|
2023-06-24 09:49:57 +07:00
|
|
|
unzstd --rm "$template.zst"
|
|
|
|
unzstd --rm "$image.zst"
|
2023-06-11 18:02:38 +07:00
|
|
|
chmod +w "$template" "$image"
|
|
|
|
|
|
|
|
function cleanup {
|
|
|
|
run umount "$rootfs" || echo -n
|
|
|
|
run umount "$tmp/out" || echo -n
|
|
|
|
rm -rf "$tmp"
|
|
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p "$tmp/rootfs" "$tmp/out"
|
|
|
|
Mount ext4 "$rootfs" "$tmp/rootfs" ro
|
|
|
|
rootfs="$tmp/rootfs"
|
|
|
|
Mount btrfs "$template" "$tmp/out"
|
2023-06-24 07:12:11 +07:00
|
|
|
cpr "$boot" "$tmp/out/@boot"
|
2023-06-11 18:02:38 +07:00
|
|
|
run umount "$tmp/out"
|
|
|
|
Mount btrfs "$template" "$tmp/out" "compress=zstd:15"
|
|
|
|
run cp -v "$rootfs/nix-path-registration" "$tmp/out/@/"
|
2023-06-12 17:07:38 +07:00
|
|
|
# those two are the only dirs needed for impermanence in boot stage 1
|
2023-06-24 07:12:11 +07:00
|
|
|
run mkdir -p "$tmp/out/@/var/lib/nixos"
|
|
|
|
run mkdir -p "$tmp/out/@/var/log"
|
|
|
|
|
|
|
|
# secrets, we don't want to pass them via the store
|
|
|
|
run mkdir -p "$tmp/out/@/secrets"
|
2023-12-25 04:13:25 +07:00
|
|
|
run cp -v /secrets/nixos/wireguard-key "$tmp/out/@/secrets/"
|
2023-06-24 07:12:11 +07:00
|
|
|
run chmod -R 000 "$tmp/out/@/secrets"
|
|
|
|
|
2023-06-11 18:02:38 +07:00
|
|
|
cpr "$rootfs/nix" "$tmp/out/@nix"
|
|
|
|
|
|
|
|
run umount "$rootfs"
|
|
|
|
run umount "$tmp/out"
|
|
|
|
|
|
|
|
dd conv=notrunc if="$template" of="$image" seek="$metadata0"
|
|
|
|
|
2023-06-24 09:49:57 +07:00
|
|
|
zstd -f --rm --compress "$image" -o ./image.img.zst
|