Created
February 24, 2026 18:37
-
-
Save 0xdeafbeef/9600e57e130a7ab557f9d8a46624f247 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| usage() { | |
| cat <<'EOF' | |
| Usage: | |
| sudo ./fedora-disk-setup.sh /dev/<disk> [--swap-size 34G] [--efi-size 600M] [--boot-size 1G] [--no-mount] [--yes] | |
| Examples: | |
| sudo ./fedora-disk-setup.sh /dev/nvme0n1 | |
| sudo ./fedora-disk-setup.sh /dev/sda --swap-size 32G --yes | |
| EOF | |
| } | |
| need() { command -v "$1" >/dev/null 2>&1 || { echo "Missing: $1"; exit 1; }; } | |
| DISK="${1:-}" | |
| [[ -z "${DISK}" || "${DISK}" == "-h" || "${DISK}" == "--help" ]] && usage && exit 0 | |
| shift || true | |
| EFI_SIZE="600M" | |
| BOOT_SIZE="1G" | |
| SWAP_SIZE="" # empty => auto (RAM + 2G) | |
| DO_MOUNT=1 | |
| ASSUME_YES=0 | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| --efi-size) EFI_SIZE="${2:?}"; shift 2 ;; | |
| --boot-size) BOOT_SIZE="${2:?}"; shift 2 ;; | |
| --swap-size) SWAP_SIZE="${2:?}"; shift 2 ;; | |
| --no-mount) DO_MOUNT=0; shift ;; | |
| --yes) ASSUME_YES=1; shift ;; | |
| *) echo "Unknown arg: $1"; usage; exit 1 ;; | |
| esac | |
| done | |
| [[ -b "${DISK}" ]] || { echo "Not a block device: ${DISK}"; exit 1; } | |
| need sgdisk | |
| need wipefs | |
| need mkfs.fat | |
| need mkfs.ext4 | |
| need mkswap | |
| need mkfs.btrfs | |
| need lsblk | |
| need partprobe | |
| need findmnt | |
| # Compute swap size if not provided: RAM + 2G (rounded up to GiB) | |
| if [[ -z "${SWAP_SIZE}" ]]; then | |
| mem_kib=$(awk '/MemTotal:/ {print $2}' /proc/meminfo) | |
| mem_gib=$(( (mem_kib + 1024*1024 - 1) / (1024*1024) )) | |
| swap_gib=$(( mem_gib + 2 )) | |
| SWAP_SIZE="${swap_gib}G" | |
| fi | |
| # Partition naming helper (nvme0n1p1 vs sda1) | |
| part() { | |
| local n="$1" | |
| if [[ "${DISK}" =~ [0-9]$ ]]; then | |
| echo "${DISK}p${n}" | |
| else | |
| echo "${DISK}${n}" | |
| fi | |
| } | |
| echo "About to WIPE and repartition: ${DISK}" | |
| lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT "${DISK}" || true | |
| echo | |
| echo "Layout:" | |
| echo " 1) EFI : ${EFI_SIZE} (FAT32) -> /boot/efi" | |
| echo " 2) /boot: ${BOOT_SIZE} (ext4) -> /boot" | |
| echo " 3) swap : ${SWAP_SIZE} (swap) -> hibernation" | |
| echo " 4) root : rest (btrfs) -> / (subvol root, home)" | |
| echo | |
| if [[ "${ASSUME_YES}" -ne 1 ]]; then | |
| read -r -p "Type YES to continue: " ans | |
| [[ "${ans}" == "YES" ]] || { echo "Aborted."; exit 1; } | |
| fi | |
| # Safety: refuse if any partitions are mounted | |
| if findmnt -rn -S "${DISK}" >/dev/null 2>&1; then | |
| echo "Some part of ${DISK} is mounted. Unmount first." | |
| exit 1 | |
| fi | |
| # Best-effort swapoff if this disk contains swap currently | |
| for s in $(swapon --noheadings --raw | awk '{print $1}' | grep -E "^${DISK}" || true); do | |
| sudo swapoff "$s" || true | |
| done | |
| echo "Wiping signatures + partition table..." | |
| wipefs -a "${DISK}" | |
| sgdisk --zap-all "${DISK}" | |
| echo "Creating GPT partitions..." | |
| sgdisk -n1:1MiB:+"${EFI_SIZE}" -t1:EF00 -c1:"EFI" "${DISK}" | |
| sgdisk -n2:0:+"${BOOT_SIZE}" -t2:8300 -c2:"boot" "${DISK}" | |
| sgdisk -n3:0:+"${SWAP_SIZE}" -t3:8200 -c3:"swap" "${DISK}" | |
| sgdisk -n4:0:0 -t4:8300 -c4:"root" "${DISK}" | |
| partprobe "${DISK}" | |
| P1="$(part 1)" | |
| P2="$(part 2)" | |
| P3="$(part 3)" | |
| P4="$(part 4)" | |
| echo "Formatting..." | |
| mkfs.fat -F32 -n EFI "${P1}" | |
| mkfs.ext4 -F -L boot "${P2}" | |
| mkswap -L swap "${P3}" | |
| mkfs.btrfs -f -L fedora "${P4}" | |
| if [[ "${DO_MOUNT}" -eq 1 ]]; then | |
| echo "Creating Btrfs subvolumes + mounting to /mnt..." | |
| mkdir -p /mnt | |
| mount "${P4}" /mnt | |
| btrfs subvolume create /mnt/root >/dev/null | |
| btrfs subvolume create /mnt/home >/dev/null | |
| umount /mnt | |
| mount -o subvol=root,compress=zstd:1 "${P4}" /mnt | |
| mkdir -p /mnt/{home,boot,boot/efi} | |
| mount -o subvol=home,compress=zstd:1 "${P4}" /mnt/home | |
| mount "${P2}" /mnt/boot | |
| mount "${P1}" /mnt/boot/efi | |
| swapon "${P3}" | |
| echo | |
| echo "Done. Mounted under /mnt:" | |
| findmnt /mnt /mnt/home /mnt/boot /mnt/boot/efi || true | |
| echo | |
| echo "Swap enabled:" | |
| swapon --show | |
| else | |
| echo "Done. (Not mounted; --no-mount)" | |
| fi | |
| echo | |
| echo "Next steps (after installing Fedora):" | |
| echo " - Add resume=UUID=<swap-uuid> to kernel cmdline (for hibernation resume)" | |
| echo " - Consider disabling zram if you want predictable hibernation behavior" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment