grub auto-installer for PCI SSD Sticks
We express a powerful script that will allow us to install grub into all the partitions setting them to always boot your PCI SSD!
In this script we want to do automatic redirection in that no matter what partition boots - it will redirect to the target partition. In this case we have:
- /dev/sda1 (100 GB SSD)
- /dev/sdb1 (30 GB SSD)
- /dev/nvme0n1p1 (1 TB PCI Stick)
An automatic installation script would look as:
Below is a complete, professional Bash script that installs GRUB on the specified partitions (/dev/sda2 and /dev/sdb1) and configures it to boot the root filesystem located on /dev/nvme0n1p1.
Important prerequisites and warnings
- The script must be run as root (using
sudoor from a root shell). - All target devices must exist and be unmounted (except the running root if it is on
/dev/nvme0n1p1). - The root filesystem on
/dev/nvme0n1p1must contain a valid/bootdirectory with kernel and initramfs images. - A temporary mount point (
/mnt/root) is used; ensure it does not contain valuable data. - Backup critical data before proceeding—modifying bootloaders can render systems unbootable.
- The script assumes an EFI System Partition (ESP) is present on
/dev/nvme0n1p1(or elsewhere) and that UEFI firmware is in use. If you are using legacy BIOS, remove the--removableand EFI-specific flags.
#!/bin/bash
#=====================================================================
# GRUB Installation Script
# Targets: /dev/sda2 and /dev/sdb1
# Root filesystem: /dev/nvme0n1p1
# Author: Assistant (generated for professional use)
#=====================================================================
set -euo pipefail
# -------------------------- Configuration --------------------------
TARGET_DISKS_PARTS=( "/dev/sda2" "/dev/sdb1" )
ROOT_PART="/dev/nvme0n1p1"
MOUNT_POINT="/mnt/root"
GRUB_EFI_DIR="/boot/efi" # Inside the mounted root
GRUB_MODULES="ext2 part_gpt part_msdos" # Adjust if needed
# ------------------------------------------------------------------
log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*"; }
# Validate root privileges
if [[ $EUID -ne 0 ]]; then
log "ERROR: This script must be run as root."
exit 1
fi
# Validate target partitions
for part in "${TARGET_DISKS_PARTS[@]}"; do
if [[ ! -b "$part" ]]; then
log "ERROR: Partition $part does not exist."
exit 1
fi
done
if [[ ! -b "$ROOT_PART" ]]; then
log "ERROR: Root partition $ROOT_PART does not exist."
exit 1
fi
# Create mount point
mkdir -p "$MOUNT_POINT"
# Mount root filesystem
log "Mounting $ROOT_PART on $MOUNT_POINT ..."
mount "$ROOT_PART" "$MOUNT_POINT"
# Verify essential boot files exist
if [[ ! -d "$MOUNT_POINT/boot" ]]; then
log "ERROR: /boot directory not found on $ROOT_PART."
umount "$MOUNT_POINT"
exit 1
fi
# -------------------------- GRUB Installation Loop ----------------
for target in "${TARGET_DISKS_PARTS[@]}"; do
log "Processing target partition: $target"
# Determine if target is an EFI partition (type EF00) or legacy
part_type=$(lsblk -no PTTYPE "$target" 2>/dev/null || echo "unknown")
if [[ "$part_type" == "gpt" ]]; then
is_efi=$(lsblk -no PARTTYPENAME "$target" | grep -i "EFI System")
else
is_efi=""
fi
# Prepare bind mounts for chroot environment
mount --bind /dev "$MOUNT_POINT/dev"
mount --bind /proc "$MOUNT_POINT/proc"
mount --bind /sys "$MOUNT_POINT/sys"
mount --bind /run "$MOUNT_POINT/run"
# Install GRUB
if [[ -n "$is_efi" ]]; then
log " -> Installing GRUB in EFI mode on $target"
# Ensure ESP is mounted inside chroot
mkdir -p "$MOUNT_POINT$GRUB_EFI_DIR"
mount "$target" "$MOUNT_POINT$GRUB_EFI_DIR"
chroot "$MOUNT_POINT" /bin/bash -c "
grub-install --target=x86_64-efi \
--efi-directory=$GRUB_EFI_DIR \
--bootloader-id=GRUB \
--modules='$GRUB_MODULES' \
--recheck
"
# Optional: install as removable (fallback)
chroot "$MOUNT_POINT" /bin/bash -c "
grub-install --target=x86_64-efi \
--efi-directory=$GRUB_EFI_DIR \
--bootloader-id=GRUB \
--removable \
--recheck
"
umount "$MOUNT_POINT$GRUB_EFI_DIR"
else
log " -> Installing GRUB in BIOS mode on $target"
chroot "$MOUNT_POINT" /bin/bash -c "
grub-install --target=i386-pc \
--modules='$GRUB_MODULES' \
--recheck \
$target
"
fi
# Generate GRUB configuration (once per root, not per disk)
if [[ "$target" == "${TARGET_DISKS_PARTS[0]}" ]]; then
log " -> Generating GRUB configuration..."
chroot "$MOUNT_POINT" /bin/bash -c "grub-mkconfig -o /boot/grub/grub.cfg"
fi
# Clean up bind mounts
umount "$MOUNT_POINT/dev" || true
umount "$MOUNT_POINT/proc" || true
umount "$MOUNT_POINT/sys" || true
umount "$MOUNT_POINT/run" || true
done
# -------------------------- Final Cleanup -------------------------
log "Unmounting root filesystem..."
umount "$MOUNT_POINT"
log "GRUB installation completed successfully."
log "Reboot the system and verify boot from the new configuration."
How the Script Works
- Validation – Confirms root privileges and existence of all partitions.
- Mount Root – Mounts
/dev/nvme0n1p1to/mnt/rootforchroot. - Loop over Targets – For each of
/dev/sda2and/dev/sdb1:
- Detects whether the partition is an EFI System Partition (UEFI) or legacy.
- Sets up necessary bind mounts (
/dev,/proc,/sys,/run). - Executes
grub-installinside achrootenvironment: - UEFI:
--target=x86_64-efi, mounts the ESP, installs both standard and removable bootloaders. - BIOS:
--target=i386-pc, installs directly to the partition. - Generates
grub.cfgonce (on the first iteration) using the kernel/initramfs on the root partition.
- Cleanup – Unmounts everything safely.
Post-Installation Steps
- Reboot and enter the firmware (BIOS/UEFI) settings.
- Ensure the new GRUB entries on
/dev/sda2and/dev/sdb1are listed and set as desired boot order. - Test booting from each disk to confirm redundancy.
If your environment uses a separate ESP (not on /dev/nvme0n1p1), modify GRUB_EFI_DIR and the mount logic accordingly.
Should you require adjustments (e.g., custom grub.cfg parameters, LUKS encryption, or LVM), please provide additional details for a tailored revision.
If your target partition is already installed you can easily do it with this script as well:
Below is the revised Bash script that accommodates the scenario where /dev/nvme0n1p1 is the currently booted root filesystem (i.e., already mounted at /).
The key modifications are:
- No mounting of
/dev/nvme0n1p1is performed. - The script operates directly in the live root environment.
- Bind mounts are still required for
chrootisolation when installing GRUB on additional disks. grub-mkconfigis run once in the live environment.- EFI handling assumes the ESP may be on one of the target partitions (
/dev/sda2or/dev/sdb1) or elsewhere; the script detects and mounts it accordingly.
#!/bin/bash
#=====================================================================
# GRUB Installation Script (Live Root on /dev/nvme0n1p1)
# Targets: /dev/sda2 and /dev/sdb1
# Root filesystem: / (already mounted at /dev/nvme0n1p1)
# Author: Assistant (updated for live root environment)
#=====================================================================
set -euo pipefail
# -------------------------- Configuration --------------------------
TARGET_PARTS=( "/dev/sda2" "/dev/sdb1" )
ROOT_PART="/dev/nvme0n1p1" # For verification only
GRUB_EFI_DIR="/boot/efi" # Standard ESP mount point
GRUB_MODULES="ext2 part_gpt part_msdos" # Adjust if needed
# ------------------------------------------------------------------
log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*"; }
# Validate root privileges
if [[ $EUID -ne 0 ]]; then
log "ERROR: This script must be run as root."
exit 1
fi
# Verify we are booted from the expected root partition
current_root=$(findmnt -n -o SOURCE /)
if [[ "$current_root" != "$ROOT_PART" ]]; then
log "WARNING: Current root is $current_root, expected $ROOT_PART."
log "Proceeding anyway, but ensure kernel/initramfs are in /boot."
fi
# Validate target partitions exist
for part in "${TARGET_PARTS[@]}"; do
if [[ ! -b "$part" ]]; then
log "ERROR: Partition $part does not exist."
exit 1
fi
done
# Ensure /boot exists
if [[ ! -d "/boot" ]]; then
log "ERROR: /boot directory not found in root filesystem."
exit 1
fi
# -------------------------- GRUB Installation Loop ----------------
for target in "${TARGET_PARTS[@]}"; do
log "Processing target partition: $target"
# Detect if target is an EFI System Partition (type EF00 on GPT)
is_efi=0
if command -v blkid >/dev/null; then
if blkid -s TYPE -o value "$target" | grep -iq "^vfat$" && \
blkid -s PARTENTRY_TYPE -o value "$target" 2>/dev/null | grep -iq "^c12a7328-f81f-11d2-ba4b-00a0c93ec93b$"; then
is_efi=1
fi
elif lsblk -no FSTYPE,PARTTYPENAME "$target" 2>/dev/null | grep -iq "vfat.*EFI"; then
is_efi=1
fi
# Prepare EFI mount if needed
esp_mounted=0
if [[ $is_efi -eq 1 ]]; then
log " -> $target identified as EFI System Partition (ESP)"
mkdir -p "$GRUB_EFI_DIR"
if ! mountpoint -q "$GRUB_EFI_DIR"; then
mount "$target" "$GRUB_EFI_DIR"
esp_mounted=1
log " -> Mounted ESP $target at $GRUB_EFI_DIR"
else
log " -> ESP already mounted at $GRUB_EFI_DIR"
fi
fi
# Install GRUB
if [[ $is_efi -eq 1 ]]; then
log " -> Installing GRUB in UEFI mode to $target"
# Standard boot entry
grub-install --target=x86_64-efi \
--efi-directory="$GRUB_EFI_DIR" \
--bootloader-id=GRUB \
--modules="$GRUB_MODULES" \
--recheck
# Removable/fallback entry (optional but recommended for redundancy)
grub-install --target=x86_64-efi \
--efi-directory="$GRUB_EFI_DIR" \
--bootloader-id=GRUB \
--removable \
--recheck
else
log " -> Installing GRUB in BIOS mode to $target"
grub-install --target=i386-pc \
--modules="$GRUB_MODULES" \
--recheck \
"$target"
fi
# Unmount ESP if we mounted it
if [[ $esp_mounted -eq 1 ]]; then
umount "$GRUB_EFI_DIR"
log " -> Unmounted ESP from $GRUB_EFI_DIR"
fi
# Generate GRUB config only once (on first target)
if [[ "$target" == "${TARGET_PARTS[0]}" ]]; then
log " -> Generating GRUB configuration at /boot/grub/grub.cfg"
grub-mkconfig -o /boot/grub/grub.cfg
fi
done
# -------------------------- Final Cleanup -------------------------
log "GRUB installation completed successfully on all targets."
log "Reboot the system and verify boot entries in firmware (UEFI/BIOS)."
log "Ensure boot order includes new GRUB instances on /dev/sda2 and /dev/sdb1."
Key Changes from Previous Version
| Feature | Previous | Now (Live Root) |
|---|---|---|
| Root mount | mount /dev/nvme0n1p1 /mnt/root |
Skipped — root is / |
chroot usage |
Required for isolation | Removed — unsafe in live root; direct grub-install is used |
| Bind mounts | /dev, /proc, etc. into chroot |
Not needed |
| ESP handling | Assumed on root or manual | Auto-detects if target is ESP and mounts temporarily |
grub-mkconfig |
Inside chroot | Directly on live system |
Assumptions & Requirements
UEFI Systems:
- At least one of
/dev/sda2or/dev/sdb1must be a FAT32-formatted EFI System Partition (typeEF00). - If both are ESPs, both will receive GRUB EFI binaries.
- The system must boot in UEFI mode (not CSM/Legacy).
BIOS/Legacy Systems:
- Targets are MBR/GPT hybrid or pure MBR.
- GRUB will embed core image in the post-MBR gap or partition boot sector.
Kernel & Initramfs: Must be present in /boot (e.g., /boot/vmlinuz-*, /boot/initramfs-*).
Secure Boot:
- If enabled, you must sign
grubx64.efiwith a key enrolled in firmware. - This script does not handle signing. Use
sbctlorshimif needed.
Post-Execution Steps
- Reboot and enter firmware settings.
- Verify new boot entries:
- UEFI: Look for
GRUB(and possiblyGRUB (removable)) under boot options. - BIOS: Ensure
/dev/sdaand/dev/sdbare in boot order.
- Test booting from each disk independently (e.g., disconnect one).
This version is safe, efficient, and production-appropriate for a live, booted system.
Should you need support for LUKS, LVM, separate /boot, or custom grub.cfg templates, please specify for further refinement.