Initial commit.
commit
d6c6bc72dc
|
@ -0,0 +1,773 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# Automatic setup of Debian or Ubuntu on an Online.net or Hetzner rescue system.
|
||||||
|
#
|
||||||
|
# ref https://github.com/openzfs/zfs/wiki/Debian-Buster-Root-on-ZFS
|
||||||
|
#
|
||||||
|
# Author: Carl Kittelberger <icedream@icedream.pw>
|
||||||
|
# Version: 3.0.0-beta.2
|
||||||
|
# Date: 2021-05-01
|
||||||
|
|
||||||
|
raidtype=auto
|
||||||
|
disks=()
|
||||||
|
hostname=${hostname:-$(hostname)}
|
||||||
|
rpool=""
|
||||||
|
bpool=""
|
||||||
|
system="${system:-$(lsb_release -is | tr '[[:upper:]]' '[[:lower:]]')}"
|
||||||
|
mirror="http://deb.debian.org/debian"
|
||||||
|
|
||||||
|
# Ensure only valid defaults are set for system
|
||||||
|
case "$system" in
|
||||||
|
debian|ubuntu)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
system=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 [options] <disk> [<disk>...]" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Disks need to be supplied as /dev/disk/by-id/... path references.">&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Options:">&2
|
||||||
|
echo "" >&2
|
||||||
|
echo " -h, --help Show this help message" >&2
|
||||||
|
echo " --hostname HOSTNAME Set hostname to be written to the installed operating system. Default: $hostname" >&2
|
||||||
|
echo " --rpool RPOOL Set name of ZFS data pool. Default: <hostname>-rpool ($hostname-rpool)" >&2
|
||||||
|
echo " --bpool BPOOL Set name of ZFS data pool. Default: <hostname>-bpool ($hostname-bpool)" >&2
|
||||||
|
if [ -n "$system" ]
|
||||||
|
then
|
||||||
|
echo " -s, --system SYSTEM The system to install. Valid values are debian or ubuntu. Defaults to currently running operating system ($system)." >&2
|
||||||
|
else
|
||||||
|
echo " -s, --system SYSTEM The system to install. Valid values are debian or ubuntu. Required because the current operating system is not actually supported as target operating system." >&2
|
||||||
|
fi
|
||||||
|
echo " --hetzner Use Hetzner network mirror." >&2
|
||||||
|
echo " --online Use Online.net network mirror." >&2
|
||||||
|
echo " --mirror MIRROR Use custom mirror . Default: $mirror" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
noproc=0
|
||||||
|
while [ "$noproc" -eq 0 ] && [ "$#" -gt 0 ]
|
||||||
|
do
|
||||||
|
opt="$1"
|
||||||
|
case "$opt" in
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
--hostname)
|
||||||
|
if [ -z "$2" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Expected a value following $opt." >&2
|
||||||
|
fi
|
||||||
|
hostname="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--rpool)
|
||||||
|
if [ -z "$2" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Expected a value following $opt." >&2
|
||||||
|
fi
|
||||||
|
rpool="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--bpool)
|
||||||
|
if [ -z "$2" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Expected a value following $opt." >&2
|
||||||
|
fi
|
||||||
|
bpool="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-s|--system)
|
||||||
|
if [ -z "$2" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Expected a value following $opt." >&2
|
||||||
|
fi
|
||||||
|
system="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-t|--type)
|
||||||
|
if [ -z "$2" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Expected a value following $opt." >&2
|
||||||
|
fi
|
||||||
|
raidtype="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--hetzner)
|
||||||
|
mirror="http://mirror.hetzner.de/${system}/packages"
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
--online)
|
||||||
|
mirror="https://mirrors.online.net/${system}"
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
--mirror)
|
||||||
|
if [ -z "$2" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Expected a value following $opt." >&2
|
||||||
|
fi
|
||||||
|
mirror="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
noproc=1
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
noproc=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
rpool="${rpool:-${hostname}-rpool}"
|
||||||
|
bpool="${bpool:-${hostname}-bpool}"
|
||||||
|
|
||||||
|
echo "Data pool will be named $rpool." >&2
|
||||||
|
echo "Boot pool will be named $bpool." >&2
|
||||||
|
|
||||||
|
# Check disks use /dev/disk/by-id/... style reference
|
||||||
|
for disk in "$@"
|
||||||
|
do
|
||||||
|
case "$disk" in
|
||||||
|
/dev/disk/by-id/*)
|
||||||
|
echo "Considering disk $disk." >&2
|
||||||
|
disks+=("$disk")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Invalid disk reference $disk, needs to be formatted like this: /dev/disk/by-id/..." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Did we receive any disk information at all?
|
||||||
|
if [ "${#disks[@]}" -lt 1 ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Need at least one disk." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if we got a valid target operating system to install
|
||||||
|
case "$system" in
|
||||||
|
debian|ubuntu)
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
echo "ERROR: You need to set a system to be installed." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: You need to set a valid system to be installed. $system is not supported, only debian and ubuntu are." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# If raidtype is auto, automatically select one:
|
||||||
|
# - 1 disk: striped
|
||||||
|
# - 2 disks: mirror
|
||||||
|
# - 3+ disks: raidz
|
||||||
|
if [ "$raidtype" = auto ]
|
||||||
|
then
|
||||||
|
raidtype=striped
|
||||||
|
if [ "${#disks[@]}" -gt 2 ]
|
||||||
|
then
|
||||||
|
raidtype=raidz
|
||||||
|
elif [ "${#disks[@]}" -gt 1 ]
|
||||||
|
then
|
||||||
|
raidtype=mirror
|
||||||
|
fi
|
||||||
|
echo "Autoselected RAID type for ${#disks[@]} disks: $raidtype" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
alldisks() {
|
||||||
|
for disk in "${disks[@]}"
|
||||||
|
do
|
||||||
|
"$@" "$disk" || return "$?"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
allpartref() {
|
||||||
|
for disk in "${disks[@]}"
|
||||||
|
do
|
||||||
|
echo "${disk}-part$1"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Only apply a patch if it wasn't already applied.
|
||||||
|
# Turns the error case of an already applied patch into a success case.
|
||||||
|
softpatch() {
|
||||||
|
patch "$@" || if [ "$?" -ne 1 ]
|
||||||
|
then
|
||||||
|
return $?
|
||||||
|
else
|
||||||
|
true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$(id -u)" != 0 ]; then
|
||||||
|
sudo -v
|
||||||
|
else
|
||||||
|
sudo() {
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
export sudo
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND="${DEBIAN_FRONTEND:-noninteractive}"
|
||||||
|
|
||||||
|
sudo apt install -y "linux-image-$(uname -r)" "linux-headers-$(uname -r)" eatmydata
|
||||||
|
sudo eatmydata apt-get autoremove -y $(eatmydata apt list | grep -P '^linux-(image|headers)' | grep -vP "^linux-(image|headers)-$(uname -r)" | cut -d/ -f 1)
|
||||||
|
for d in /lib/modules/*/
|
||||||
|
do
|
||||||
|
kernel_version=$(basename "$d")
|
||||||
|
if [ "${kernel_version}" != "$(uname -r)" ]
|
||||||
|
then
|
||||||
|
rm -rv "$d"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
sudo umount -l /mnt/dev || true
|
||||||
|
sudo umount -l /mnt/proc || true
|
||||||
|
sudo umount -l /mnt/sys || true
|
||||||
|
|
||||||
|
#sudo touch /boot/vmlinuz-4.4.0-97 /boot/vmlinuz-4.4.0-97-generic /boot/initrd.img-4.4.0-97 /boot/initrd.img-4.4.0-97-generic
|
||||||
|
|
||||||
|
#sudo sed -i 's,\bmain\b,main contrib,g' /etc/apt/sources.list
|
||||||
|
sudo eatmydata apt install -y mdadm gdisk "linux-headers-$(uname -r)"
|
||||||
|
if ! modprobe zfs
|
||||||
|
then
|
||||||
|
# check for backports
|
||||||
|
codename="$(lsb_release -cs)"
|
||||||
|
has_backports="$(curl -Ifso /dev/null "https://deb.debian.org/debian/dists/${codename}-backports/Release" && echo 1 || echo 0)"
|
||||||
|
if [ "${has_backports}" -ne 0 ]
|
||||||
|
then
|
||||||
|
echo "deb https://deb.debian.org/debian ${codename}-backports main contrib" > /etc/apt/sources.list.d/backports.list
|
||||||
|
eatmydata apt update
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${has_backports}" -ne 0 ]
|
||||||
|
then
|
||||||
|
sudo eatmydata apt install -y -t "${codename}-backports" zfs-dkms
|
||||||
|
|
||||||
|
# sudo eatmydata apt install -y devscripts
|
||||||
|
|
||||||
|
# # Build spl
|
||||||
|
# sudo eatmydata apt build-dep -y spl-linux
|
||||||
|
# rm -rf spl-linux*
|
||||||
|
# eatmydata apt source spl-linux
|
||||||
|
# wget -O spl-pr-710.patch https://github.com/zfsonlinux/spl/pull/710.patch
|
||||||
|
# if (cd spl-linux*/ && patch --dry-run --silent -N -p1 -i ../spl-pr-710.patch)
|
||||||
|
# then
|
||||||
|
# cd spl-linux*/
|
||||||
|
# patch -N -p1 -i ../spl-pr-710.patch
|
||||||
|
# echo '4.19' > debian/linux_compat
|
||||||
|
# dch -v 0.7.12 "Apply spl 0.7.12 patchset."
|
||||||
|
# cd ../spl-linux-*/
|
||||||
|
# dpkg-buildpackage -b
|
||||||
|
# cd ..
|
||||||
|
# sudo eatmydata apt install -y ./*.deb
|
||||||
|
# rm *.deb
|
||||||
|
# elif [ "$?" -eq 1 ]
|
||||||
|
# then
|
||||||
|
# echo "Patch was already applied, skipping spl-linux build." >&2
|
||||||
|
# else
|
||||||
|
# echo "ERROR: Failed to apply patch." >&2
|
||||||
|
# exit 1
|
||||||
|
# fi
|
||||||
|
# rm spl-pr-710.patch
|
||||||
|
|
||||||
|
# # Build zfs
|
||||||
|
# sudo eatmydata apt build-dep -y zfs-linux
|
||||||
|
# rm -rf zfs-linux*
|
||||||
|
# eatmydata apt source zfs-linux
|
||||||
|
# wget -O zfs-pr-8078.patch https://github.com/zfsonlinux/zfs/pull/8078.patch
|
||||||
|
# if (cd zfs-linux*/ && patch --dry-run --silent -N -p1 -i ../zfs-pr-8078.patch)
|
||||||
|
# then
|
||||||
|
# cd zfs-linux*/
|
||||||
|
# patch -N -p1 -i ../zfs-pr-8078.patch
|
||||||
|
# echo '4.19' > debian/linux_compat
|
||||||
|
# dch -v 0.7.12 "Apply zfsonlinux 0.7.12 patchset."
|
||||||
|
# cd ../zfs-linux-*/
|
||||||
|
# dpkg-buildpackage -b
|
||||||
|
# cd ..
|
||||||
|
# rm *dracut*.deb
|
||||||
|
# sudo eatmydata apt install -y ./*.deb
|
||||||
|
# rm *.deb
|
||||||
|
# elif [ "$?" -eq 1 ]
|
||||||
|
# then
|
||||||
|
# echo "Patch was already applied, skipping zfs build and installing zfs-dkms binary distribution." >&2
|
||||||
|
# sudo eatmydata apt install -y zfs-dkms
|
||||||
|
# else
|
||||||
|
# echo "ERROR: Failed to apply patch." >&2
|
||||||
|
# exit 1
|
||||||
|
# fi
|
||||||
|
# rm zfs-pr-8078.patch
|
||||||
|
else
|
||||||
|
sudo eatmydata apt install -y zfs-dkms
|
||||||
|
fi
|
||||||
|
sudo modprobe zfs
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo eatmydata apt install -y jq
|
||||||
|
debootstrap_version=$(wget -qO- https://sources.debian.org/api/src/debootstrap/ | jq '.versions[0].version' -r)
|
||||||
|
case "$system" in
|
||||||
|
debian)
|
||||||
|
sudo eatmydata apt install -y debian-archive-keyring
|
||||||
|
wget -Odebootstrap.deb https://deb.debian.org/debian/pool/main/d/debootstrap/debootstrap_${debootstrap_version}_all.deb
|
||||||
|
;;
|
||||||
|
ubuntu)
|
||||||
|
sudo eatmydata apt install -y ubuntu-keyring
|
||||||
|
wget -Odebootstrap.deb http://de.archive.ubuntu.com/ubuntu/pool/main/d/debootstrap/debootstrap_${debootstrap_version}ubuntu1_all.deb
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported system: $system"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sudo eatmydata apt install -y --allow-downgrades ./debootstrap.deb
|
||||||
|
|
||||||
|
sudo zpool export "${hostname}" || true
|
||||||
|
sudo zpool export "${bpool}" || true
|
||||||
|
sudo zpool export "${rpool}" || true
|
||||||
|
sudo zpool destroy "${hostname}" || true
|
||||||
|
sudo zpool destroy "${bpool}" || true
|
||||||
|
sudo zpool destroy "${rpool}" || true
|
||||||
|
alldisks sudo mdadm --zero-superblock --force || true
|
||||||
|
alldisks sudo sgdisk --zap-all
|
||||||
|
alldisks sudo blkdiscard || for d in "${disks[@]}"; do
|
||||||
|
sudo dd if=/dev/zero of="${d}" bs=32M count=4 oflag=direct status=progress
|
||||||
|
done
|
||||||
|
partBIOS=1
|
||||||
|
partUEFI=2
|
||||||
|
partBootPool=3
|
||||||
|
partRootPool=4
|
||||||
|
alldisks sudo sgdisk -a1 -n1:24K:+1000K -t1:EF02 # bios boot
|
||||||
|
alldisks sudo sgdisk -n2:1M:+512M -t2:EF00 # uefi boot
|
||||||
|
alldisks sudo sgdisk -n3:0:+1G -t3:BF01 # boot pool
|
||||||
|
alldisks sudo sgdisk -n4:0:0 -t4:BF01 # zfs pool
|
||||||
|
sudo partprobe
|
||||||
|
# sudo hdparm -z "${disks[@]}"
|
||||||
|
sleep 1
|
||||||
|
for d in $(
|
||||||
|
allpartref "${partBootPool}"
|
||||||
|
allpartref "${partRootPool}"
|
||||||
|
)
|
||||||
|
do
|
||||||
|
sudo blkdiscard "$d" || sudo dd if=/dev/zero of="$d" bs=1M count=1
|
||||||
|
done
|
||||||
|
|
||||||
|
# create boot pool
|
||||||
|
sudo zpool create -o ashift=12 -d \
|
||||||
|
-o feature@async_destroy=enabled \
|
||||||
|
-o feature@bookmarks=enabled \
|
||||||
|
-o feature@embedded_data=enabled \
|
||||||
|
-o feature@empty_bpobj=enabled \
|
||||||
|
-o feature@enabled_txg=enabled \
|
||||||
|
-o feature@extensible_dataset=enabled \
|
||||||
|
-o feature@filesystem_limits=enabled \
|
||||||
|
-o feature@hole_birth=enabled \
|
||||||
|
-o feature@large_blocks=enabled \
|
||||||
|
-o feature@lz4_compress=enabled \
|
||||||
|
-o feature@spacemap_histogram=enabled \
|
||||||
|
-o feature@userobj_accounting=enabled \
|
||||||
|
-o feature@zpool_checkpoint=enabled \
|
||||||
|
-o feature@spacemap_v2=enabled \
|
||||||
|
-o feature@project_quota=enabled \
|
||||||
|
-o feature@resilver_defer=enabled \
|
||||||
|
-o feature@allocation_classes=enabled \
|
||||||
|
-O acltype=posixacl -O canmount=off -O compression=lz4 -O devices=off \
|
||||||
|
-O normalization=formD -O relatime=on -O xattr=sa \
|
||||||
|
-O mountpoint=/ -R /mnt -f \
|
||||||
|
"$bpool" "$raidtype" \
|
||||||
|
$(allpartref "${partBootPool}")
|
||||||
|
|
||||||
|
# create root pool
|
||||||
|
sudo zpool create -o ashift=12 \
|
||||||
|
-O acltype=posixacl -O canmount=off -O compression=lz4 \
|
||||||
|
-O dnodesize=auto -O normalization=formD -O relatime=on -O xattr=sa \
|
||||||
|
-O mountpoint=/ -R /mnt -f \
|
||||||
|
"$rpool" "$raidtype" \
|
||||||
|
$(allpartref "${partRootPool}")
|
||||||
|
|
||||||
|
# create filesystem dataset
|
||||||
|
sudo zfs create -o canmount=off -o mountpoint=none "$rpool/ROOT"
|
||||||
|
sudo zfs create -o canmount=off -o mountpoint=none "$bpool/BOOT"
|
||||||
|
|
||||||
|
# create filesystem dataset for root fs
|
||||||
|
sudo zfs create -o canmount=noauto -o mountpoint=/ "$rpool/ROOT/operating_system"
|
||||||
|
sudo zfs mount $rpool/ROOT/operating_system
|
||||||
|
sudo zfs create -o canmount=noauto -o mountpoint=/boot "$bpool/BOOT/operating_system"
|
||||||
|
sudo zfs mount $bpool/BOOT/operating_system
|
||||||
|
#sudo zpool set bootfs=$rpool/ROOT/operating_system $rpool
|
||||||
|
|
||||||
|
# create datasets for folders
|
||||||
|
sudo zfs create -o setuid=off "$rpool/home"
|
||||||
|
sudo zfs create -o mountpoint=/root "$rpool/home/root"
|
||||||
|
sudo zfs create -o canmount=off -o setuid=off -o exec=off "$rpool/var"
|
||||||
|
sudo zfs create -o canmount=off "$rpool/var/lib"
|
||||||
|
sudo zfs create -o acltype=posixacl -o xattr=sa "$rpool/var/log"
|
||||||
|
sudo zfs create "$rpool/var/mail"
|
||||||
|
sudo zfs create "$rpool/var/spool"
|
||||||
|
|
||||||
|
# Exclude cache and tmp files from snapshots
|
||||||
|
sudo zfs create -o com.sun:auto-snapshot=false "$rpool/var/cache"
|
||||||
|
sudo zfs create -o com.sun:auto-snapshot=false -o exec=on "$rpool/var/tmp"
|
||||||
|
|
||||||
|
# We may be using /usr/local
|
||||||
|
sudo zfs create -o canmount=off "$rpool/usr"
|
||||||
|
sudo zfs create "$rpool/usr/local"
|
||||||
|
|
||||||
|
# We may be using /opt
|
||||||
|
sudo zfs create "$rpool/opt"
|
||||||
|
|
||||||
|
# Do not snapshot ZFS
|
||||||
|
sudo zfs create "$rpool/srv"
|
||||||
|
# sudo zfs create -o com.sun:auto-snapshot=false -o mountpoint=/srv/nfs4 "$rpool/srv/nfs"
|
||||||
|
|
||||||
|
# install system
|
||||||
|
sudo chmod 1777 /mnt/var/tmp
|
||||||
|
|
||||||
|
if [ -z "$codename" ]
|
||||||
|
then
|
||||||
|
case "$system" in
|
||||||
|
debian)
|
||||||
|
codename="$(curl -L https://deb.debian.org/debian/dists/stable/Release | grep -Po '^Codename: \K(.+)$')"
|
||||||
|
;;
|
||||||
|
ubuntu)
|
||||||
|
codename="bionic" # TODO
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Unsupported system: $system" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
sudo eatmydata debootstrap --include=console-setup,eatmydata,ca-certificates,coreutils,gdisk,ssh,zsh,nano,lsb-release "${codename}" /mnt "$mirror"
|
||||||
|
|
||||||
|
sudo zfs set devices=off "$rpool"
|
||||||
|
|
||||||
|
# hostname/hosts configuration
|
||||||
|
echo "${hostname}" | sudo tee /mnt/etc/hostname
|
||||||
|
sudo tee /mnt/etc/hosts <<EOF
|
||||||
|
127.0.0.1 localhost
|
||||||
|
127.0.1.1 ${hostname} ${hostname}.serverkomplex.de
|
||||||
|
|
||||||
|
# The following lines are desirable for IPv6 capable hosts
|
||||||
|
::1 ip6-localhost ip6-loopback
|
||||||
|
fe00::0 ip6-localnet
|
||||||
|
ff00::0 ip6-mcastprefix
|
||||||
|
ff02::1 ip6-allnodes
|
||||||
|
ff02::2 ip6-allrouters
|
||||||
|
ff02::3 ip6-allhosts
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# configure swap
|
||||||
|
sudo zfs create -V 64G -b "$(getconf PAGESIZE)" -o compression=zle \
|
||||||
|
-o logbias=throughput -o sync=always \
|
||||||
|
-o primarycache=metadata -o secondarycache=none \
|
||||||
|
-o com.sun:auto-snapshot=false "$rpool/swap"
|
||||||
|
while [ ! -b "/dev/zvol/$rpool/swap" ]
|
||||||
|
do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
sudo mkswap -f "/dev/zvol/$rpool/swap"
|
||||||
|
echo "/dev/zvol/$rpool/swap none swap defaults 0 0" | sudo tee -a /mnt/etc/fstab >/dev/null
|
||||||
|
sudo mkdir -p /mnt/etc/initramfs-tools/conf.d
|
||||||
|
echo RESUME=none | sudo tee /mnt/etc/initramfs-tools/conf.d/resume >/dev/null
|
||||||
|
|
||||||
|
# prepare for chroot
|
||||||
|
sudo mount --bind /dev /mnt/dev
|
||||||
|
sudo mount --bind /proc /mnt/proc
|
||||||
|
sudo mount --bind /sys /mnt/sys
|
||||||
|
|
||||||
|
# configure
|
||||||
|
codename="$(sudo chroot /mnt lsb_release -cs)"
|
||||||
|
case "$system" in
|
||||||
|
debian)
|
||||||
|
sudo chroot /mnt grep '\bcontrib\b' /etc/apt/sources.list ||\
|
||||||
|
sudo chroot /mnt sed -i 's,\bmain\b,main contrib,g' /etc/apt/sources.list
|
||||||
|
url="https://deb.debian.org/debian"
|
||||||
|
if curl -o /dev/null --fail "${url}/dists/${codename}-backports/Release"
|
||||||
|
then
|
||||||
|
echo "deb ${url} ${codename}-backports main contrib" |\
|
||||||
|
sudo chroot /mnt tee /etc/apt/sources.list.d/backports.list
|
||||||
|
fi
|
||||||
|
success=0
|
||||||
|
for url in \
|
||||||
|
https://deb.debian.org/debian-security \
|
||||||
|
http://security.debian.org
|
||||||
|
do
|
||||||
|
for name in \
|
||||||
|
"${codename}/updates" \
|
||||||
|
"${codename}"
|
||||||
|
do
|
||||||
|
if curl -o /dev/null --fail "${url}/dists/${codename}/updates/Release"
|
||||||
|
then
|
||||||
|
echo "deb ${url} ${name} main contrib" |\
|
||||||
|
sudo chroot /mnt tee /etc/apt/sources.list.d/security.list
|
||||||
|
success=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$success" -ne 0 ]
|
||||||
|
then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
ubuntu)
|
||||||
|
sudo chroot /mnt eatmydata apt update
|
||||||
|
sudo chroot /mnt eatmydata apt install -y software-properties-common
|
||||||
|
sudo chroot /mnt eatmydata apt-add-repository "${mirror}" multiverse universe
|
||||||
|
sudo chroot /mnt ln -s /proc/self/mounts /etc/mtab
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
sudo chroot /mnt eatmydata apt update
|
||||||
|
sudo chroot /mnt eatmydata apt install -y locales
|
||||||
|
sudo chroot /mnt dpkg-reconfigure locales
|
||||||
|
sudo chroot /mnt dpkg-reconfigure tzdata
|
||||||
|
case "$system" in
|
||||||
|
debian)
|
||||||
|
sudo chroot /mnt eatmydata apt install -y linux-headers-amd64 linux-image-amd64
|
||||||
|
;;
|
||||||
|
ubuntu)
|
||||||
|
sudo chroot /mnt eatmydata apt install -y --no-install-recommends linux-image-generic linux-headers-generic
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
sudo chroot /mnt eatmydata apt install -y -t "${codename}-backports" zfsutils-linux zfs-dkms zfs-initramfs
|
||||||
|
sudo chroot /mnt sh -c 'ZPOOL_VDEV_NAME_PATH=YES DEBIAN_NONINTERACTIVE=true eatmydata apt install -y grub-pc'
|
||||||
|
sudo tee /etc/ssh/sshd_config <<EOF
|
||||||
|
# Supported HostKey algorithms by order of preference.
|
||||||
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
|
HostKey /etc/ssh/ssh_host_rsa_key
|
||||||
|
HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||||
|
|
||||||
|
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
|
||||||
|
|
||||||
|
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
||||||
|
|
||||||
|
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
|
||||||
|
|
||||||
|
# Password based logins are disabled - only public key based logins are allowed.
|
||||||
|
AuthenticationMethods publickey
|
||||||
|
|
||||||
|
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
|
||||||
|
LogLevel VERBOSE
|
||||||
|
|
||||||
|
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
|
||||||
|
Subsystem sftp $(sudo chroot /mnt find /usr/lib -name sftp-server -type f -executable) -f AUTHPRIV -l INFO
|
||||||
|
|
||||||
|
# Root login is not allowed for auditing reasons. This is because it's difficult to track which process belongs to which root user:
|
||||||
|
#
|
||||||
|
# On Linux, user sessions are tracking using a kernel-side session id, however, this session id is not recorded by OpenSSH.
|
||||||
|
# Additionally, only tools such as systemd and auditd record the process session id.
|
||||||
|
# On other OSes, the user session id is not necessarily recorded at all kernel-side.
|
||||||
|
# Using regular users in combination with /bin/su or /usr/bin/sudo ensure a clear audit track.
|
||||||
|
PermitRootLogin No
|
||||||
|
|
||||||
|
# Use kernel sandbox mechanisms where possible in unprivileged processes
|
||||||
|
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
|
||||||
|
UsePrivilegeSeparation sandbox
|
||||||
|
EOF
|
||||||
|
if [ -f ~/.ssh/authorized_keys ]; then
|
||||||
|
sudo mkdir -p /mnt/root/.ssh
|
||||||
|
sudo chmod 700 /mnt/root/.ssh
|
||||||
|
cat ~/.ssh/authorized_keys | sudo tee /mnt/root/.ssh/authorized_keys
|
||||||
|
sudo chmod 600 /mnt/root/.ssh/authorized_keys
|
||||||
|
sudo chroot /mnt sed -i 's,PermitRootLogin .\+$,PermitRootLogin prohibit-password,' /etc/ssh/sshd_config
|
||||||
|
echo "Make sure to create a separate user account so you can set PermitRootLogin back to No in /etc/ssh/sshd_config."
|
||||||
|
else
|
||||||
|
# you should definitely change this ASAP!
|
||||||
|
sudo chroot /mnt sed -i 's,PermitRootLogin .\+$,PermitRootLogin yes,' /etc/ssh/sshd_config
|
||||||
|
echo "SSH will have to be secured as root is now accessible with a password."
|
||||||
|
fi
|
||||||
|
sudo chroot /mnt passwd
|
||||||
|
|
||||||
|
# Enable importing bpool
|
||||||
|
sudo tee /mnt/etc/systemd/system/zfs-import-bpool.service <<EOF
|
||||||
|
[Unit]
|
||||||
|
DefaultDependencies=no
|
||||||
|
Before=zfs-import-scan.service
|
||||||
|
Before=zfs-import-cache.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart=/sbin/zpool import -N -o cachefile=none "$bpool"
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=zfs-import.target
|
||||||
|
EOF
|
||||||
|
sudo chroot /mnt systemctl enable zfs-import-bpool.service
|
||||||
|
|
||||||
|
# Mount a tmpfs to /tmp
|
||||||
|
sudo chroot /mnt cp -v /usr/share/systemd/tmp.mount /etc/systemd/system/
|
||||||
|
sudo chroot /mnt systemctl enable tmp.mount
|
||||||
|
|
||||||
|
if ! (sudo chroot /mnt grub-probe /boot | grep '\bzfs\b')
|
||||||
|
then
|
||||||
|
echo "ERROR: Failed to validate that GRUB supports zfs. Aborting." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sudo chroot /mnt update-initramfs -u -k all
|
||||||
|
sudo chroot /mnt sed -e 's#GRUB_CMDLINE_LINUX="\(.*\)"#GRUB_CMDLINE_LINUX="root=ZFS='"$rpool"'/ROOT/operating_system \1"#' -i /etc/default/grub
|
||||||
|
sudo chroot /mnt update-grub
|
||||||
|
for d in "${disks[@]}"
|
||||||
|
do
|
||||||
|
sudo chroot /mnt sh -c "ZPOOL_VDEV_NAME_PATH=YES grub-install '${d}'"
|
||||||
|
done
|
||||||
|
if [ "$(sudo chroot /mnt find /boot/grub -name zfs.mod | wc -l)" -lt 1 ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Installed GRUB does not seem to have ZFS module. Aborting." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# fix filesystem mount ordering
|
||||||
|
sudo zfs set mountpoint=legacy "$bpool/BOOT/operating_system"
|
||||||
|
sudo tee -a /mnt/etc/fstab <<EOF
|
||||||
|
$bpool/BOOT/operating_system /boot zfs nodev,relatime,x-systemd.requires=zfs-import-bpool.service 0 0
|
||||||
|
EOF
|
||||||
|
sudo mkdir -p /mnt/etc/zfs/zfs-list.cache
|
||||||
|
#sudo mkdir -p /etc/zfs/zfs-list.cache
|
||||||
|
sudo touch "/mnt/etc/zfs/zfs-list.cache/$rpool"
|
||||||
|
#sudo touch "/etc/zfs/zfs-list.cache/$rpool"
|
||||||
|
sudo chroot /mnt ln -sf /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
|
||||||
|
#sudo ln -sf /mnt/usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
|
||||||
|
zedpidfile=$(mktemp -p /mnt/var/tmp)
|
||||||
|
zedpidfile_chroot="${zedpidfile#/mnt}"
|
||||||
|
sudo chroot /mnt zed -p "${zedpidfile_chroot}"
|
||||||
|
echo "Waiting for ZFS cache to be written…"
|
||||||
|
sleep 5
|
||||||
|
until [ "$(cat /mnt/etc/zfs/zfs-list.cache/$rpool)" != "" ]
|
||||||
|
do
|
||||||
|
#sudo zfs set canmount=noauto "$rpool/ROOT/operating_system"
|
||||||
|
sleep 3
|
||||||
|
done
|
||||||
|
sudo chroot /mnt kill "$(cat "${zedpidfile}")"
|
||||||
|
sudo sleep 2
|
||||||
|
sudo rm -f "${zedpidfile}"
|
||||||
|
#sudo cp -a /etc/zfs/zfs-list.cache/* /mnt/etc/zfs/zfs-list.cache/
|
||||||
|
# Fix paths to eliminate /mnt
|
||||||
|
sudo sed -Ei "s|/mnt/?|/|" "/mnt/etc/zfs/zfs-list.cache/$rpool"
|
||||||
|
|
||||||
|
# configure networking
|
||||||
|
|
||||||
|
# nicht funktionierend:
|
||||||
|
# sudo tee /mnt/etc/netplan/eth0.yaml <<"EOF"
|
||||||
|
# network:
|
||||||
|
# version: 2
|
||||||
|
# ethernets:
|
||||||
|
# eth0:
|
||||||
|
# dhcp4: true
|
||||||
|
# EOF
|
||||||
|
|
||||||
|
# online.net:
|
||||||
|
# sudo tee /mnt/etc/network/interfaces <<"EOF"
|
||||||
|
# auto lo
|
||||||
|
# iface lo inet loopback
|
||||||
|
#
|
||||||
|
# auto eno1
|
||||||
|
# iface eno1 inet static
|
||||||
|
# address 51.15.19.177
|
||||||
|
# netmask 255.255.255.0
|
||||||
|
# gateway 51.15.19.1
|
||||||
|
# EOF
|
||||||
|
|
||||||
|
# hetzner:
|
||||||
|
sudo mkdir -p /mnt/etc/systemd/network
|
||||||
|
gateway="$(ip -br r s default | awk '{print $3}')"
|
||||||
|
dev="$(ip -br r s default | awk '{print $5}')"
|
||||||
|
ip=$(ip -br a s dev "$dev" | awk '{print $3}')
|
||||||
|
mac="$(ip -br link show "$dev" | awk '{print $3}')"
|
||||||
|
dnssection=""
|
||||||
|
grep -Po '\d+.\d+.\d+.\d+' /etc/resolv.conf | while read -r ip
|
||||||
|
do
|
||||||
|
dnssection="$dnssection"$'\n'"DNS=$ip"
|
||||||
|
done
|
||||||
|
sudo tee /mnt/etc/systemd/network/10-ethernet.network <<EOF
|
||||||
|
[Match]
|
||||||
|
MACAddress=${mac}
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
Gateway=${gateway}
|
||||||
|
#Address=[IP RANGE]::2/64
|
||||||
|
#Gateway=fe80::1
|
||||||
|
${dnssection}
|
||||||
|
|
||||||
|
[Address]
|
||||||
|
Address=${ip}
|
||||||
|
Peer=${gateway}/32
|
||||||
|
EOF
|
||||||
|
sudo chroot /mnt systemctl enable systemd-networkd
|
||||||
|
#sudo chroot /mnt systemctl enable systemd-resolved
|
||||||
|
#sudo tee /mnt/etc/netplan/01-netcfg.yaml <<"EOF"
|
||||||
|
## network is managed by systemd-networkd
|
||||||
|
#EOF
|
||||||
|
sudo tee /mnt/etc/default/cpufrequtils <<"EOF"
|
||||||
|
# cpu frequency scaling
|
||||||
|
ENABLE="true"
|
||||||
|
GOVENOR="ondemand"
|
||||||
|
MAX_SPEED="0"
|
||||||
|
MIN_SPEED="0"
|
||||||
|
EOF
|
||||||
|
sudo tee /mnt/etc/sysctl.d/99-hetzner.conf <<"EOF"
|
||||||
|
# sysctl config
|
||||||
|
#net.ipv4.ip_forward=1
|
||||||
|
net.ipv4.conf.all.rp_filter=1
|
||||||
|
net.ipv4.icmp_echo_ignore_broadcasts=1
|
||||||
|
# ipv6 settings (no autoconfiguration)
|
||||||
|
net.ipv6.conf.default.autoconf=0
|
||||||
|
net.ipv6.conf.default.accept_dad=0
|
||||||
|
net.ipv6.conf.default.accept_ra=0
|
||||||
|
net.ipv6.conf.default.accept_ra_defrtr=0
|
||||||
|
net.ipv6.conf.default.accept_ra_rtr_pref=0
|
||||||
|
net.ipv6.conf.default.accept_ra_pinfo=0
|
||||||
|
net.ipv6.conf.default.accept_source_route=0
|
||||||
|
net.ipv6.conf.default.accept_redirects=0
|
||||||
|
net.ipv6.conf.all.autoconf=0
|
||||||
|
net.ipv6.conf.all.accept_dad=0
|
||||||
|
net.ipv6.conf.all.accept_ra=0
|
||||||
|
net.ipv6.conf.all.accept_ra_defrtr=0
|
||||||
|
net.ipv6.conf.all.accept_ra_rtr_pref=0
|
||||||
|
net.ipv6.conf.all.accept_ra_pinfo=0
|
||||||
|
net.ipv6.conf.all.accept_source_route=0
|
||||||
|
net.ipv6.conf.all.accept_redirects=0
|
||||||
|
EOF
|
||||||
|
sudo tee /mnt/etc/modprobe.d/blacklist-hetzner.conf <<"EOF"
|
||||||
|
### silence any onboard speaker
|
||||||
|
blacklist pcspkr
|
||||||
|
blacklist snd_pcsp
|
||||||
|
### i915 driver blacklisted due to various bugs
|
||||||
|
### especially in combination with nomodeset
|
||||||
|
blacklist i915
|
||||||
|
blacklist i915_bdw
|
||||||
|
### mei driver blacklisted due to serious bugs
|
||||||
|
blacklist mei
|
||||||
|
blacklist mei-me
|
||||||
|
blacklist sm750fb
|
||||||
|
EOF
|
||||||
|
#sudo chroot /mnt rm -f /etc/resolv.conf
|
||||||
|
sudo chroot /mnt tee /etc/resolv.conf < /etc/resolv.conf > /dev/null
|
||||||
|
#sudo chroot /mnt ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
|
||||||
|
#sudo chroot /mnt systemctl enable systemd-resolved.service
|
||||||
|
|
||||||
|
sudo chroot /mnt zfs snapshot "$bpool/BOOT/operating_system@install"
|
||||||
|
sudo chroot /mnt zfs snapshot "$rpool/ROOT/operating_system@install"
|
||||||
|
|
||||||
|
sudo chroot /mnt hostnamectl set-hostname "${hostname}" ||\
|
||||||
|
(printf "%s" "${hostname}" | sudo chroot /mnt tee /etc/hostname >/dev/null)
|
||||||
|
|
||||||
|
sudo chroot /mnt bash -i
|
||||||
|
|
||||||
|
# unmount
|
||||||
|
sudo umount -l /mnt/dev
|
||||||
|
sudo umount -l /mnt/proc
|
||||||
|
sudo umount -l /mnt/sys
|
||||||
|
#mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | xargs -i{} sudo umount -lf {}
|
||||||
|
sudo zpool export "$bpool"
|
||||||
|
sudo zpool export "$rpool"
|
||||||
|
|
||||||
|
echo "Installation done."
|
Loading…
Reference in New Issue