From 81e0e0b826ebffdee7d809ee4dff1338af7692e1 Mon Sep 17 00:00:00 2001 From: Ian Kelling Date: Sun, 8 May 2016 00:28:07 -0700 Subject: [PATCH] fix various arch issues With 9 disks, the kernel cmdline was ~2100 chars, but it's limited to 2048. So, modified the encrypt hook to use the kernel args less. Now it's down to ~800 chars. --- arch-init | 65 ++----------- arch-init-chroot | 52 ++++------ arch-init-remote | 18 +++- arch-iso-init.sh | 18 ++++ arch-pxe | 12 +-- encrypt | 129 +++++++++++++++++++++++++ encrypt.upstream | 139 +++++++++++++++++++++++++++ fai-redep | 34 +++++-- fai/config/distro-install-common/end | 2 +- fai/config/hooks/partition.DEFAULT | 9 +- pxe-server | 3 +- 11 files changed, 368 insertions(+), 113 deletions(-) create mode 100644 arch-iso-init.sh create mode 100644 encrypt create mode 100644 encrypt.upstream diff --git a/arch-init b/arch-init index d1c5542..a9e5d68 100755 --- a/arch-init +++ b/arch-init @@ -17,7 +17,7 @@ if [[ $hostname == tp ]]; then ROOTPW="$TPPASS" fi -(( $# >= 2 )) || { echo "error: need 2 arguments"; exit 1; } +(( $# >= 1 )) || { echo "$0: error: need 1 or 2 arguments"; exit 1; } mv /root/devbyid /usr/bin @@ -39,7 +39,6 @@ export -f ifclass for x in $(bash 50-host-classes); do export CLASS_$x=true done -export CLASS_TWO_DISK=true export LUKS_DIR=/root/luks export HOSTNAME=$hostname export DISTRO=arch @@ -47,6 +46,7 @@ chmod +x partition.DEFAULT export PARTITION_PROMPT=true +# to be idempotent if we fail after partitioning already_partitioned=true mount_out=$(mount) for dir in /mnt{,/home,/boot,/q}; do @@ -69,6 +69,7 @@ export rootn=1 export bootn=3 export swapn=2 export BOOT_DEVICE +export ROOT_PARTITIONS sed -ri "/^crypt_dev_\S+$rootn /d" /tmp/fai/crypttab if ! $already_partitioned; then @@ -84,64 +85,18 @@ cp /root/luks/host-$hostname /mnt/crypto_keyfile.bin chmod 600 /mnt/crypto_keyfile.bin -shopt -s extglob -case $hostname in - # todo: these hosts are broken, not updated to new fai hyrbrid scripts. - frodo) - - # for this system, no separate /boot, to keep partitions simple, - # since we want simpler backup recovery. - mount -U $rootid /mnt - ;;& - treetowl) - mount /dev/mapper/vg_treetowl00-lv02 /mnt - mount -U $bootid /mnt/boot - ;;& - frodo|treetowl) - rm -rf /mnt/!(a|i|q|f|boot) /mnt/boot/* - ;; -esac - - - if [[ $mirror ]]; then echo "$0: 404 errors about core.db etc are normal, they will succeed using the secodary mirror" fi pacstrap /mnt base cp /tmp/fai/{fstab,crypttab} /mnt/etc -cp /usr/bin/devbyid /mnt/root -case $hostname in - frodo) - # the root .ssh needs to be like this, - # because it\'s used to get the key to mount an encrypted filesystem - # on top of itself. - d=/mnt/q/root/.ssh - rm -rf $d # for idempotency - mkdir -p $d - scp -oStrictHostKeyChecking=no ian@treetowl:/a/c/machine_specific/frodo/subdir_files/.ssh/* $d - cp .ssh/* $d - ln -s /q/root/.ssh /mnt/root - # background: errors=remount-ro is a debian installer thing. seems like - # not a bad idea. man mount says: The default is set in the filesystem - # superblock, and can be changed using tune2fs(8) - - cat > /mnt/etc/fstab <<'EOF' -UUID=e9ce7b46-9a21-4e79-b7f7-0b18acb57587 / ext4 noatime,errors=remount-ro 0 1 -UUID=dd67766f-93c5-4ce3-9877-a1d9841dd4a4 none swap sw 0 0 -/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0 -/dev/mapper/crypta7 /mnt/btrfs_root btrfs subvolid=0,noatime,noauto 0 2 -/dev/mapper/crypta7 /a btrfs subvol=a,noatime,noauto 0 2 -EOF - ;; - *) - cp -r .ssh /mnt/root - cp -r /root/distro-install-common /mnt/root - ;;& - treetowl) - echo "UUID=a9e83bb7-d23d-4de6-ba9f-d88b887f7206 /a ext4 noatime 0 2" >> /mnt/etc/fstab - ;; -esac +cp /root/encrypt /mnt/usr/lib/initcpio/hooks +# not needed anymore +#cp /usr/bin/devbyid /mnt/root + +cp -r .ssh /mnt/root +cp -r /root/distro-install-common /mnt/root cp /root/arch-init-chroot /mnt/root # for manual commands, arch-chroot /mnt bash @@ -152,7 +107,7 @@ rm -f /mnt/etc/resolv.conf ln -s /run/systemd/resolve/resolv.conf /mnt/etc/resolv.conf # not necsesary, but makes reboot go fast. -umount -R /mnt; sleep 1 +#umount -R /mnt; sleep 1 # causes 255 exit code, so doing this from the caller script. # reboot now diff --git a/arch-init-chroot b/arch-init-chroot index 6c9d66b..d2e0f97 100755 --- a/arch-init-chroot +++ b/arch-init-chroot @@ -55,50 +55,28 @@ cat /etc/fstab # which will be the crypt device name under /dev/mapper/ # https://wiki.archlinux.org/index.php/GRUB#Additional_arguments -first_boot_dev=${BOOT_DEVICE%% *} -crypt_dev=${first_boot_dev}$rootn -crypt_name=$(/root/devbyid $crypt_dev) -crypt_name=crypt_dev_${crypt_name##*/} + +root_devs=( ${ROOT_PARTITIONS} ) +first_root_dev=${root_devs[0]} k_args=( - cryptdevice=$crypt_dev:$crypt_name:allow-discards - root=/dev/mapper/$crypt_name - resume=${crypt_dev%[0-9]}$swapn + cryptdevices=${ROOT_PARTITIONS// /,} + root=/dev/mapper/crypt_dev_${first_root_dev##*/} + resume=${first_root_dev%[0-9]}$swapn ) -crypt_mapper_devs=(/dev/mapper/crypt_dev_*$rootn) -crypt_count=${#crypt_mapper_devs[@]} -if [[ crypt_count == 0 ]]; then - echo "$0: error: expected crypt_mapper_devs length to be > 0" - ls -la /dev/mapper - exit 1 -fi -keyfile_vars=() -dup_keys=() extra_encrypt_hooks=() # If we have more than 1 to decrypt, arch wiki lead me onto # a sort of hacky way run the encrypt hook multiple times. -for ((i=1; i < $crypt_count; i++)); do - extra_encrypt_hooks+=(encrypt$i) - if (( i = 1 )); then dup_keys=(" "); fi # prefix with an empty space - cp /crypto_keyfile.bin /crypto_keyfile$i.bin - dup_keys+=(/crypto_keyfile$i.bin) - base=/usr/lib/initcpio - cp $base/hooks/encrypt{,$i} - cp $base/install/encrypt{,$i} - sed -i "s/cryptdevice/cryptdevice$i/" $base/hooks/encrypt$i - sed -i "s/cryptkey/cryptkey$i/" $base/hooks/encrypt$i - crypt_name=${crypt_mapper_devs[i]#/dev/mapper/} - crypt_dev=/dev/${crypt_name#crypt_dev_} - k_args+=(cryptdevice$i=$crypt_dev:$crypt_name:allow-discards - cryptkey$i=rootfs:/crypto_keyfile$i.bin) -done + +base=/usr/lib/initcpio + # https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#Configuring_mkinitcpio_2 # used to have lvm2 after encrypt for lvm, but not using lvm anymore -for x in encrypt ${extra_encrypt_hooks[@]} btrfs; do +for x in encrypt btrfs; do sed -ri -f - /etc/mkinitcpio.conf < /tmp/myarchinit.log +if ! ip a | grep '^ *inet ' | grep -vF 127.0.0.1; then + cat <<'eof' +We don't have an ipv4 address. Maybe arch doesn't do that for us, +or we are probably using an ethernet port +which is not the 1st one, so we haven't automatically done dhcpcd, +so let's do it on whatever interface has a carrier +eof + for f in /sys/class/net/*; do + if [[ `cat $f/carrier` == 1 ]]; then + echo $0: running: dhcpcd ${f##*/} + dhcpcd ${f##*/} + break + fi + done +fi +systemctl start sshd diff --git a/arch-pxe b/arch-pxe index 7252f2d..66a79de 100755 --- a/arch-pxe +++ b/arch-pxe @@ -6,6 +6,8 @@ set -eE -o pipefail trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR +x="$(readlink -f "$BASH_SOURCE")" +script_dir="${x%/*}" cd /a/opt iso="archlinux-2016.05.01-dual" sfs=$iso/arch/x86_64/airootfs.sfs @@ -14,7 +16,7 @@ ex $iso.iso sed -i -f - $iso/arch/boot/syslinux/archiso_pxe64.cfg < /tmp/myarchinit.log -dhcpcd eth0 -systemctl start sshd -EOF + +s cp $script_dir/arch-iso-init.sh squashfs-root/root s rm $sfs s mksquashfs squashfs-root $sfs -comp xz # file transfer to wrt is slow, so remove some useless files diff --git a/encrypt b/encrypt new file mode 100644 index 0000000..89cc95f --- /dev/null +++ b/encrypt @@ -0,0 +1,129 @@ +#!/usr/bin/ash +run_hook() { + set -x + echo $0 + modprobe -a -q dm-crypt >/dev/null 2>&1 + [ "${quiet}" = "y" ] && CSQUIET=">/dev/null" + + # Get keyfile if specified + ckeyfile="/crypto_keyfile.bin" + if [ -n "$cryptkey" ]; then + IFS=: read ckdev ckarg1 ckarg2 </dev/null 2>&1 + umount /ckey + ;; + *) + # Read raw data from the block device + # ckarg1 is numeric: ckarg1=offset, ckarg2=length + dd if="$resolved" of="$ckeyfile" bs=1 skip="$ckarg1" count="$ckarg2" >/dev/null 2>&1 + ;; + esac + fi + [ ! -f ${ckeyfile} ] && echo "Keyfile could not be opened. Reverting to passphrase." + fi + + for cryptdev in ${cryptdevices//,/ }; do + cryptname=crypt_dev_${cryptdev##*/} + + if [ -n "${cryptoptions}" ]; then + cryptargs="${cryptargs} --allow-discards" + fi + for cryptopt in ${cryptoptions//,/ }; do + case ${cryptopt} in + no-allow-discards) + cryptargs="" + ;; + *) + echo "Encryption option '${cryptopt}' not known, ignoring." >&2 + ;; + esac + done + + if resolved=$(resolve_device "${cryptdev}" ${rootdelay}); then + if cryptsetup isLuks ${resolved} >/dev/null 2>&1; then + dopassphrase=1 + # If keyfile exists, try to use that + if [ -f ${ckeyfile} ]; then + if eval cryptsetup --key-file ${ckeyfile} open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; then + dopassphrase=0 + else + echo "Invalid keyfile. Reverting to passphrase." + fi + fi + # Ask for a passphrase + if [ ${dopassphrase} -gt 0 ]; then + echo "" + echo "A password is required to access the ${cryptname} volume:" + + #loop until we get a real password + while ! eval cryptsetup open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; do + sleep 2; + done + fi + if [ -e "/dev/mapper/${cryptname}" ]; then + if [ ${DEPRECATED_CRYPT} -eq 1 ]; then + export root="/dev/mapper/root" + fi + else + err "Password succeeded, but ${cryptname} creation failed, aborting..." + exit 1 + fi + elif [ -n "${crypto}" ]; then + msg "Non-LUKS encrypted device found..." + if echo "$crypto" | awk -F: '{ exit(NF == 5) }'; then + err "Verify parameter format: crypto=hash:cipher:keysize:offset:skip" + err "Non-LUKS decryption not attempted..." + return 1 + fi + exe="cryptsetup open --type plain $resolved $cryptname $cryptargs" + IFS=: read c_hash c_cipher c_keysize c_offset c_skip </dev/null 2>&1 + [ "${quiet}" = "y" ] && CSQUIET=">/dev/null" + + # Get keyfile if specified + ckeyfile="/crypto_keyfile.bin" + if [ -n "$cryptkey" ]; then + IFS=: read ckdev ckarg1 ckarg2 </dev/null 2>&1 + umount /ckey + ;; + *) + # Read raw data from the block device + # ckarg1 is numeric: ckarg1=offset, ckarg2=length + dd if="$resolved" of="$ckeyfile" bs=1 skip="$ckarg1" count="$ckarg2" >/dev/null 2>&1 + ;; + esac + fi + [ ! -f ${ckeyfile} ] && echo "Keyfile could not be opened. Reverting to passphrase." + fi + + if [ -n "${cryptdevice}" ]; then + DEPRECATED_CRYPT=0 + IFS=: read cryptdev cryptname cryptoptions <&2 + ;; + esac + done + + if resolved=$(resolve_device "${cryptdev}" ${rootdelay}); then + if cryptsetup isLuks ${resolved} >/dev/null 2>&1; then + [ ${DEPRECATED_CRYPT} -eq 1 ] && warn_deprecated + dopassphrase=1 + # If keyfile exists, try to use that + if [ -f ${ckeyfile} ]; then + if eval cryptsetup --key-file ${ckeyfile} open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; then + dopassphrase=0 + else + echo "Invalid keyfile. Reverting to passphrase." + fi + fi + # Ask for a passphrase + if [ ${dopassphrase} -gt 0 ]; then + echo "" + echo "A password is required to access the ${cryptname} volume:" + + #loop until we get a real password + while ! eval cryptsetup open --type luks ${resolved} ${cryptname} ${cryptargs} ${CSQUIET}; do + sleep 2; + done + fi + if [ -e "/dev/mapper/${cryptname}" ]; then + if [ ${DEPRECATED_CRYPT} -eq 1 ]; then + export root="/dev/mapper/root" + fi + else + err "Password succeeded, but ${cryptname} creation failed, aborting..." + exit 1 + fi + elif [ -n "${crypto}" ]; then + [ ${DEPRECATED_CRYPT} -eq 1 ] && warn_deprecated + msg "Non-LUKS encrypted device found..." + if echo "$crypto" | awk -F: '{ exit(NF == 5) }'; then + err "Verify parameter format: crypto=hash:cipher:keysize:offset:skip" + err "Non-LUKS decryption not attempted..." + return 1 + fi + exe="cryptsetup open --type plain $resolved $cryptname $cryptargs" + IFS=: read c_hash c_cipher c_keysize c_offset c_skip <&2' ERR cd $(dirname $(readlink -f "$BASH_SOURCE")) -ssh root@faiserver rm -rf /srv/fai/config -scp -r fai/config root@faiserver:/srv/fai + +faiserver_host=faiserver +# i use faiserver as a dns alias, but ssh key is associated with +# a canonical hostname and we will have ssh warning spam unless we +# use it, so look it up. +if addr=$(host faiserver); then + addr=${addr##* } + if h=$(host $addr); then + h=${h##* } + faiserver_host=${h%%.*} + else + echo "$0: warning: host \$addr($addr) failed" + fi +else + echo "$0: warning: host faiserver failed" +fi + + +ssh root@$faiserver_host rm -rf /srv/fai/config +scp -r fai/config root@$faiserver_host:/srv/fai # fai example pass: fai #ROOTPW='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' @@ -22,24 +40,24 @@ scp -r fai/config root@faiserver:/srv/fai f=/q/root/shadow/standard if s test -e $f; then - ssh root@faiserver tee -a /srv/fai/config/class/DEFAULT.var </tmp/fai/disk_var.sh <&2' ERR -- 2.30.2