Skip to content

Instantly share code, notes, and snippets.

@j0ju
Created June 7, 2020 10:39
Show Gist options
  • Save j0ju/593a499aaae73c3ca112fa32fac389ed to your computer and use it in GitHub Desktop.
Save j0ju/593a499aaae73c3ca112fa32fac389ed to your computer and use it in GitHub Desktop.
current root to nvme with efi and systemd
#!/bin/sh
set -e
TGT=/dev/nvme0n1
WAIT=5
VG=nvme
LV_ROOT_SIZE=150G
#LV_ROOT_SIZE="$(df -h / | tail -n 1 | awk '{print $2}')"
KEY_FILE=/tmp/.nvme.key
warn() { echo "W: $*" >&2; }
info() { echo "I: $*"; }
msg() { echo "I: $*"; }
error() { echo "E: $*" >&2; }
die() { error "$@"; exit 1; }
if [ "$1" = --force ]; then
warn "will copy and move root to $TGT in $WAIT seconds"
for _ in $(seq 1 $WAIT); do
sleep 1
echo -n .
done
echo
else
error "not copying root (/dev/mmcblk0) to $TGT"
info "use the --force, Luke"
echo
lsblk
echo
exit 1
fi
if mountpoint /mnt > /dev/null 2>&1; then
die "filesystem is mounted at /mnt"
fi
if [ ! -r "$KEY_FILE" ]; then
die "KEY_FILE ($KEY_FILE) does not exist"
fi
if grep "$TGT" /proc/mounts >&2; then
die "$TGT is mounted"
fi
CLEANUP_TRAPS=
cleanup_trap() {
local rs=$?
local p
msg "TRAP: exitcode $rs"
for p in $CLEANUP_TRAPS; do
msg " TRAP: execute $p"
"$p"
done
exit $rs
}
trap cleanup_trap EXIT KILL TERM INT QUIT STOP USR1 HUP USR2
msg "partition disk ROOTDEV=$TGT"
sgdisk $TGT -Z
PART_MD5="$(md5sum /proc/partitions | cut -f1 -d' ')"
sgdisk $TGT -Z \
-n 15::+128M -t 15:ef00 \
-n 14::+2G -t 14:8300 \
-n 1:: -t 1:8e00 \
# eo sgdisk
# check if the partition table has not been changed
if [ "$PART_MD5" = "$(md5sum /proc/partitions | cut -f1 -d' ')" ]; then
error "partition disk failed or reloading partition table failed"
exit 1
fi
msg "evaluate settings"
ROOTDEV="$TGT"
case "$ROOTDEV" in
*[0-9] ) _PD_=p ;;
* ) _PD_= ;;
esac
EFIPART="${ROOTDEV}$_PD_"15
BOOTPART="${ROOTDEV}$_PD_"14
ROOTPART="${ROOTDEV}$_PD_"1
wipefs -af $EFIPART $ROOTPART
msg "create crypt"
wipefs -af $ROOTPART
cryptsetup luksFormat $ROOTPART -d $KEY_FILE -q --type luks2
CRYPT_UUID="$(blkid -o value -s UUID $ROOTPART)"
msg "open crypt crypt-$CRYPT_UUID"
cleanup_close_crypt() {
if [ -b /dev/mapper/crypt-$CRYPT_UUID ]; then
cryptsetup close /dev/mapper/crypt-$CRYPT_UUID
fi
}
CLEANUP_TRAPS="cleanup_close_crypt $CLEANUP_TRAPS"
cryptsetup luksOpen UUID=$CRYPT_UUID crypt-$CRYPT_UUID -d $KEY_FILE
ROOTPART=/dev/mapper/crypt-$CRYPT_UUID
msg "create system VG ($VG @ $ROOTPART)"
cleanup_deactivate_vg() {
vgchange -an $VG
}
CLEANUP_TRAPS="cleanup_deactivate_vg $CLEANUP_TRAPS"
wipefs -af $ROOTPART
pvcreate "$ROOTPART"
vgcreate $VG "$ROOTPART"
msg "create root LV ($VG/root $LV_ROOT_SIZE)"
case "$LV_ROOT_SIZE" in
*G | *M | *T ) lvcreate -n root -L $LV_ROOT_SIZE -W n $VG ;;
*%* ) lvcreate -n root -l $LV_ROOT_SIZE -W n $VG ;;
default ) die "unknown size specifier $LV_ROOT_SIZE, exit" ;;
esac
ROOTPART=/dev/$VG/root
# helper for /mnt
cleanup_umount_mnt() {
if mountpoint /mnt > /dev/null; then
mount | grep -Eo " /mnt[^ ]* " | sort -ur | while read mnt; do
umount "$mnt" || :
done
fi
}
CLEANUP_TRAPS="cleanup_umount_mnt $CLEANUP_TRAPS"
# helper for /.btrfs
cleanup_umount_dot_btrfs() {
if mountpoint /.btrfs > /dev/null; then
umount /.btrfs
fi
}
CLEANUP_TRAPS="cleanup_umount_dot_btrfs $CLEANUP_TRAPS"
msg "format EFI boot partition ($EFIPART - /boot/efi)"
wipefs -af $EFIPART
mkfs.vfat "$EFIPART" -F 32 -n EFI
msg "copy EFI partition"
mount $EFIPART /mnt
rsync /boot/efi/ /mnt -a -x
umount /mnt
msg "format boot partition ($BOOTPART - /boot)"
wipefs -af $BOOTPART
mkfs.ext4 $BOOTPART
msg "copy boot partition"
mount $BOOTPART /mnt
rsync /boot/ /mnt -a -x
umount /mnt
msg "format system volume"
wipefs -af $ROOTPART
mkfs.btrfs -d single -m single $ROOTPART
msg "mount system volume"
mount -o relatime,compress=zstd $ROOTPART /mnt
set -x
msg "copy btrfs subvolume structure and data"
mount -o relatime,compress=zstd /.btrfs
btrfs sub list /.btrfs | awk '{print $NF}' | sort | while read sub; do
# only copy data and rootfs/*-current*
case "$sub" in
rootfs | rootfs/*-current | rootfs/*-current/* ) : ;; # OK
rootfs/* ) continue ;; # do NOT copy this
# rest is okay
esac
subpath="/mnt/${sub}"
mkdir -p "${subpath%/*}"
btrfs sub create "/mnt/$sub"
done
ROOT_SUB_VOL="$( < /proc/mounts sed -nre '/ \/ / s@^.*subvol=([^, ]+).*$@\1@ p' )"
#ROOT_SUB_VOL="$( btrfs sub list /.btrfs | grep -o 'rootfs/.*-current$' | head -n 1 )"
echo $ROOT_SUB_VOL | while read sub; do
msg "copy current rootfs sub volume $sub"
sub="/$sub"
rsync -aH /.btrfs/$sub /mnt/${sub%/*}
rsync -aHx /dev /mnt/${sub}
done
btrfs sub list /.btrfs | grep -Eo '[^ ]+$' | grep -v ^rootfs | sort -r | while read sub; do
msg "copy sub volume $sub"
sub="/$sub"
rsync -aH /.btrfs/$sub /mnt/${sub%/*}
done
umount /mnt
msg "assemble / file system"
mount -o relatime,compress=zstd,subvol=$ROOT_SUB_VOL $ROOTPART /mnt
mount $BOOTPART /mnt/boot
mount $EFIPART /mnt/boot/efi
mount -o rbind /dev /mnt/dev
chroot /mnt mount -t proc proc /proc
chroot /mnt mount -t sysfs sysfs /sys
mount -o bind /tmp /mnt/tmp
mount -o bind /mnt/tmp /mnt/var/tmp
mount -o bind /run /mnt/run
msg "update crypttab to new UUID"
UUID_OLD="$(cat /etc/crypttab | grep -oE "UUID=[^ ]+" | cut -f2 -d=)"
sed -i -e "s/$UUID_OLD/$CRYPT_UUID/g" /mnt/etc/crypttab
msg "update fstab to new UUID for /"
UUID_OLD="$(grep " / " /etc/fstab | grep -oE "UUID=[^ ]+" | cut -f2 -d=)"
sed -i -e "s/$UUID_OLD/$(blkid -o value -s UUID $ROOTPART)/g" /mnt/etc/fstab
msg "update fstab to new UUID for /boot"
UUID_OLD="$(grep " /boot " /etc/fstab | grep -oE "UUID=[^ ]+" | cut -f2 -d=)"
sed -i -e "s/$UUID_OLD/$(blkid -o value -s UUID $BOOTPART)/g" /mnt/etc/fstab
msg "update fstab to new UUID for /boot/efi"
UUID_OLD="$(grep " /boot/efi " /etc/fstab | grep -oE "UUID=[^ ]+" | cut -f2 -d=)"
sed -i -e "s/$UUID_OLD/$(blkid -o value -s UUID $EFIPART)/g" /mnt/etc/fstab
msg "generate new SSH host keys"
for f in /mnt/etc/ssh/ssh_host_*_key; do
t="${f#*ssh_host_}"
t="${t%_key}"
if ssh-keygen -P "" -t "$t" -f "$f".new -C "$(hostname)" -m pem; then
mv -f "$f".new "$f"
mv -f "$f".new.pub "$f".pub
fi
done
for type in rsa dsa:dss ecdsa; do
openssh_type="${type%:*}"
dropbear_type="${type#*:}"
openssh_key="/mnt/etc/ssh/ssh_host_${openssh_type}_key"
dropbear_key="/mnt/etc/dropbear/dropbear_${dropbear_type}_host_key"
rm -f "$dropbear_key"
if [ -f "$openssh_key" ]; then
/usr/lib/dropbear/dropbearconvert openssh dropbear ${openssh_key} ${dropbear_key} 1> /dev/null 2>&1 || \
warn "converting ssh host key for $openssh_type to ${dropbear_key##*/} FAILED" && \
msg "converted ssh host key for $openssh_type to ${dropbear_key##*/}"
fi
done
chroot /mnt grub-install $ROOTDEV
chroot /mnt update-initramfs -kall -u
chroot /mnt update-grub
chroot /mnt etckeeper commit "new root device $ROOTDEV"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment