|
|
|
@ -35,7 +35,7 @@ if [[ ${#active_ttys} -gt 1 ]]; then
|
|
|
|
|
else
|
|
|
|
|
echo "Found more than one graphical TTY!"
|
|
|
|
|
echo -n "If you wish to run the installer on this graphical TTY, press enter within 60 seconds... "
|
|
|
|
|
if ! read -t 60; then
|
|
|
|
|
if ! read -t 60 _d; then
|
|
|
|
|
echo "timeout."
|
|
|
|
|
echo "To launch the installer again on this TTY, run '/install.sh'."
|
|
|
|
|
exit 0
|
|
|
|
@ -49,6 +49,9 @@ fi
|
|
|
|
|
printf "PID $$ on TTY ${this_tty}" > ${lockfile}
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
# Stop all existing networking for a fresh slate
|
|
|
|
|
service networking stop &>/dev/null
|
|
|
|
|
|
|
|
|
|
# Set the target consoles in the installed image
|
|
|
|
|
target_consoles=""
|
|
|
|
|
for tty in $( echo -e "$( sed 's/ /\n/g' <<<"${active_ttys[@]}" )" | sort ); do
|
|
|
|
@ -73,7 +76,7 @@ default_filesystem="ext4"
|
|
|
|
|
|
|
|
|
|
supported_debrelease="buster bullseye bookworm"
|
|
|
|
|
default_debrelease="bookworm"
|
|
|
|
|
default_debmirror="http://mirror.csclub.uwaterloo.ca/debian"
|
|
|
|
|
default_debmirror="http://ftp.debian.org/debian"
|
|
|
|
|
|
|
|
|
|
# Base packages (installed by debootstrap)
|
|
|
|
|
basepkglist="lvm2,parted,gdisk,sudo,vim,gpg,gpg-agent,openssh-server,vlan,ifenslave,python3,ca-certificates,curl"
|
|
|
|
@ -310,6 +313,10 @@ interactive_config() {
|
|
|
|
|
echo " then re-running it by calling /install.sh in the resulting shell."
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo "| Section 1: System Hostname |"
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo
|
|
|
|
|
echo "1) Please enter a fully-qualified hostname for the system. This should match the hostname"
|
|
|
|
|
echo "in the 'pvc-ansible' inventory."
|
|
|
|
|
while [[ -z ${target_hostname} ]]; do
|
|
|
|
@ -337,13 +344,20 @@ interactive_config() {
|
|
|
|
|
done
|
|
|
|
|
)"
|
|
|
|
|
|
|
|
|
|
echo "2a) Please enter the disk to install the PVC base system to. This disk will be"
|
|
|
|
|
echo "wiped, an LVM PV created on it, and the system installed to this LVM."
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo "| Section 2: Disk setup |"
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo
|
|
|
|
|
echo "2a) Please enter the disk to install the PVC base system to. This disk will be WIPED,"
|
|
|
|
|
echo "an LVM PV created on it, and the system installed to this LVM."
|
|
|
|
|
echo
|
|
|
|
|
echo "* NOTE: PVC requires a disk of at least 30GB to be installed to, and 100GB is the"
|
|
|
|
|
echo "recommended minimum size for optimal production partition sizes."
|
|
|
|
|
echo "* NOTE: For optimal performance, this disk should be high-performance flash (SSD, etc.)."
|
|
|
|
|
echo "* NOTE: This disk should be a RAID-1 volume configured in hardware, or a durable storage"
|
|
|
|
|
echo "device, maximum redundancy and resiliency."
|
|
|
|
|
echo
|
|
|
|
|
echo "* NOTE: This disk should be high-performance flash (SSD, etc.)."
|
|
|
|
|
echo
|
|
|
|
|
echo "* NOTE: This disk should be a RAID-1 volume configured in hardware, or a very durable"
|
|
|
|
|
echo "storage device, for maximum redundancy and resiliency."
|
|
|
|
|
echo
|
|
|
|
|
echo "Available disks:"
|
|
|
|
|
echo
|
|
|
|
@ -387,20 +401,30 @@ interactive_config() {
|
|
|
|
|
echo
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo "| Section 3: Networking |"
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
echo -n "Probing interfaces... "
|
|
|
|
|
for interface in $( ip address | grep '^[0-9]' | grep 'eno\|enp\|ens\|wlp' | awk '{ print $2 }' | tr -d ':' ); do
|
|
|
|
|
ip link set ${interface} up
|
|
|
|
|
done
|
|
|
|
|
sleep 2
|
|
|
|
|
sleep 5
|
|
|
|
|
interfaces="$(
|
|
|
|
|
ip address | grep '^[0-9]' | grep 'eno\|enp\|ens\|wlp' | awk '{ print $2"\t"$3 }' | tr -d ':'
|
|
|
|
|
)"
|
|
|
|
|
echo "done."
|
|
|
|
|
|
|
|
|
|
echo "Available interfaces:"
|
|
|
|
|
echo
|
|
|
|
|
echo -e "$( sed 's/\(.*\)/ \1/' <<<"${interfaces[@]}" )"
|
|
|
|
|
echo
|
|
|
|
|
echo "3a) Please enter the primary network interface for external connectivity. If"
|
|
|
|
|
echo "no entries are shown here, ensure a cable is connected, then restart the"
|
|
|
|
|
echo "installer with ^C and '/install.sh'."
|
|
|
|
|
echo
|
|
|
|
|
echo "Available interfaces:"
|
|
|
|
|
echo
|
|
|
|
|
echo -e "$( sed 's/\(.*\)/ \1/' <<<"${interfaces[@]}" )"
|
|
|
|
|
echo "If you want a bonding interface, please enter 'bond' here."
|
|
|
|
|
while [[ -z ${target_interface} ]]; do
|
|
|
|
|
echo
|
|
|
|
|
echo -n "> "
|
|
|
|
@ -410,7 +434,7 @@ interactive_config() {
|
|
|
|
|
echo "Please enter a valid interface."
|
|
|
|
|
continue
|
|
|
|
|
fi
|
|
|
|
|
if ! grep -qw "${target_interface}" <<<"${interfaces[@]}"; then
|
|
|
|
|
if [[ ${target_interface} != "bond" ]] && ! grep -qw "${target_interface}" <<<"${interfaces[@]}"; then
|
|
|
|
|
target_interface=""
|
|
|
|
|
echo
|
|
|
|
|
echo "Please enter a valid interface."
|
|
|
|
@ -419,7 +443,77 @@ interactive_config() {
|
|
|
|
|
echo
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo -n "3b) Is a tagged vLAN required for the primary network interface? [y/N] "
|
|
|
|
|
if [[ ${target_interface} == "bond" ]]; then
|
|
|
|
|
target_interface=""
|
|
|
|
|
echo "3b) Please enter the name of the bonding interface (e.g. 'bond0'). This"
|
|
|
|
|
echo "should match the interface you will use in the pvc-ansible configuration if"
|
|
|
|
|
echo "applicable and MUST start with 'bond'."
|
|
|
|
|
echo
|
|
|
|
|
while [[ -z ${target_interface} ]]; do
|
|
|
|
|
echo -n "> "
|
|
|
|
|
read target_interface
|
|
|
|
|
if [[ -z ${target_interface} ]]; then
|
|
|
|
|
echo
|
|
|
|
|
echo "Please enter a valid interface."
|
|
|
|
|
continue
|
|
|
|
|
fi
|
|
|
|
|
if ! grep -q '^bond' <<<"${target_interface}"; then
|
|
|
|
|
echo
|
|
|
|
|
echo "Please enter a valid interface."
|
|
|
|
|
continue
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
echo "3c) Please enter the bonding mode for the interface (e.g. '802.3ad' or"
|
|
|
|
|
echo "'active-backup'). This mode must be valid or the networking will fail."
|
|
|
|
|
echo
|
|
|
|
|
while [[ -z ${bonding_mode} ]]; do
|
|
|
|
|
echo -n "> "
|
|
|
|
|
read bonding_mode
|
|
|
|
|
if [[ -z ${bonding_mode} ]]; then
|
|
|
|
|
echo
|
|
|
|
|
echo "Please enter a valid bonding mode."
|
|
|
|
|
continue
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
echo "3d) Please enter the space-separated slave interfaces from the list above."
|
|
|
|
|
echo
|
|
|
|
|
while [[ -z ${slave_interfaces} ]]; do
|
|
|
|
|
echo -n "> "
|
|
|
|
|
read slave_interfaces
|
|
|
|
|
if [[ -z ${slave_interfaces} ]]; then
|
|
|
|
|
echo
|
|
|
|
|
echo "Please enter a valid list of slave interfaces."
|
|
|
|
|
continue
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
echo -n "Bringing up bond interface... "
|
|
|
|
|
ip link add ${target_interface} type bond
|
|
|
|
|
ip link set ${target_interface} type bond mode ${bonding_mode}
|
|
|
|
|
for slave_interface in ${slave_interfaces}; do
|
|
|
|
|
ip link set ${slave_interface} down
|
|
|
|
|
ip link set ${slave_interface} master ${target_interface}
|
|
|
|
|
ip link set ${slave_interface} up
|
|
|
|
|
done
|
|
|
|
|
ip link set ${target_interface} up
|
|
|
|
|
echo "done."
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
next_prompt_1="3e"
|
|
|
|
|
next_prompt_2="3f"
|
|
|
|
|
next_prompt_3="3g"
|
|
|
|
|
else
|
|
|
|
|
next_prompt_1="3b"
|
|
|
|
|
next_prompt_2="3c"
|
|
|
|
|
next_prompt_3="3g"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo -n "${next_prompt_1}) Is a tagged vLAN required for the primary network interface? [y/N] "
|
|
|
|
|
read vlans_req
|
|
|
|
|
if [[ ${vlans_req} == 'y' || ${vlans_req} == 'Y' ]]; then
|
|
|
|
|
echo
|
|
|
|
@ -440,7 +534,7 @@ interactive_config() {
|
|
|
|
|
echo
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "3c) Please enter the IP address, in CIDR format [X.X.X.X/YY], of the primary"
|
|
|
|
|
echo "${next_prompt_2}) Please enter the IP address, in CIDR format [X.X.X.X/YY], of the primary"
|
|
|
|
|
echo "network interface. Leave blank for DHCP configuration of the interface on boot."
|
|
|
|
|
echo
|
|
|
|
|
echo -n "> "
|
|
|
|
@ -448,7 +542,7 @@ interactive_config() {
|
|
|
|
|
if [[ -n ${target_ipaddr} ]]; then
|
|
|
|
|
target_netformat="static"
|
|
|
|
|
echo
|
|
|
|
|
echo "3d) Please enter the default gateway IP address of the primary"
|
|
|
|
|
echo "${next_prompt_3}) Please enter the default gateway IP address of the primary"
|
|
|
|
|
echo "network interface."
|
|
|
|
|
while [[ -z ${target_defgw} ]]; do
|
|
|
|
|
echo
|
|
|
|
@ -519,6 +613,10 @@ EOF
|
|
|
|
|
echo "done."
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo "| Section 4: Debian Configuration |"
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo
|
|
|
|
|
echo "4a) Please enter an alternate Debian release codename for the system if desired."
|
|
|
|
|
echo " Supported: ${supported_debrelease}"
|
|
|
|
|
echo " Default: ${default_debrelease}"
|
|
|
|
@ -566,6 +664,10 @@ EOF
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
target_keys_method="wget"
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo "| Section 5: SSH Setup |"
|
|
|
|
|
echo "--------------------------------------------------------"
|
|
|
|
|
echo
|
|
|
|
|
echo "5) Please enter an HTTP URL containing a text list of SSH authorized keys to"
|
|
|
|
|
echo "fetch. These keys will be allowed access to the deployment user '${target_deploy_user}'"
|
|
|
|
|
echo "via SSH."
|
|
|
|
@ -617,6 +719,7 @@ case ${install_option} in
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
titlestring_text="| Proceeding with installation of host '${target_hostname}'. |"
|
|
|
|
|
titlestring_len="$(( $( wc -c <<<"${titlestring_text}" ) - 2 ))"
|
|
|
|
|
for i in $( seq 0 ${titlestring_len} ); do echo -n "-"; done; echo
|
|
|
|
@ -776,16 +879,29 @@ echo "Command: debootstrap --include=${basepkglist} ${debrelease} ${target}/ ${d
|
|
|
|
|
debootstrap --include=${basepkglist} ${debrelease} ${target}/ ${debmirror} >&2
|
|
|
|
|
echo "done."
|
|
|
|
|
|
|
|
|
|
echo -n "Adding non-free repository (firmware, etc.)... "
|
|
|
|
|
case ${debrelease} in
|
|
|
|
|
buster)
|
|
|
|
|
non_free="non-free"
|
|
|
|
|
;;
|
|
|
|
|
bullseye)
|
|
|
|
|
non_free="non-free"
|
|
|
|
|
# python-is-python3 is critical for bullsye
|
|
|
|
|
suppkglist="python-is-python3,${suppkglist}"
|
|
|
|
|
;;
|
|
|
|
|
bookworm)
|
|
|
|
|
# Use non-free-firmware component instead of non-free
|
|
|
|
|
non_free="non-free-firmware"
|
|
|
|
|
# python-is-python3 is critical for bullsye
|
|
|
|
|
suppkglist="python-is-python3,${suppkglist}"
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
echo -n "Adding ${non_free} APT component (firmware, etc.)... "
|
|
|
|
|
mkdir -p ${target}/etc/apt/sources.list.d/ >&2
|
|
|
|
|
echo "deb ${debmirror} ${debrelease} contrib non-free" | tee -a ${target}/etc/apt/sources.list >&2
|
|
|
|
|
echo "deb ${debmirror} ${debrelease} contrib ${non_free}" | tee -a ${target}/etc/apt/sources.list >&2
|
|
|
|
|
chroot ${target} apt-get update >&2
|
|
|
|
|
echo "done."
|
|
|
|
|
|
|
|
|
|
# python-is-python3 is critical for bullsye
|
|
|
|
|
if [[ ${debrelease} != "buster" ]]; then
|
|
|
|
|
suppkglist="python-is-python3,${suppkglist}"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo -n "Installing supplemental packages... "
|
|
|
|
|
chroot ${target} apt-get install -y --no-install-recommends $( sed 's/,/ /g' <<<"${suppkglist}" ) >&2
|
|
|
|
@ -827,17 +943,26 @@ interactive_interfaces_segment() {
|
|
|
|
|
case ${target_interfaces_is} in
|
|
|
|
|
static-vlan)
|
|
|
|
|
target_interfaces_block="auto ${vlan_interface}\niface ${vlan_interface} inet ${target_netformat}\n\tvlan_raw_device ${target_interface}\n\taddress ${formatted_ipaddr}\n\tnetmask ${formatted_netmask}\n\tgateway ${target_defgw}"
|
|
|
|
|
if [[ -n ${slave_interfaces} ]]; then
|
|
|
|
|
target_interfaces_block="${target_interfaces_block}\n\nauto ${target_interface}\niface ${target_interface} inet manual"
|
|
|
|
|
fi
|
|
|
|
|
;;
|
|
|
|
|
static-raw)
|
|
|
|
|
target_interfaces_block="auto ${target_interface}\niface ${target_interface} inet ${target_netformat}\n\taddress ${formatted_ipaddr}\n\tnetmask ${formatted_netmask}\n\tgateway ${target_defgw}"
|
|
|
|
|
;;
|
|
|
|
|
dhcp-vlan)
|
|
|
|
|
target_interfaces_block="auto ${vlan_interface}\niface ${vlan_interface} inet ${target_netformat}\n\tvlan_raw_device${target_interface}"
|
|
|
|
|
if [[ -n ${slave_interfaces} ]]; then
|
|
|
|
|
target_interfaces_block="${target_interfaces_block}\n\nauto ${target_interface}\niface ${target_interface} inet manual"
|
|
|
|
|
fi
|
|
|
|
|
;;
|
|
|
|
|
dhcp-raw)
|
|
|
|
|
target_interfaces_block="auto ${target_interface}\niface ${target_interface} inet ${target_netformat}"
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
if [[ -n ${slave_interfaces} ]]; then
|
|
|
|
|
target_interfaces_block="${target_interfaces_block}\n\tbond-mode ${bonding_mode}\n\tbond-slaves ${slave_interfaces}"
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
echo -n "Creating bootstrap interface segment... "
|
|
|
|
@ -1014,7 +1139,7 @@ seed_postinst() {
|
|
|
|
|
interactive_postinst() {
|
|
|
|
|
set +o errexit
|
|
|
|
|
echo
|
|
|
|
|
echo -n "Launch a chroot shell in the target environment? [y/N] "
|
|
|
|
|
echo -n "Launch a chroot shell in the target environment? (NOTE: no shell prompt) [y/N] "
|
|
|
|
|
read launch_chroot
|
|
|
|
|
if [[ ${launch_chroot} == 'y' || ${launch_chroot} == 'Y' ]]; then
|
|
|
|
|
echo "Type 'exit' or Ctrl+D to exit chroot."
|
|
|
|
|