# https://www.gnu.org/software/grub/manual/html_node/Device-map.html
e grub-bios-setup -d $mount_point/grub/i386-pc -s -m $mount_point/grub/device.map $boot_disk
+# todo, mount_point needs subvolid=0
+e grub-editenv $mount_point/grub2/grubenv set default_subvol=/boot_$distro
+
e umount $mount_point
e rmdir $mount_point
# use it, so look it up just to avoid the warning spam.
faiserver_host=$(chost faiserver) || faiserver_host=faiserver
-
-ssh root@$faiserver_host rm -rf /srv/fai/config
+shopt -s extglob
+ssh root@$faiserver_host rm -rf /srv/fai/config/!(basefiles)
scp -r fai/config root@$faiserver_host:/srv/fai
scp ~/.ssh/id_rsa.pub \
- root@$faiserver_host:/srv/fai/config/files/home/ian/.ssh/authorized_keys/GRUB_PC
+ root@$faiserver_host:/srv/fai/config/files/root/.ssh/authorized_keys/GRUB_PC
# todo: automatically disable faiserver after a period so
# these files are not exposed.
s scp -r /q/root/luks /q/root/shadow \
# built this with mk-basefile -J BELENOS64. it's stored in it's own repo which
# is published alongside this one called fai-basefiles due
# to being a large binary file.
-scp /a/bin/basefiles/BELENOS64.tar.xz root@$faiserver_host:/srv/fai/config/basefiles
+scp /a/bin/fai-basefiles/BELENOS64.tar.xz root@$faiserver_host:/srv/fai/config/basefiles
ssh root@$faiserver_host bash <<'EOF'
set -eE -o pipefail
set -x
-chmod 644 /srv/fai/config/files/home/ian/.ssh/authorized_keys/GRUB_PC
+# make it the root because pxe-kexec only looks there.
+# It wouldn't be too hard to change if we needed.
+# We could also just dump things in /srv/tftp, but fai
+# has some defaults, which I don't even use, which expect
+# the other directory, so it's kind of a tossup, whatever.
+sed -ri 's,^ *(TFTP_DIRECTORY=).*,\1"/srv/tftp/fai",' /etc/default/tftpd-hpa
+systemctl restart tftpd-hpa
+chmod 644 /srv/fai/config/files/root/.ssh/authorized_keys/GRUB_PC
chmod -R a+rX /srv/fai/config/distro-install-common
cd /srv/fai/config/basefiles
u=http://fai-project.org/download/basefiles/XENIAL64.tar.xz
# use a list of classes for our demo machine
echo "FAIBASE PARTITION_PROMPT"
case $HOSTNAME in
- x2|frodo|treetowl)
+ frodo|treetowl)
echo "DEBIAN_NON_FREE"
if [[ -e /a/bin/fai/fai-wrapper ]] && isdebian-stable; then
echo "STABLE_NON_FREE"
if [[ $pwfile && -e $pwfile ]]; then
printf "$user:" | cat - "$pwfile" | $ROOTCMD chpasswd -e
else
- echo "$0: warning: no pw set for $user"
+ echo "$0: warning: no pw set for $user" >&2
fi
}
au() {
#!/bin/bash
# exit for any vm which is not our test vm
-if ifclass VM && ! ifclass demohost; then
+if ifclass VM && ! ifclass demohost || ifclass STABLE_BOOTSTRAP; then
exit 0
fi
swapn=2
bootn=3
bios_grubn=4
-boot_mib=1500
+boot_mib=4000
##### end configuration
-add-part() {
+add-part() { # add partition suffix to $dev
local d ret
if [[ $# == 1 ]]; then
d=$dev
done
if [[ ! $DISTRO ]]; then
- if ifclass STRETCH64; then
+ if ifclass STABLE_BOOTSTRAP; then
+ DISTRO=debianstable_bootstrap
+ elif ifclass STRETCH64; then
DISTRO=debiantesting
elif ifclass STABLE; then
DISTRO=debianstable
swap_end=$(( root_end + swap_mib))
parted -s $dev mklabel gpt
- # gpt ubuntu cloud image uses ~4. fai uses 1 MiB.
- # I read something in the parted manual saying cheap flash media
- # likes to start at 4.
# MiB because parted complains about alignment otherwise.
pcmd="parted -a optimal -s -- $dev"
$pcmd mkpart primary "ext3" 4MiB ${root_end}MiB
$pcmd mkpart primary "linux-swap" ${root_end}MiB ${swap_end}MiB
$pcmd mkpart primary "" ${swap_end}MiB ${disk_mib}MiB
+ # gpt ubuntu cloud image uses ~4. fai uses 1 MiB.
+ # I read something in the parted manual saying cheap flash media
+ # likes to start at 4.
$pcmd mkpart primary "" 1MiB 4MiB
$pcmd set $bios_grubn bios_grub on
$pcmd set $bootn boot on # generally not needed on modern systems
cryptsetup luksOpen `rootdev` `root-cryptname` \
--key-file $luks_dir/host-$HOSTNAME
done
- ls -la /dev/btrfs-control
+ ls -la /dev/btrfs-control # this was probably for debugging...
sleep 1
bpart $(for dev in ${devs[@]}; do root-cryptdev; done)
bpart ${boot_devs[@]}
sleep 1
fi
-mount -o subvolid=0 $first_root_crypt /mnt
-# systemd creates subvolumes we want to delete.
-s=($(btrfs subvolume list --sort=-path /mnt |
- sed -rn "s#^.*path\s*(root_$DISTRO/\S+)\s*\$#\1#p"))
-for subvol in ${s[@]}; do btrfs subvolume delete /mnt/$subvol; done
-btrfs subvolume set-default 0 /mnt
-[[ ! -e /mnt/root_$DISTRO ]] || btrfs subvolume delete /mnt/root_$DISTRO
-## create subvols ##
-cd /mnt
-btrfs subvolume create root_$DISTRO
-[[ -e q ]] || btrfs subvolume create q
-chown root:1000 q
-
-mkdir -p /mnt/root_$DISTRO/boot
-for x in q/a q/i; do
- mkdir -p $x
- chown 1000:1000 $x
- chmod 755 $x
-done
-# could set default like this, but no reason to.
-# btrfs subvolume set-default \
- # $(btrfs subvolume list . | grep "root_$DISTRO$" | awk '{print $2}') .
-chattr -Rf +C root_$DISTRO
-cd /
-umount /mnt
+if [[ $DISTRO != debianstable_bootstrap ]]; then
+ # bootstrap distro doesn't use separate encrypted root.
+ mount -o subvolid=0 $first_root_crypt /mnt
+ # systemd creates subvolumes we want to delete.
+ s=($(btrfs subvolume list --sort=-path /mnt |
+ sed -rn "s#^.*path\s*(root_$DISTRO/\S+)\s*\$#\1#p"))
+ for subvol in ${s[@]}; do btrfs subvolume delete /mnt/$subvol; done
+ btrfs subvolume set-default 0 /mnt
+ [[ ! -e /mnt/root_$DISTRO ]] || btrfs subvolume delete /mnt/root_$DISTRO
+
+ ## create subvols ##
+ cd /mnt
+
+ btrfs subvolume create root_$DISTRO
+ [[ -e q ]] || btrfs subvolume create q
+ chown root:1000 q
+
+ mkdir -p /mnt/root_$DISTRO/boot
+ for x in q/a q/i; do
+ mkdir -p $x
+ chown 1000:1000 $x
+ chmod 755 $x
+ done
+ # could set default like this, but no reason to.
+ # btrfs subvolume set-default \
+ # $(btrfs subvolume list . | grep "root_$DISTRO$" | awk '{print $2}') .
+
+ # no cow on the root filesystem. it's setup is fully scripted,
+ # (immutable in buzzwords). if it messes up, we will just recreated it,
+ # and we can get better perf with this.
+ # I can't remember exactly why, but this is preferable to mounting with
+ # -o nodatacow, I think because subvolumes inherit that.
+ chattr -Rf +C root_$DISTRO
+ cd /
+ umount /mnt
+fi
+
mount -o subvolid=0 $first_boot_dev /mnt
cd /mnt
btrfs subvolume set-default 0 /mnt
-[[ ! -e /mnt/boot_$DISTRO ]] || btrfs subvolume delete /mnt/boot_$DISTRO
-btrfs subvolume create boot_$DISTRO
+
+# for libreboot systems
+mkdir -p /mnt/grub2
+cat >/mnt/grub2/libreboot_grub.cfg <<'EOF'
+#!/bin/sh
+# shebang is for editor file mode detection only
+
+if [ -s $prefix/grubenv ]; then
+ load_env
+fi
+
+set default="0"
+set timeout=1
+
+menuentry debianstable_bootstrap {
+ configfile /$1/boot/grub/grub.cfg
+}
+
+for dir in /boot_*; do
+ if [ x$dir = x$default_subvol ]; then
+ default=default_id
+ menuentry $dir --id=default_id {
+ configfile $1/grub/grub.cfg
+ }
+ else
+ menuentry $dir {
+ configfile $1/grub/grub.cfg
+ }
+ fi
+done
+EOF
+
+if [[ $DISTRO == debianstable_bootstrap ]]; then
+ # this is just convenience for the libreboot_grub config
+ # so we can glob the other ones easier.
+ boot_vol=$DISTRO
+else
+ boot_vol=boot_$DISTRO
+fi
+[[ ! -e /mnt/$boot_vol ]] || btrfs subvolume delete /mnt/$boot_vol
+btrfs subvolume create $boot_vol
cd /
umount /mnt
## end create subvols ##
-# note, the mount point /a seems to get automatically created somewhere
-cat > /tmp/fai/fstab <<EOF
+if [[ $DISTRO == debianstable_bootstrap ]]; then
+ cat > /tmp/fai/fstab <<EOF
+$first_boot_dev / btrfs noatime,subvol=$boot_vol 0 0
+EOF
+ cat >/tmp/fai/disk_var.sh <<EOF
+BOOT_DEVICE="${short_devs[@]}"
+ROOT_PARTITION=$first_boot_dev
+EOF
+else
+ # note, the mount point /a seems to get automatically created somewhere
+ cat > /tmp/fai/fstab <<EOF
$first_root_crypt / btrfs noatime,subvol=root_$DISTRO 0 0
$first_root_crypt /q btrfs noatime,subvol=q 0 0
/q/a /a none bind 0 0
-$first_boot_dev /boot btrfs noatime,subvol=boot_$DISTRO 0 0
+$first_boot_dev /boot btrfs noatime,subvol=$boot_vol 0 0
EOF
-
-# I will avoid using uuid in the future.
-if ifclass treetowl; then
- cat >> /tmp/fai/fstab <<'EOF'
+ # I will avoid using uuid in the future. the other way of specifying is simpler
+ if ifclass treetowl; then
+ cat >> /tmp/fai/fstab <<'EOF'
$first_root_crypt /i btrfs noatime,subvol=i 0 0
UUID=3f7b31cd-f299-40b4-a86b-7604282e2715 /i btrfs noatime 0 2
EOF
-fi
+ fi
-swaps=()
-for dev in ${devs[@]}; do
- swaps+=(`swap-cryptname`)
- cat >>/tmp/fai/crypttab <<EOF
+ swaps=()
+ for dev in ${devs[@]}; do
+ swaps+=(`swap-cryptname`)
+ cat >>/tmp/fai/crypttab <<EOF
`root-cryptname` `rootdev` none keyscript=/root/keyscript,discard,luks
`swap-cryptname` `swapdev` /dev/urandom swap,cipher=aes-xts-plain64,size=256,hash=ripemd160
EOF
- cat >> /tmp/fai/fstab <<EOF
+ cat >> /tmp/fai/fstab <<EOF
`swap-cryptdev` none swap sw 0 0
EOF
-done
-
-# fai would do this:
-#BOOT_DEVICE=\${BOOT_DEVICE:-"${devs[0]}"}
+ done
-# swaplist seems to do nothing.
+ # fai would do this:
+ #BOOT_DEVICE=\${BOOT_DEVICE:-"${devs[0]}"}
-cat >/tmp/fai/disk_var.sh <<EOF
+ # note: swaplist seems to do nothing.
+ cat >/tmp/fai/disk_var.sh <<EOF
+BOOT_DEVICE="${short_devs[@]}"
+BOOT_PARTITION=\${BOOT_PARTITION:-$first_boot_dev}
# ROOT_PARTITIONS is added by me, used in arch setup.
ROOT_PARTITIONS="${root_devs[@]}"
ROOT_PARTITION=\${ROOT_PARTITION:-$first_root_crypt}
-BOOT_PARTITION=\${BOOT_PARTITION:-$first_boot_dev}
-BOOT_DEVICE="${short_devs[@]}"
SWAPLIST=\${SWAPLIST:-"${swaps[@]}"}
EOF
+fi
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
if [[ $EUID != 0 ]]; then
- echo "$0: error: expected to be root."
- exit 1
+ echo "$0: error: expected to be root."
+ exit 1
+fi
+
+# note:
+# fcopy -i = ignore nonmatching class error, always return 0.
+fcopy -riM /root/.ssh
+
+chroot $FAI_ROOT bash <<'EOFOUTER'
+debconf-set-selections <<EOF
+kexec-tools kexec-tools/load_kexec boolean false
+EOF
+apt-get install -y pxe-kexec
+EOFOUTER
+
+if ifclass STABLE_BOOTSTRAP; then
+ exit 0
fi
if ! type -t fcopy &>/dev/null; then
- sudo apt-get -y install fai-client
+ sudo apt-get -y install fai-client
fi
dir=/q/root/shadow
fai_shadow=$FAI/distro-install-common/shadow
if [[ ! -e $dir && -e $fai_shadow ]]; then
- mkdir -p $dir
- mount -o bind $fai_shadow $dir
+ mkdir -p $dir
+ mount -o bind $fai_shadow $dir
fi
$FAI/distro-install-common/end
if ifclass STABLE || ifclass LINODESTABLE; then
- fcopy -M /etc/apt/preferences
+ fcopy -M /etc/apt/preferences
fi
if ifclass DEBIAN; then
- fcopy -M /etc/apt/preferences.d/unstable
+ fcopy -M /etc/apt/preferences.d/unstable
fi
fcopy -riM /etc/apt/sources.list.d
$ROOTCMD apt-get update
-# note:
-# fcopy -i = ignore nonmatching class error, always return 0.
-
-# for lj, this will be empty and fail
-fcopy -riM /home/ian/.ssh
rm -f $FAI_ROOT/etc/apt/sources.list
| tr '\n' ' '; ssh-keyscan localhost | grep -o "ecdsa-sha2-nistp256.*"; \
} >>/srv/fai/nfsroot/root/.ssh/known_hosts
-# this does not alter the config on a new install
-$sed 's#^([[:space:]]*TFTP_DIRECTORY[[:space:]]*=).*#\1"/srv/tftp"#' \
- /etc/default/tftpd-hpa
-
-service tftpd-hpa restart
-
# initially did the basic fai-chboot -Iv $std_arg default
# but found in console that it wanted to mount nfsroot
# to be the same as my dhcp server.
errcatch
-[[ $EUID == 0 ]] || sudo "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo "$BASH_SOURCE" "$@"
usage() {
cat <<EOF
Usage: ${0##*/} [OPTIONS] +/-SIZE[g] swap|boot
-Assuming Ian Kelling's partition scheme,
-Resize swap or boot, expanding or shrinking the root fs and partition to compensate.
+Assuming Ian Kelling's partition scheme, Resize swap or boot, expanding
+or shrinking the root fs and partition to compensate. If it changes
+the partition tables incorrectly, the originals are stored in
+/root/backup_partition_table_<device_names>.
-n Dry run
-r Reboot now if it's needed.
reboot_not=false
dry_run=false
-temp=$(getopt -l opt o "$@") || usage 1
+temp=$(getopt -l help rnh "$@") || usage 1
eval set -- "$temp"
while true; do
case $1 in
[[ $2 == boot ]] || boot=false
op_size=$1 # operator plus size
-[[ $op_size != *g ]] || op_size=$(( ${op_size%g} / 1024 ))
-size=${op_size#[+-]}
+if [[ $op_size == *g ]]; then
+ op_size=${op_size%g}
+ size=${op_size#?}
+ op=${op_size%size}
+ size=$(( ${size} * 1024 ))
+ op_size=$op$size
+else
+ size=${op_size#?}
+fi
if [[ $op_size == +* ]]; then
op_size_rev=-$size # rev = reverse
grow=false
fi
-
##### end command line parsing ########
rootn=1
needs_reboot=false
reboot_script_initialized=false
-pmk() {
+pmk() { # partition make
part=$1
start_op=$2
end_op=$3
- p mkpart primary "$4" \
- $((${ptable[start$part]} $start_op)) $((${ptable[end$part]} $end_op))
+ fs_type="$4"
+
+ # This fails outside a vm, but actually succeeds. also prints this
+ # message:
+ # Error: Partition(s) 2 on /dev/sda have been written, but
+ # we have been unable to inform the kernel of the change, probably
+ # because it/they are in use. As a result, the old partition(s)
+ # will remain in use. You should reboot now before making further
+ # changes.
+
+ p mkpart primary "$fs_type" \
+ $((${ptable[start$part]} $start_op)) $((${ptable[end$part]} $end_op)) ||:
}
def-e() {
e swapoff -a
while read devid dev; do
+ if [[ $dev != /dev/mapper/* ]]; then
+ # older oses, it points to /dev/dm-x
+ dev=$(dmsetup info $dev | sed -rn 's/^\s*Name:\s*(\S*)/\1/p')
+ else
+ dev=${dev#/dev/mapper/}
+ fi
+ dev=${dev#crypt_dev_}
+ r='-part[0-9]*$'
+ [[ $dev =~ $r ]] ||:
+ dev=${dev%$BASH_REMATCH}
+ devpath=/dev/disk/by-id/$dev
echo skip=$size
def-e
declare -A ptable
ptable[start$id]=start=${start%%[^0-9]*}
ptable[end$id]=${end%%[^0-9]*}
ptable[size$id]=${psize%%[^0-9]*}
- done < <(parted -m /dev/$dev unit MiB print)
- parted /dev/$dev unit MiB print | tee /root/backup_partition_table_$dev
- p() { e parted -a optimal -s -- /dev/$dev unit MiB "$@"; }
- e systemctl stop systemd-cryptsetup@crypt_swap_$dev$swapn
+ done < <(parted -m $devpath unit MiB print)
+ parted $devpath unit MiB print | tee /root/backup_partition_table_$dev
+ p() { e parted -a optimal -s -- $devpath unit MiB "$@"; }
+ unit=systemd-cryptsetup@crypt_dev_$dev-part$swapn
+ # note systemctl show can test if a unit exists.
+ e systemctl stop $unit || [[ $? == 5 ]] # fail due to not loaded
+ # there is a bug in jessie. this and the .swap unit are
+ # generated from /etc/fstab, and it escapes - to x2d, then doesn't escape it
+ # when looking for the file to use as swap. so, no swap is working on jessie
+ # right now.
sleep 1 # dunno if this is needed,
# but systemd likes to do these kind of things in the background.
$root_resize_cmd
fi
if $boot; then
+ # non by-id path, to match what btrfs fi show will tell us
+ boot_dev_path=$(readlink -f $devpath-part$bootn)
boot_devid=$(btrfs fi show /boot | \
- sed -rn "s#^\s*devid\s+(\S+)\s.*$dev[0-9]#\1#p")
+ sed -rn "s#^\s*devid\s+(\S+)\s.*$boot_dev_path#\1#p")
if ! $grow; then
# shrink boot, move it to a temp file
e btrfs fi resize $boot_devid:${op_size}M /boot
e umount /boot
temp_boot=/root/temp_boot_$dev
- e dd bs=1M if=/dev/$dev$bootn of=$temp_boot \
+ e dd bs=1M if=$boot_dev_path of=$temp_boot \
count=$((${ptable[size$bootn]} $op_size))
else
e umount /boot
pmk $bootn $op_size_rev ""
if $grow; then
- e dd bs=1M if=/dev/$dev$bootn of=/dev/$dev$bootn skip=$size
+ e dd bs=1M if=$boot_dev_path of=$boot_dev_path skip=$size
e mount /boot
e btrfs fi resize $boot_devid:${op_size}M /boot
else
- e dd bs=1M if=$temp_boot of=/dev/$dev$bootn
+ e dd bs=1M if=$temp_boot of=$boot_dev_path
e mount /boot
fi
else
pmk $swapn $op_size_rev "" "linux-swap"
e systemctl start systemd-cryptsetup@crypt_swap_$dev$swapn
fi
-done < <(btrfs fi show / | \
- sed -nr 's#^\s*devid\s*(\S+)\s.*_([^_ ]+)[0-9]\s*$#\1 \2#p')
+done < <(btrfs fi show / | sed -nr 's#^\s*devid\s*(\S+).* path (.*)$#\1 \2#p')
if $boot; then
exit
fi
fi
-
fai() {
cat <<EOF
$set_host_tag
-dhcp-boot=${host_tag}fai/pxelinux.0,faiserver.lan,faiserver.lan
+dhcp-boot=${host_tag}pxelinux.0,faiserver.lan,faiserver.lan
EOF
}