#!/bin/sh # Vars ## Define the hard drive to use if [ -b '/dev/sda' ]; then hdd="/dev/sda" else printf '%b\n' "Please check the hard drive to use" exit 0 fi ## Which version of Debian should be installed debian_version="bullseye" ## Computer hostname ## If empty, the script will try to get one with nslookup new_hostname="" ## Volume Group name to use for LVM vgname="${new_hostname}vg" ## If the script should manage the partitions (delete, add,…) manage_part=0 ## If the script should use BTRFS manage_btrfs=1 ## If the script should create extra volume (eg. backup, virt, Proxmox,…) manage_extra_lv=0 ## If the script should cipher data with LUKS manage_luks=1 ## You need to set a new passphrase after the installation or at least change this one luks_passphrase="generic key" luks_key_file="/tmp/luks.keyfile.temp" luks_pv_name=$(basename "${hdd}"_crypt) ## If the script should manage everything (partition, package,…) related to grub manage_grub=0 ## Colors definition {{{ BLACK='\033[49;30m' BLACKB='\033[49;90m' RED='\033[0;31m' REDB='\033[1;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[94;49m' MAGENTA='\033[0;35m' CYAN='\033[36;49m' WHITE='\033[0;37m' BOLD='\033[1m' RESET='\033[0m' ## }}} ## Package to exclude from debootstrap install dbs_pkg_exclude="vim-tiny" ## Package to include to debootstrap install dbs_pkg_include="aptitude,btrfs-progs,bzip2,cryptsetup,debconf-i18n,dialog,dmsetup,htop,isc-dhcp-client,isc-dhcp-common,locales,lvm2,openssh-server,pciutils,thin-provisioning-tools,tmux,vim-nox,wget,zsh" # Prepare host system {{{ apt update apt install -y coreutils e2fsprogs gawk ipcalc lvm2 thin-provisioning-tools parted util-linux wget || exit 1 ## Install a recent version of debootstrap wget http://ftp.de.debian.org/debian/pool/main/d/debootstrap/debootstrap_1.0.114_all.deb -O /tmp/debootstrap.deb dpkg -i /tmp/debootstrap.deb || exit 2 ## Install a recent version of debian-archive-keyring wget http://ftp.de.debian.org/debian/pool/main/d/debian-archive-keyring/debian-archive-keyring_2019.1+deb10u1_all.deb -O /tmp/debian-archive-keyring.deb dpkg -i /tmp/debian-archive-keyring.deb || exit 3 # }}} # Partitionning {{{ if [ "${manage_part}" -eq 0 ]; then ## Remove all old partitions {{{ for part_number in 1 2 3 4 5 6 7 8; do [ -b "${hdd}""${part_number}" ] && parted "${hdd}" rm "${part_number}" done ## }}} ## Recreate partition (/boot and LV) {{{ ### Partition type parted "${hdd}" mklabel gpt || exit 1 if [ "${manage_grub}" -eq 0 ]; then ### /boot parted "${hdd}" mkpart primary 0% 512MB || exit 1 parted "${hdd}" set 1 boot on sleep 2 mkfs.ext3 -F -L boot -- "${hdd}"1 || exit 4 ### LV root_part_id="2" parted "${hdd}" mkpart primary 512MB 100% || exit 1 parted "${hdd}" set "${root_part_id}" lvm on sleep 2 else ### LV root_part_id="1" parted "${hdd}" mkpart primary 0% 100% || exit 1 parted "${hdd}" set "${root_part_id}" lvm on sleep 2 fi if [ "${manage_luks}" -eq 0 ]; then rm -f -- "${luks_key_file}" && printf '%b' "${luks_passphrase}" > "${luks_key_file}" cryptsetup -c aes-xts-plain64 -s 512 --use-random -y luksFormat "${hdd}${root_part_id}" "${luks_passphrase}" --key-file "${luks_key_file}" || exit 2 cryptsetup luksOpen "${hdd}${root_part_id}" "${luks_pv_name}" --key-file "${luks_key_file}" || exit 2 pvcreate /dev/mapper/"${luks_pv_name}" || exit 3 vgcreate "${vgname}" /dev/mapper/"${luks_pv_name}" || exit 3 else pvcreate "${hdd}${root_part_id}" || exit 3 vgcreate "${vgname}" "${hdd}${root_part_id}" || exit 3 fi ## }}} ## Create Logical Volumes {{{ if [ "${manage_btrfs}" -eq 0 ]; then ### Create only 1 LV for btrfs base system [ ! -b /dev/mapper/"${vgname}"-root ] && lvcreate -n root -L 70g "${vgname}" else ### Otherwise create differents LVs [ ! -b /dev/mapper/"${vgname}"-home ] && lvcreate -n home -L 20g "${vgname}" [ ! -b /dev/mapper/"${vgname}"-opt ] && lvcreate -n opt -L 2g "${vgname}" [ ! -b /dev/mapper/"${vgname}"-root ] && lvcreate -n root -L 5g "${vgname}" [ ! -b /dev/mapper/"${vgname}"-srv ] && lvcreate -n srv -L 2g "${vgname}" [ ! -b /dev/mapper/"${vgname}"-tmp ] && lvcreate -n tmp -L 10g "${vgname}" [ ! -b /dev/mapper/"${vgname}"-usr ] && lvcreate -n usr -L 15g "${vgname}" [ ! -b /dev/mapper/"${vgname}"-var ] && lvcreate -n var -L 10g "${vgname}" fi ### Create extra LVs if [ "${manage_extra_lv}" -eq 0 ]; then [ ! -b /dev/mapper/"${vgname}"-vz ] && lvcreate -n vz -L 150g "${vgname}" [ ! -b /dev/mapper/"${vgname}"-bkp ] && lvcreate -n bkp -L 150g "${vgname}" fi [ ! -b /dev/mapper/"${vgname}"-swap ] && lvcreate -n swap -L 4g "${vgname}" ## }}} ## Format Logical Volumes {{{ ### Format LVs in ext4 cd -- /dev/"${vgname}" || exit 1 for lvname in *; do mkfs.ext4 -F -L "${lvname}" -- "${lvname}" || exit 4 done cd -- - || exit 1 ### (re)format Btrfs LV if [ "${manage_btrfs}" -eq 0 ]; then ### Ensure to format Btrfs LV mkfs.btrfs --force -L root -- /dev/"${vgname}"/root || exit 4 fi ### And format the swap mkswap -L sw01 -- /dev/mapper/"${vgname}"-swap || exit 4 ## }}} fi # }}} # Debootstrap {{{ ## Create and mount the system {{{ ### Root mkdir -p -- /target mountpoint -q /target || mount -- /dev/mapper/"${vgname}"-root /target if [ "${manage_grub}" -eq 0 ]; then ### boot - grub mkdir -p -- /target/boot mountpoint -q /target/boot || mount -- ${hdd}1 /target/boot boot_uuid=$(blkid | grep "${hdd}1" | sed 's/.*1.*UUID="\(.*\)" TYPE.*/\1/') ### Prepare an fstab file printf '%b\n' "UUID=${boot_uuid} /boot ext3 defaults 0 0" > /tmp/target.fstab fi ### Prepare the base system tree according to the expected file system if [ "${manage_btrfs}" -eq 0 ]; then #### Download an extra script for Btrfs wget -O /tmp/part.btrfs.sh "https://git.101010.fr/gardouille-dotfiles/scripts/raw/master/debian/part.btrfs.sh" #### Create several subvolumes chmod +x /tmp/part.btrfs.sh && /tmp/part.btrfs.sh #### root grep "btrfs" /etc/mtab >> /tmp/target.fstab else ### Or for ext4, create mountpoint and mount LV #### root printf '%b\n' "/dev/mapper/${vgname}-root / ext4 defaults 0 0" >> /tmp/target.fstab #### home LV mkdir -p -- /target/home mountpoint -q /target/home || mount -- /dev/mapper/"${vgname}"-home /target/home printf '%b\n' "/dev/mapper/${vgname}-home /home ext4 defaults 0 0" >> /tmp/target.fstab #### opt LV mkdir -p -- /target/opt mountpoint -q /target/opt || mount -- /dev/mapper/"${vgname}"-opt /target/opt printf '%b\n' "/dev/mapper/${vgname}-opt /opt ext4 defaults 0 0" >> /tmp/target.fstab #### srv LV mkdir -p -- /target/srv mountpoint -q /target/srv || mount -- /dev/mapper/"${vgname}"-srv /target/srv printf '%b\n' "/dev/mapper/${vgname}-srv /srv ext4 defaults 0 0" >> /tmp/target.fstab #### tmp LV mkdir -p -- /target/tmp chmod 0777 -- /target/tmp mountpoint -q /target/tmp || mount -- /dev/mapper/"${vgname}"-tmp /target/tmp printf '%b\n' "/dev/mapper/${vgname}-tmp /tmp ext4 defaults 0 0" >> /tmp/target.fstab #### usr LV mkdir -p -- /target/usr mountpoint -q /target/usr || mount -- /dev/mapper/"${vgname}"-usr /target/usr printf '%b\n' "/dev/mapper/${vgname}-usr /usr ext4 defaults 0 0" >> /tmp/target.fstab #### var LV mkdir -p -- /target/var mountpoint -q /target/var || mount -- /dev/mapper/"${vgname}"-var /target/var printf '%b\n' "/dev/mapper/${vgname}-var /var ext4 defaults 0 0" >> /tmp/target.fstab fi ### Ensure to remove any occurence to /target mountpoint sed -i 's;target/;;' /tmp/target.fstab sed -i 's;target;;' /tmp/target.fstab if [ "${manage_extra_lv}" -eq 0 ]; then ### Extra bkp LV mkdir -p -- /target/srv/backup mountpoint -q /target/srv/backup || mount -- /dev/mapper/"${vgname}"-bkp /target/srv/backup printf '%b\n' "/dev/mapper/${vgname}-bkp /srv/backup ext4 defaults 0 0" >> /tmp/target.fstab ### Extra vz LV mkdir -p -- /target/var/lib/vz mountpoint -q /target/var/lib/vz || mount -- /dev/mapper/"${vgname}"-vz /target/var/lib/vz printf '%b\n' "/dev/mapper/${vgname}-vz /var/lib/vz ext4 defaults 0 0" >> /tmp/target.fstab fi ### Swap swapon -- /dev/mapper/"${vgname}"-swap ## }}} ## Run debootstrap debootstrap --arch amd64 --include="${dbs_pkg_include}" --exclude="${dbs_pkg_exclude}" "${debian_version}" /target http://ftp.fr.debian.org/debian || exit 1 # }}} # Configure system {{{ ## Fstab {{{ ### Copy the temp fstab file to target cp -- /tmp/target.fstab /target/etc/fstab ## }}} ## Ensure to (re)mount devices for chroot {{{ mkdir -p -- /target/dev mountpoint -q /target/dev || mount -t devtmpfs -- none /target/dev mkdir -p -- /target/dev/pts mountpoint -q /target/dev/pts || mount -t devpts -- /dev/pts /target/dev/pts mkdir -p -- /target/proc mountpoint -q /target/proc || mount -t proc -- none /target/proc mkdir -p -- /target/sys mountpoint -q /target/sys || mount -t sysfs -- none /target/sys ### FIXME : /run/lvm needs to be manually set in debootstrap|chroot for Buster {{{ ### See : ### https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=918590 ### https://bbs.archlinux.org/viewtopic.php?pid=1820949#p1820949 mkdir -p -- /target/run/lvm mountpoint -q /target/run/lvm || mount --bind -- /run/lvm /target/run/lvm mkdir -p -- /target/run/udev mountpoint -q /target/run/udev || mount --bind -- /run/udev /target/run/udev ### }}} ## }}} ## Luks {{{ if [ "${manage_luks}" -eq 0 ]; then luks_part_uuid=$(blkid | grep "${hdd}2.*TYPE=\"crypto_LUKS\"" | sed 's/.*UUID="\(.*\)" TYPE.*/\1/') ### Ensure crypttab file contains the LUKS informations printf '%b\n' "${luks_pv_name} UUID=${luks_part_uuid} none luks,discard" >> /target/etc/crypttab fi ### Regenerate initramfs chroot /target update-initramfs -k all -u ## }}} ## Network {{{ ### Get all informations from current network configuration in rescue mode net_device=$(ip r | grep "^default" | head -1 | cut -d" " -f5) #### TODO: Switch to ip a to get ip address net_address=$(ip r | grep -vE "(^default|metric)" | grep "${net_device}.*src" | head -1 | awk -F" " '{print $NF}') read -r net_mac_address /target/etc/systemd/network/50-default.network ### Ensure to enable systemd-networkd at startup chroot /target systemctl enable systemd-networkd ## }}} ## Locale {{{ ### Enable locale(s) sed -i 's/^# \(en_US.UTF-8 UTF-8\)/\1/' /target/etc/locale.gen #sed -i 's/^# \(fr_FR.UTF-8 UTF-8\)/\1/' /target/etc/locale.gen chroot /target locale-gen ## }}} ## Timezone {{{ ### Set timezone printf '%b\n' "Europe/Paris" > /target/etc/timezone ln -fs /usr/share/zoneinfo/Europe/Paris /target/etc/localtime chroot /target dpkg-reconfigure --frontend noninteractive tzdata ## }}} ## Kernel and Grub {{{ ### Install if [ "${manage_grub}" -eq 0 ]; then chroot /target aptitude install --assume-yes --without-recommends -- linux-image-amd64 grub-pc chroot /target grub-install "${hdd}" chroot /target update-grub else chroot /target aptitude install --assume-yes --without-recommends -- linux-image-amd64 fi ## }}} ## Hostname {{{ if [ -z "${new_hostname}" ]; then lookup_hostname=$(nslookup "${net_address}" || echo "server name = new_server") get_hostname=$(echo "${lookup_hostname}" | awk '/name =/{print $4;}' | cut -d. -f1) printf '%b\n' "${get_hostname}" > /target/etc/hostname else printf '%b\n' "${new_hostname}" > /target/etc/hostname fi #printf '%b\n' "127.0.0.1 ${new_hostname}" >> /target/etc/hosts ## }}} # }}} # Finish {{{ ## Call a latecommand script {{{ wget -O /tmp/latecommand.tar.gz "https://git.ipr.univ-rennes1.fr/cellinfo/tftpboot/raw/master/scripts/latecommand.tar.gz" --no-check-certificate tar xzf /tmp/latecommand.tar.gz -C /target/tmp/ chroot /target /usr/bin/env debian_version="${debian_version}" /bin/sh /tmp/latecommand/post."${debian_version}".sh ## }}} ## SSH {{{ ### Allow root connections - this should be fixed if it works sed -i 's/\(^\|^\#\)\(PermitRootLogin\).*/\2 yes/g' /target/etc/ssh/sshd_config ### Add current authorized_keys from the rescue system if present if [ -f /root/.ssh/authorized_keys ]; then mkdir -p -- /target/root/.ssh cp -- /root/.ssh/authorized_keys /target/root/.ssh/authorized_keys else printf '%b\n' "${REDB}You might want to define an authorized key for SSH/root in /target/etc/ssh/sshd_config${RESET}" fi ## }}} printf '%b\n' "${REDB}Please change the root's password :${RESET}" chroot /target passwd # Ensure to umount everything #umount /target/var/lib/vz/ /target/var/ /target/usr/ /target/tmp/ /target/sys/ /target/srv/backup/ /target/srv/ /target/proc/ /target/opt/ /target/home/ /target/dev/pts/ /target/dev /target/boot/ /target/ printf '%b\n' "${GREEN}The system is still available on /target but you can now try to reboot the hardware.${RESET}" exit 0 # }}}