192 lines
6.8 KiB
Bash
192 lines
6.8 KiB
Bash
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
###############################################################################
|
||
# WARNING: THIS SCRIPT ERASES DATA!
|
||
#
|
||
# This script will:
|
||
# 1. Identify all internal (nonremovable) SSD and NVMe disks, excluding the
|
||
# live USB from which Ubuntu is booted.
|
||
# 2. Wipe their partition tables.
|
||
# 3. On the first detected disk, create:
|
||
# - a 1 GB EFI partition (formatted FAT32, flagged as ESP)
|
||
# - a ~19 GB partition for Ubuntu root (formatted ext4)
|
||
# - if any space remains, a partition covering the rest (formatted btrfs)
|
||
# 4. On every other disk, create one partition spanning the entire disk and
|
||
# format it as btrfs.
|
||
#
|
||
# Double‐check that you want to wipe all these disks BEFORE you run this script.
|
||
###############################################################################
|
||
|
||
# Ensure the script is run as root.
|
||
if [ "$EUID" -ne 0 ]; then
|
||
echo "This script must be run as root."
|
||
exit 1
|
||
fi
|
||
|
||
# Helper: given a device like /dev/sda1 or /dev/nvme0n1p1, return the base device.
|
||
get_base_device() {
|
||
local dev="$1"
|
||
if [[ "$dev" =~ ^/dev/nvme.*p[0-9]+$ ]]; then
|
||
# For NVMe devices, remove the trailing 'pX'
|
||
echo "$dev" | sed -E 's/p[0-9]+$//'
|
||
else
|
||
# For /dev/sdX type devices, remove trailing numbers
|
||
echo "$dev" | sed -E 's/[0-9]+$//'
|
||
fi
|
||
}
|
||
|
||
# Helper: given a disk (e.g. /dev/sda or /dev/nvme0n1) and a partition number,
|
||
# print the proper partition name.
|
||
get_partition_name() {
|
||
local disk="$1"
|
||
local partnum="$2"
|
||
if [[ "$disk" =~ nvme ]]; then
|
||
echo "${disk}p${partnum}"
|
||
else
|
||
echo "${disk}${partnum}"
|
||
fi
|
||
}
|
||
|
||
# Determine the boot device (i.e. the device from which the live system is running)
|
||
boot_dev_full=$(findmnt -n -o SOURCE /)
|
||
boot_disk=$(get_base_device "$boot_dev_full")
|
||
echo "Detected boot device (from /): $boot_dev_full"
|
||
echo "Base boot disk (will be used for Ubuntu install): $boot_disk"
|
||
|
||
# Now, enumerate candidate target disks.
|
||
# We will scan /sys/block for devices starting with "sd" or "nvme".
|
||
target_disks=()
|
||
|
||
# Loop over sd* and nvme* disks.
|
||
for dev_path in /sys/block/sd* /sys/block/nvme*; do
|
||
[ -e "$dev_path" ] || continue
|
||
disk_name=$(basename "$dev_path")
|
||
disk="/dev/$disk_name"
|
||
|
||
# Skip removable devices (e.g. USB sticks)
|
||
if [ "$(cat "$dev_path/removable")" -ne 0 ]; then
|
||
continue
|
||
fi
|
||
|
||
# Skip disks that are rotational (i.e. likely HDD) if you want only SSD/NVMe.
|
||
# (Usually SSD/NVMe have rotational=0.)
|
||
if [ -f "$dev_path/queue/rotational" ]; then
|
||
if [ "$(cat "$dev_path/queue/rotational")" -ne 0 ]; then
|
||
continue
|
||
fi
|
||
fi
|
||
|
||
# Add disk to list.
|
||
target_disks+=("$disk")
|
||
done
|
||
|
||
# Ensure the boot disk is in our list. (It will be partitioned for Ubuntu.)
|
||
if [[ ! " ${target_disks[@]} " =~ " ${boot_disk} " ]]; then
|
||
# Check if boot_disk qualifies (nonremovable and nonrotational)
|
||
disk_dir="/sys/block/$(basename "$boot_disk")"
|
||
if [ -f "$disk_dir/removable" ] && [ "$(cat "$disk_dir/removable")" -eq 0 ]; then
|
||
if [ -f "$disk_dir/queue/rotational" ] && [ "$(cat "$disk_dir/queue/rotational")" -eq 0 ]; then
|
||
target_disks=("$boot_disk" "${target_disks[@]}")
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
if [ "${#target_disks[@]}" -eq 0 ]; then
|
||
echo "No qualifying internal SSD/NVMe disks found."
|
||
exit 1
|
||
fi
|
||
|
||
echo
|
||
echo "The following disks will be wiped and re-partitioned:"
|
||
for disk in "${target_disks[@]}"; do
|
||
echo " $disk"
|
||
done
|
||
echo
|
||
read -p "ARE YOU SURE YOU WANT TO PROCEED? This will permanently erase all data on these disks (type 'yes' to continue): " answer
|
||
if [ "$answer" != "yes" ]; then
|
||
echo "Aborting."
|
||
exit 1
|
||
fi
|
||
|
||
###############################################################################
|
||
# Wipe all target disks.
|
||
###############################################################################
|
||
for disk in "${target_disks[@]}"; do
|
||
echo "Wiping partition table on $disk..."
|
||
sgdisk --zap-all "$disk"
|
||
# Overwrite beginning of disk (optional but recommended)
|
||
dd if=/dev/zero of="$disk" bs=512 count=2048 status=none
|
||
# Overwrite end of disk (ignoring errors if size is too small)
|
||
total_sectors=$(blockdev --getsz "$disk")
|
||
dd if=/dev/zero of="$disk" bs=512 count=2048 seek=$(( total_sectors - 2048 )) status=none 2>/dev/null || true
|
||
done
|
||
|
||
###############################################################################
|
||
# Partition the FIRST disk for Ubuntu installation.
|
||
###############################################################################
|
||
boot_install_disk="${target_disks[0]}"
|
||
echo
|
||
echo "Partitioning boot/install disk: $boot_install_disk"
|
||
parted -s "$boot_install_disk" mklabel gpt
|
||
|
||
# Create EFI partition: from 1MiB to 1025MiB (~1GB).
|
||
parted -s "$boot_install_disk" mkpart ESP fat32 1MiB 1025MiB
|
||
parted -s "$boot_install_disk" set 1 esp on
|
||
|
||
# Create root partition: from 1025MiB to 21025MiB (~20GB total for install).
|
||
parted -s "$boot_install_disk" mkpart primary ext4 1025MiB 21025MiB
|
||
|
||
# Determine if there’s any space left.
|
||
disk_size_bytes=$(blockdev --getsize64 "$boot_install_disk")
|
||
# Calculate 21025MiB in bytes.
|
||
min_install_bytes=$((21025 * 1024 * 1024))
|
||
if [ "$disk_size_bytes" -gt "$min_install_bytes" ]; then
|
||
echo "Creating additional partition on $boot_install_disk for btrfs (using remaining space)..."
|
||
parted -s "$boot_install_disk" mkpart primary btrfs 21025MiB 100%
|
||
boot_disk_partitions=(1 2 3)
|
||
else
|
||
boot_disk_partitions=(1 2)
|
||
fi
|
||
|
||
# Format the partitions on the boot/install disk.
|
||
efi_part=$(get_partition_name "$boot_install_disk" 1)
|
||
root_part=$(get_partition_name "$boot_install_disk" 2)
|
||
|
||
echo "Formatting EFI partition ($efi_part) as FAT32..."
|
||
mkfs.fat -F32 "$efi_part"
|
||
|
||
echo "Formatting root partition ($root_part) as ext4..."
|
||
mkfs.ext4 -F "$root_part"
|
||
|
||
# If a third partition exists, format it as btrfs.
|
||
if [ "${boot_disk_partitions[2]:-}" ]; then
|
||
btrfs_part=$(get_partition_name "$boot_install_disk" 3)
|
||
echo "Formatting extra partition ($btrfs_part) as btrfs..."
|
||
mkfs.btrfs -f "$btrfs_part"
|
||
fi
|
||
|
||
###############################################################################
|
||
# Partition all OTHER target disks entirely as btrfs.
|
||
###############################################################################
|
||
if [ "${#target_disks[@]}" -gt 1 ]; then
|
||
echo
|
||
echo "Partitioning remaining disks for btrfs:"
|
||
for disk in "${target_disks[@]:1}"; do
|
||
echo "Processing disk $disk..."
|
||
parted -s "$disk" mklabel gpt
|
||
parted -s "$disk" mkpart primary btrfs 1MiB 100%
|
||
# Determine the partition name (e.g. /dev/sdb1 or /dev/nvme0n1p1).
|
||
if [[ "$disk" =~ nvme ]]; then
|
||
part="${disk}p1"
|
||
else
|
||
part="${disk}1"
|
||
fi
|
||
echo "Formatting $part as btrfs..."
|
||
mkfs.btrfs -f "$part"
|
||
done
|
||
fi
|
||
|
||
echo
|
||
echo "All operations complete. Ubuntu install partitions and btrfs volumes have been created."
|