|
@@ -0,0 +1,295 @@
|
|
|
+#!/bin/bash -e
|
|
|
+#----------
|
|
|
+# Interactive installation steps for Debian Bullseye from GRML using debootstrap
|
|
|
+
|
|
|
+# Design decisions
|
|
|
+# - Fokus on a simple setup, primarly for VMs
|
|
|
+# - One disk, one partion, swap-file in the same partion as safety net
|
|
|
+# - Use systemd whereever possible (network, ntp, cron, journald logging)
|
|
|
+# - Minimal number of packages & cloud kernel
|
|
|
+# - grub-pc, not efi
|
|
|
+# - random root and admin user password generation
|
|
|
+# - ssh on port 50101 limited to the admin user
|
|
|
+
|
|
|
+# Usage
|
|
|
+# # Boot grml
|
|
|
+# passwd root
|
|
|
+# grml-network
|
|
|
+# Start ssh
|
|
|
+# git clone https://git.in-ulm.de/ulpeters/bootstrap.git
|
|
|
+# cp config.sh.template config.sh # copy template
|
|
|
+# config-get-netconf-eth0.sh # get running grml network config
|
|
|
+# vi config.sh # update installation variables
|
|
|
+# bootstrap-bullseye.sh install # start installation
|
|
|
+# !! Note down the admin passwords and reboot
|
|
|
+# sudo /installer/bootstrap-bullseye.sh postinstall # run postinstall in the new system
|
|
|
+
|
|
|
+# Variables
|
|
|
+mnt="/mnt/root" # mountpoint for the new root filesystem
|
|
|
+hostname="somehost.example.com"
|
|
|
+disk="/dev/vda" # lsblk --list
|
|
|
+disk1=$disk"1"
|
|
|
+netDev="eth0" # ip link
|
|
|
+netAddress="203.0.113.66/24"
|
|
|
+netGateway="203.0.113.1"
|
|
|
+netBroadcast="203.0.113.255"
|
|
|
+netDNS1="192.0.2.10"
|
|
|
+netDNS2="198.51.100.10"
|
|
|
+netNTP="pool.ntp.org"
|
|
|
+extraPackages=""
|
|
|
+
|
|
|
+[ -f ./config.sh ] && source config.sh
|
|
|
+
|
|
|
+
|
|
|
+# Setup network in grml
|
|
|
+grmlnetwork(){
|
|
|
+ip link show # list interfaces
|
|
|
+ip addr add $netAddress dev $netDev
|
|
|
+ip link set $netDev up
|
|
|
+ip route add default via $netGateway
|
|
|
+echo nameserver $netDNS1 >> /etc/resolv.conf
|
|
|
+echo nameserver $netDNS2 >> /etc/resolv.conf
|
|
|
+}
|
|
|
+
|
|
|
+install(){
|
|
|
+#----------
|
|
|
+# Prepare disks
|
|
|
+# Parition disks -- pkg: parted
|
|
|
+parted $disk -s \
|
|
|
+mklabel msdos \
|
|
|
+mkpart primary ext4 512M 100% toggle 1 boot
|
|
|
+fdisk -l $disk
|
|
|
+
|
|
|
+# Format disks -- pkg: e2fsprogs dosfstools and to file system check
|
|
|
+mkfs.ext4 $disk1 && e2fsck $disk1
|
|
|
+
|
|
|
+# Prepare mount points and mount
|
|
|
+mkdir -p $mnt
|
|
|
+mount $disk1 $mnt
|
|
|
+
|
|
|
+# Create swapfile
|
|
|
+swapfile=$mnt/swapfile
|
|
|
+dd if=/dev/zero of=$swapfile bs=1M count=1024 status=progress # create 1GB file
|
|
|
+chmod 600 $swapfile #restric permissions
|
|
|
+mkswap $swapfile #format file
|
|
|
+
|
|
|
+#----------
|
|
|
+# Bootstrap -- pkg: debootstrap
|
|
|
+# Remark: Debootstrap does not install recommands!!
|
|
|
+debootstrap --variant=minbase --arch=amd64 bullseye $mnt http://ftp2.de.debian.org/debian/
|
|
|
+
|
|
|
+#----------
|
|
|
+# Configuration
|
|
|
+# Configure disk mounts
|
|
|
+# Or get UUID from blkid...
|
|
|
+cat >$mnt/etc/fstab <<EOL
|
|
|
+$disk1 / ext4 rw 0 0
|
|
|
+/swapfile none swap defaults 0 0
|
|
|
+EOL
|
|
|
+
|
|
|
+# Configure sources.list
|
|
|
+cat >$mnt/etc/apt/sources.list <<EOL
|
|
|
+deb http://ftp2.de.debian.org/debian bullseye main contrib non-free
|
|
|
+#deb-src http://ftp2.de.debian.org/debian bullseye main contrib non-free
|
|
|
+deb http://deb.debian.org/debian-security/ bullseye-security main contrib non-free
|
|
|
+#deb-src http://deb.debian.org/debian-security/ bullseye-security main contrib non-free
|
|
|
+deb http://ftp2.de.debian.org/debian bullseye-updates main contrib non-free
|
|
|
+#deb-src http://ftp2.de.debian.org/debian bullseye-updates main contrib non-free
|
|
|
+EOL
|
|
|
+
|
|
|
+# Configure hostname
|
|
|
+echo "127.0.0.1 $hostname" >> $mnt/etc/hosts
|
|
|
+echo "$hostname" > $mnt/etc/hostname
|
|
|
+
|
|
|
+#----------
|
|
|
+# Prepare chroot
|
|
|
+mount -o bind /dev $mnt/dev
|
|
|
+mount -o bind /dev/pts $mnt/dev/pts
|
|
|
+mount -t sysfs /sys $mnt/sys
|
|
|
+mount -t proc /proc $mnt/proc
|
|
|
+cp /proc/mounts $mnt/etc/mtab
|
|
|
+cp /etc/resolv.conf $mnt/etc/resolv.conf
|
|
|
+mkdir -p $mnt/installer
|
|
|
+cp $(dirname `realpath $0`)/*.sh $mnt/installer
|
|
|
+
|
|
|
+# Run script in chroot
|
|
|
+chroot $mnt /bin/bash /installer/bootstrap-bullseye.sh install2
|
|
|
+
|
|
|
+# Install bootloader
|
|
|
+$0 bootloader
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#----------
|
|
|
+# Function executed within chroot
|
|
|
+install2(){
|
|
|
+source /installer/config.sh
|
|
|
+# Install basic system
|
|
|
+apt-get update
|
|
|
+apt-get install --yes \
|
|
|
+ apt-utils dialog msmtp-mta \
|
|
|
+ systemd-sysv locales tzdata haveged \
|
|
|
+ linux-image-cloud-amd64 grub-pc \
|
|
|
+ iproute2 netbase \
|
|
|
+ ssh sudo molly-guard \
|
|
|
+ less vim-tiny bash-completion pwgen lsof \
|
|
|
+ dnsutils iputils-ping curl \
|
|
|
+ $extraPackages
|
|
|
+
|
|
|
+# Upgrade and clean up
|
|
|
+apt-get upgrade --yes
|
|
|
+apt-get autoremove --yes
|
|
|
+apt-get clean --yes
|
|
|
+
|
|
|
+# Setup users and passwords
|
|
|
+[ -z $pwdAdmin ] && pwdAdmin=`pwgen --capitalize --numerals --ambiguous 12 1`
|
|
|
+useradd admin --create-home --shell /bin/bash
|
|
|
+echo "admin:$pwdAdmin" | chpasswd
|
|
|
+usermod -a -G sudo admin
|
|
|
+echo -e "\e[1;33;4;44mPassword for the user admin: $pwdAdmin\e[0m"
|
|
|
+pass=`pwgen --capitalize --numerals --ambiguous 12 1`
|
|
|
+[ -z $pwdRoot ] && pwdRoot=`pwgen --capitalize --numerals --ambiguous 12 1`
|
|
|
+echo "root:$pwdRoot" | chpasswd
|
|
|
+echo -e "\e[1;33;4;44mPassword for the user root: $pwdRoot\e[0m"
|
|
|
+
|
|
|
+# Harden SSHD
|
|
|
+sed -i -e 's/#Port 22/Port 50101/g' /etc/ssh/sshd_config
|
|
|
+sed -i -e 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config
|
|
|
+# https://infosec.mozilla.org/guidelines/openssh.html
|
|
|
+
|
|
|
+
|
|
|
+# Allow admin to sudo without password
|
|
|
+echo AllowUsers admin >> /etc/ssh/sshd_config
|
|
|
+echo "admin ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/admin
|
|
|
+
|
|
|
+## Configure network using systemd
|
|
|
+if [ -z $netAddress ]
|
|
|
+then
|
|
|
+## Network OPTION 1 - DHCP
|
|
|
+cat >/etc/systemd/network/20-wired.network <<EOL
|
|
|
+[Match]
|
|
|
+Name=e*
|
|
|
+
|
|
|
+[Network]
|
|
|
+DHCP=ipv4
|
|
|
+IPv6PrivacyExtensions=false
|
|
|
+IPv6AcceptRA=false
|
|
|
+NTP=$netNTP
|
|
|
+EOL
|
|
|
+
|
|
|
+else
|
|
|
+## Network OPTION 2 - static
|
|
|
+cat >/etc/systemd/network/20-wired.network <<EOL
|
|
|
+[Match]
|
|
|
+Name=$netDev
|
|
|
+
|
|
|
+[Network]
|
|
|
+Address=$netAddress
|
|
|
+Gateway=$netGateway
|
|
|
+Broadcast=$netBroadcast
|
|
|
+DNS=$netDNS1
|
|
|
+DNS=$netDNS2
|
|
|
+NTP=$netNTP
|
|
|
+EOL
|
|
|
+fi
|
|
|
+
|
|
|
+# Setup systemd resolver
|
|
|
+rm /etc/resolv.conf
|
|
|
+ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
|
|
|
+systemctl enable systemd-networkd
|
|
|
+# to be checked why port 5353 is opened externally
|
|
|
+sed -i 's/#LLMNR=yes/LLMNR=no/' /etc/systemd/resolved.conf
|
|
|
+systemctl enable systemd-resolved
|
|
|
+
|
|
|
+# Limit journald logging to 1 month, 1 GB in total and split files per week
|
|
|
+mkdir -p /etc/systemd/journald.conf.d/
|
|
|
+cat >/etc/systemd/journald.conf.d/retention.conf <<EOL
|
|
|
+MaxRetentionSec=1month
|
|
|
+SystemMaxUse=1G
|
|
|
+MaxFileSec=1week
|
|
|
+EOL
|
|
|
+
|
|
|
+# Show errors in motd
|
|
|
+rm /etc/motd
|
|
|
+cat >/etc/update-motd.d/15-boot-errors<<EOL
|
|
|
+#!/bin/sh
|
|
|
+echo
|
|
|
+journalctl --boot --priority=3 --no-pager
|
|
|
+EOL
|
|
|
+chmod 755 /etc/update-motd.d/15-boot-errors
|
|
|
+
|
|
|
+# Setup keyboard layout
|
|
|
+cat >/etc/default/keyboard <<EOL
|
|
|
+XKBMODEL="pc105"
|
|
|
+XKBLAYOUT="de"
|
|
|
+XKBVARIANT="nodeadkeys"
|
|
|
+XKBOPTIONS=""
|
|
|
+BACKSPACE="guess"
|
|
|
+EOL
|
|
|
+
|
|
|
+# Leave chroot
|
|
|
+exit
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bootloader(){
|
|
|
+# Install GRUB in /dev/vba
|
|
|
+chroot $mnt /bin/bash -c "grub-install $disk && update-grub"
|
|
|
+}
|
|
|
+
|
|
|
+unmount(){
|
|
|
+# Unmount if mounted
|
|
|
+! mountpoint -q $mnt/proc || umount $mnt/proc
|
|
|
+! mountpoint -q $mnt/sys || umount $mnt/sys
|
|
|
+! mountpoint -q $mnt/dev/pts || umount $mnt/dev/pts
|
|
|
+! mountpoint -q $mnt/dev || umount $mnt/dev
|
|
|
+! mountpoint -q $mnt/root || umount $mnt/root
|
|
|
+! mountpoint -q $mnt || umount $mnt
|
|
|
+# Delete mount-point if empty and not mounted
|
|
|
+[ -z "$(ls -A /mnt/)" ] && ! mountpoint -q $mnt && rm -R $mnt
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+postinstall(){
|
|
|
+####----REBOOT into the new system, so we'll have dbus running
|
|
|
+localectl set-locale LANG=de_DE.UTF-8 # Default for LC_* variables not set.
|
|
|
+localectl set-locale LC_MESSAGES=en_US.UTF-8 # System messages.
|
|
|
+#localectl set-locale LC_RESPONSE=en_US.UTF-8 # How responses (such as Yes and No) appear
|
|
|
+update-locale
|
|
|
+timedatectl set-timezone Europe/Berlin
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+# Switch to functions...
|
|
|
+case $1 in
|
|
|
+ grmlnetwork)
|
|
|
+ echo Setup network in grml
|
|
|
+ grmlnetwork
|
|
|
+ ;;
|
|
|
+ install)
|
|
|
+ echo "Stage 1: Start installation"
|
|
|
+ install
|
|
|
+ ;;
|
|
|
+ install2)
|
|
|
+ echo "Stage 2: Start installation in chroot"
|
|
|
+ install2
|
|
|
+ ;;
|
|
|
+ bootloader)
|
|
|
+ echo "Stage 3: Install bootloader and unmount chroot"
|
|
|
+ bootloader
|
|
|
+ unmount
|
|
|
+ echo "We're done and can reboot now"
|
|
|
+ ;;
|
|
|
+ postinstall)
|
|
|
+ echo "Stage 4: Start post-installation in live system"
|
|
|
+ postinstall
|
|
|
+ ;;
|
|
|
+ unmount)
|
|
|
+ echo "Unmount chroot, e.g. in case installation fails"
|
|
|
+ unmount
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ echo "Valid functions are: grmlnetwork, install, postinstall and unmount" >&2
|
|
|
+ ;;
|
|
|
+esac
|