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