Created
April 8, 2025 19:38
-
-
Save john-clark/07f7108a57d08dd6df8f439927699b4f to your computer and use it in GitHub Desktop.
menu driven iso generator for debian
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
#!/bin/bash | |
# Author: John Clark | |
# License: MIT License | |
# Copyright: © 2025 John Clark | |
# Description: | |
# This script is a comprehensive tool for creating, customizing, and managing Debian ISO images. | |
# It provides functionality to download Debian ISO images, extract and modify them, | |
# create preseed configuration files, and generate new ISO images with custom settings. | |
# The script uses `whiptail` for an interactive menu-driven interface. | |
# Features: | |
# - Download the latest Debian ISO images (stable, oldstable, archived, weekly testing, and unstable builds). | |
# - Extract ISO images and modify their contents. | |
# - Create and edit preseed configuration files for automated installations. | |
# - Customize package selection and generate override files. | |
# - Rebuild ISO images with custom configurations. | |
# - Validate required tools and dependencies before execution. | |
# Requirements: | |
# - Root privileges to execute the script. | |
# - Required tools: whiptail, wget, make, md5sum, xorriso, openssl (will install if missing). | |
# Usage: | |
# Run the script as root using the following command: | |
# sudo ./generate-debian-iso.sh | |
# Function to check if a command exists | |
command_exists() { | |
command -v "$1" &>/dev/null | |
} | |
# Variables | |
WORK_DIR=$(mktemp -d) # Temporary working directory | |
EXTRACTED_DIR="$WORK_DIR/debian_extracted" | |
MOUNT_DIR="$WORK_DIR/debian_mount" | |
ISO_FILE="" # This will hold the downloaded ISO filename | |
# check if the script is being run as root | |
check_root() { | |
if [ "$(id -u)" -ne 0 ]; then | |
whiptail --title "Root Privileges Required" --msgbox "This script must be run as root. Please run it with sudo." 8 78 | |
return 1 | |
fi | |
} | |
# Check if the necessary tools are installed and available | |
check_tools() { | |
required_tools=("whiptail" "wget" "make" "md5sum" "xorriso" "openssl") | |
# check if tools are installed | |
for tool in "${required_tools[@]}"; do | |
if ! command_exists "$tool"; then | |
whiptail --title "Missing Tool" --yesno "The required tool '$tool' is not installed. Would you like to install it?" 8 78 | |
if [ $? -eq 0 ]; then | |
apt-get install -y "$tool" | |
else | |
whiptail --title "Installation Cancelled" --msgbox "Please install '$tool' manually and rerun the script." 8 78 | |
return 1 | |
fi | |
fi | |
done | |
# verify tools can be run | |
for tool in "${required_tools[@]}"; do | |
if ! command_exists "$tool"; then | |
whiptail --title "Tool Verification Failed" --msgbox "The tool '$tool' could not be verified. Please check your installation." 8 78 | |
return 1 | |
fi | |
done | |
whiptail --title "All Tools Installed" --msgbox "All required tools are installed." 8 78 | |
} | |
cleanup() { | |
# Remove temporary directories and files | |
if [ -d "$EXTRACTED_DIR" ]; then | |
whiptail --title "Cleanup" --yesno "Do you want to remove the extracted directory?" 8 78 | |
if [ $? -eq 0 ]; then | |
rm -rf "$EXTRACTED_DIR" | |
fi | |
fi | |
if [ -d "$WORK_DIR" ]; then | |
# prompt to remove directory | |
if [ -d "$WORK_DIR" ]; then | |
whiptail --title "Cleanup" --yesno "Do you want to remove the work directory?" 8 78 | |
if [ $? -eq 0 ]; then | |
rm -rf "$WORK_DIR" | |
fi | |
fi | |
fi | |
if [ -f "$ISO_FILE" ]; then | |
# prompt to remove ISO | |
whiptail --title "Cleanup" --yesno "Do you want to remove the ISO file?" 8 78 | |
if [ $? -eq 0 ]; then | |
rm -f "$ISO_FILE" | |
fi | |
fi | |
whiptail --title "Cleanup Complete" --msgbox "Temporary files and directories have been cleaned up." 8 78 | |
} | |
# Function to download the Debian DVD-1 ISO | |
download_iso() { | |
declare -A debian_versions | |
debian_versions=() | |
# Check if there is already a downloaded ISO | |
if [ -n "$ISO_FILE" ] && [ -f "$ISO_FILE" ]; then | |
whiptail --title "ISO Already Downloaded" --msgbox "A Debian ISO is already downloaded: $ISO_FILE. Would you like to download a new one?" 8 78 | |
if [ $? -ne 0 ]; then | |
return 1 | |
fi | |
fi | |
# whiptail menu to choose the Debian architecture | |
ARCH=$(whiptail --title "Choose Debian Architecture" --menu "Select the architecture of Debian to download" 15 60 4 \ | |
"amd64" "" \ | |
"i386" "" \ | |
"arm64" "" \ | |
"armel" "" 3>&1 1>&2 2>&3) | |
if [ -z "$ARCH" ]; then | |
whiptail --title "Selection Error" --msgbox "No architecture selected. Please try again." 8 78 | |
return 1 | |
fi | |
# Get the latest stable release | |
VERSION=$(wget -qO- "https://cdimage.debian.org/cdimage/release/current/${ARCH}/iso-dvd/" | grep -o 'debian-[0-9]\+\.[0-9]\+\.[0-9]\+-'"${ARCH}"'-DVD-1\.iso' | head -n 1 | sed -E 's/debian-([0-9]+\.[0-9]+\.[0-9]+)-'"${ARCH}"'-DVD-1\.iso/\1/') | |
if [ -z "$VERSION" ]; then | |
whiptail --title "Version Detection Error" --msgbox "Failed to detect the latest stable release version." 8 78 | |
return 1 | |
fi | |
debian_versions["Stable Release (v$VERSION)"]="https://cdimage.debian.org/cdimage/release/current/${ARCH}/iso-dvd/debian-$VERSION-$ARCH-DVD-1.iso" | |
# Automatically detect the latest oldstable release | |
VERSION=$(wget -qO- https://cdimage.debian.org/cdimage/archive/ | grep -oP 'href="\K12\.[0-9]+\.[0-9]+' | sort -V | tail -n 1) | |
if [ -z "$VERSION" ]; then | |
whiptail --title "Version Detection Error" --msgbox "Failed to detect the latest oldstable release version." 8 78 | |
fi | |
debian_versions["Oldstable Release (v$VERSION)"]="https://cdimage.debian.org/cdimage/archive/$VERSION/${ARCH}/iso-dvd/debian-$VERSION-$ARCH-DVD-1.iso" | |
# Automatically find the latest archived release | |
VERSION=$(wget -qO- https://cdimage.debian.org/cdimage/archive/ | grep -oP 'href="\K11\.\d+\.\d+(?=/)' | sort -V | tail -n 1) | |
if [ -z "$VERSION" ]; then | |
whiptail --title "Version Detection Error" --msgbox "Failed to detect the latest archived release version." 8 78 | |
fi | |
debian_versions["Archived Release (v$VERSION)"]="https://cdimage.debian.org/cdimage/archive/$VERSION/${ARCH}/iso-dvd/debian-$VERSION-$ARCH-DVD-1.iso" | |
# Add weekly testing build to the array | |
debian_versions["Weekly Testing Build"]="https://cdimage.debian.org/cdimage/weekly-builds/${ARCH}/iso-dvd/debian-testing-$ARCH-DVD-1.iso" | |
# Add unstable build to the array | |
debian_versions["Unstable Build"]="https://cdimage.debian.org/cdimage/unstable/${ARCH}/iso-dvd/debian-unstable-$ARCH-DVD-1.iso" | |
# Add an option for a custom version | |
debian_versions["Custom Version"]="Enter a custom URL" | |
# Create an array with keys for whiptail | |
OPTIONS=() | |
declare -A key_map | |
sorted_versions=$(for version in "${!debian_versions[@]}"; do | |
echo "$version" | |
done | grep -E "Stable|Oldstable|Archived" | sort -r) | |
# Add sorted versions to the menu | |
n=1 | |
while IFS= read -r version; do | |
OPTIONS+=("$n" "$version") | |
key_map["$n"]="$version" | |
((n++)) | |
done <<< "$sorted_versions" | |
# Add Weekly Testing Build and Unstable Build | |
OPTIONS+=("$n" "Weekly Testing Build") | |
key_map["$n"]="Weekly Testing Build" | |
((n++)) | |
OPTIONS+=("$n" "Unstable Build") | |
key_map["$n"]="Unstable Build" | |
((n++)) | |
# Add Custom Version last | |
OPTIONS+=("$n" "Custom Version") | |
key_map["$n"]="Custom Version" | |
# Calculate the height of the menu dynamically | |
num_options=$(( ${#OPTIONS[@]} / 2 )) | |
height=$((num_options + 7)) | |
[ $height -gt 15 ] && height=15 | |
# Use whiptail to show the menu for selecting a Debian version | |
VERSION=$(whiptail --title "Choose Debian Version" --menu "Select the version of Debian to download" "$height" 80 "${num_options}" "${OPTIONS[@]}" 3>&1 1>&2 2>&3) | |
if [ $? -ne 0 ]; then | |
whiptail --title "Selection Cancelled" --msgbox "No version selected." 8 78 | |
return 1 | |
fi | |
# Map the numeric selection back to the corresponding key | |
selected_key="${key_map[$VERSION]}" | |
# Handle the selection and get the URL from the associative array | |
if [ "$selected_key" == "Custom Version" ]; then | |
# Prompt the user to enter a custom URL | |
ISO_URL=$(whiptail --title "Custom Debian ISO" --inputbox "Enter the URL of the Debian DVD-1 ISO:" 10 60 3>&1 1>&2 2>&3) | |
# Check if the user canceled or entered an empty URL | |
if [ $? -ne 0 ]; then | |
whiptail --title "Input Error" --msgbox "You canceled the input. Please try again." 8 60 | |
return 1 | |
elif [ -z "$ISO_URL" ]; then | |
whiptail --title "Input Error" --msgbox "No URL provided. Please try again." 8 60 | |
return 1 | |
fi | |
else | |
# Retrieve the URL from the associative array | |
ISO_URL=${debian_versions["$selected_key"]} | |
# Check if the URL is empty | |
if [ -z "$ISO_URL" ]; then | |
whiptail --title "Download Error" --msgbox "No URL found for the selected version. Please try again." 8 60 | |
return 1 | |
fi | |
fi | |
# Download the ISO | |
if [ -z "$ISO_URL" ]; then | |
whiptail --title "Download Error" --msgbox "No URL provided." 8 78 | |
return 1 | |
fi | |
# Download the ISO | |
ISO_FILE="$WORK_DIR/$VERSION" | |
wget -O "$ISO_FILE" "$ISO_URL" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Download Error" --msgbox "Failed to download the ISO." 8 78 | |
return 1 | |
fi | |
whiptail --title "Download Complete" --msgbox "The Debian ISO has been downloaded successfully." 8 78 | |
} | |
# Function to extract the ISO | |
diunpk() { | |
# Default values | |
local di_iso=${1:-$ISO_FILE} | |
local di_ro=${2:-$MOUNT_DIR} | |
local di_rw=${3:-$EXTRACTED_DIR} | |
# Ensure the ISO file exists | |
if [ ! -f "$di_iso" ]; then | |
whiptail --title "Error" --msgbox "The ISO file $di_iso does not exist." 8 78 | |
return 1 | |
fi | |
# Create read-only and read-write directories | |
mkdir -p "$di_ro" | |
mkdir -p "$di_rw" | |
# Mount the ISO image as read-only | |
mount "$di_iso" "$di_ro" -t iso9660 -o loop | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to mount the ISO image." 8 78 | |
return 1 | |
fi | |
# Create a work directory for overlayfs | |
mkdir -p "$WORK_DIR/work" | |
# Mount the overlay filesystem with read-write capabilities | |
mount -t overlay overlay -o lowerdir="$di_ro",upperdir="$di_rw",workdir="$WORK_DIR/work" "$di_rw" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to mount the overlay filesystem." 8 78 | |
umount "$di_ro" | |
return 1 | |
fi | |
# Set write permissions | |
chmod u+w "$di_rw" | |
chmod u+w "$di_rw/md5sum.txt" 2>/dev/null || true | |
find "$di_rw/dists" -exec chmod u+w {} \; 2>/dev/null || true | |
find "$di_rw/pool" -type d -exec chmod u+w {} \; 2>/dev/null || true | |
whiptail --title "ISO Extraction" --msgbox "The ISO has been extracted to $di_rw." 8 78 | |
return 0 | |
} | |
# Function to create a new Debian ISO | |
dipk() { | |
# Local customization | |
local di_iso=${1:-d-i.iso} | |
local di_rw=${2:-$EXTRACTED_DIR} | |
# Detect release and architecture dynamically | |
local release=$(basename "$(find "$di_rw/dists" -mindepth 1 -maxdepth 1 -type d | head -n 1)") | |
local arch=$(basename "$(find "$di_rw/dists/$release/main/debian-installer" -mindepth 1 -maxdepth 1 -type d | grep binary- | sed 's/binary-//')") | |
if [ -z "$release" ] || [ -z "$arch" ]; then | |
whiptail --title "Error" --msgbox "Failed to detect release or architecture from the extracted ISO." 8 78 | |
return 1 | |
fi | |
# Generate the apt-ftparchive configuration file | |
cat > "$di_rw/config" << EOF | |
Dir { | |
ArchiveDir "$di_rw"; | |
OverrideDir "$di_rw"; | |
CacheDir "$di_rw"; | |
}; | |
TreeDefault { | |
Directory "pool/"; | |
}; | |
BinDirectory "pool/main" { | |
Packages "dists/${release}/main/binary-${arch}/Packages"; | |
BinOverride "${di_rw}/binoverride"; | |
}; | |
Default { | |
Packages { | |
Extensions ".deb"; | |
}; | |
}; | |
EOF | |
# Generate the apt-ftparchive configuration file for udebs | |
cat > "$di_rw/config-udeb" << EOF | |
Dir { | |
ArchiveDir "$di_rw"; | |
OverrideDir "$di_rw"; | |
CacheDir "$di_rw"; | |
}; | |
TreeDefault { | |
Directory "pool/"; | |
}; | |
BinDirectory "pool/main" { | |
Packages "dists/${release}/main/debian-installer/binary-${arch}/Packages"; | |
BinOverride "${di_rw}/binoverride"; | |
}; | |
Default { | |
Packages { | |
Extensions ".udeb"; | |
}; | |
}; | |
EOF | |
# Generate the Packages file for .deb packages | |
apt-ftparchive generate "$di_rw/config" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to generate Packages file for .deb packages." 8 78 | |
return 1 | |
fi | |
# Generate the Packages file for .udeb packages | |
apt-ftparchive generate "$di_rw/config-udeb" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to generate Packages file for .udeb packages." 8 78 | |
return 1 | |
fi | |
# Generate the Release file | |
apt-ftparchive release "$di_rw/dists/${release}" > "$di_rw/dists/${release}/Release" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to generate Release file." 8 78 | |
return 1 | |
fi | |
# Generate the MD5 checksum file | |
md5sum $(find "$di_rw" -type f ! -name "md5sum.txt") > "$di_rw/md5sum.txt" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to generate MD5 checksum file." 8 78 | |
return 1 | |
fi | |
# Generate the ISO image | |
genisoimage -r -o "$di_iso" -V "CustomDebian" \ | |
-b isolinux/isolinux.bin -c isolinux/boot.cat \ | |
-no-emul-boot -boot-load-size 4 -boot-info-table "$di_rw" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to generate the ISO image." 8 78 | |
return 1 | |
fi | |
whiptail --title "ISO Creation" --msgbox "ISO image $di_iso has been successfully created." 8 78 | |
return 0 | |
} | |
# Function to extract the ISO | |
extract_iso() { | |
# Ensure the ISO file exists | |
if [ -z "$ISO_FILE" ] || [ ! -f "$ISO_FILE" ]; then | |
whiptail --title "Error" --msgbox "The ISO file does not exist. Please download the ISO first." 8 78 | |
return 1 | |
fi | |
# Create the extracted directory | |
mkdir -p "$EXTRACTED_DIR" | |
# Call diunpk with the correct ISO file and extracted directory | |
diunpk "$ISO_FILE" "$EXTRACTED_DIR" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Extraction Error" --msgbox "Failed to extract the ISO." 8 78 | |
return 1 | |
fi | |
} | |
# Function to choose packages for the pool | |
choose_packages() { | |
# Ensure the extracted directory exists | |
if [ ! -d "$EXTRACTED_DIR" ]; then | |
whiptail --title "Error" --msgbox "The extracted directory does not exist. Please extract the ISO first." 8 78 | |
return 1 | |
fi | |
# Define the path for the binoverride file | |
local binoverride_file="$EXTRACTED_DIR/binoverride" | |
# Ensure the binoverride file exists or create an empty one | |
if [ ! -f "$binoverride_file" ]; then | |
> "$binoverride_file" | |
fi | |
# Define a default array of packages | |
DEFAULT_PACKAGES=("vim" "curl" "wget" "git" "build-essential" "python3" "apache") | |
# Read the package list from the binoverride file if it exists and is not empty | |
OPTIONS=() | |
if [ -s "$binoverride_file" ]; then | |
# If the binoverride file is not empty, read packages from it | |
while IFS= read -r line; do | |
package=$(echo "$line" | awk '{print $1}') | |
OPTIONS+=("$package" "" OFF) | |
done < "$binoverride_file" | |
else | |
# If the binoverride file is empty, use the default packages | |
for package in "${DEFAULT_PACKAGES[@]}"; do | |
OPTIONS+=("$package" "" OFF) | |
done | |
fi | |
# Display a checklist for package selection | |
selected_packages=$(whiptail --title "Choose Packages" --checklist \ | |
"Select packages to include in the pool:" 15 60 8 \ | |
"${OPTIONS[@]}" 3>&1 1>&2 2>&3) | |
# Handle user cancellation | |
if [ $? -ne 0 ]; then | |
whiptail --title "Selection Cancelled" --msgbox "No packages selected." 8 78 | |
return 1 | |
fi | |
# Convert the selected packages into an array | |
IFS=" " read -r -a SELECTED_PACKAGES <<< "$selected_packages" | |
# Update the binoverride file with user-defined priority and section | |
> "$binoverride_file" # Clear the existing binoverride file | |
for package in "${SELECTED_PACKAGES[@]}"; do | |
# Remove quotes around the package name | |
package=$(echo "$package" | tr -d '"') | |
# Prompt the user for priority and section for each selected package | |
priority=$(whiptail --title "Package Priority" --inputbox "Enter the priority for package $package (e.g., optional, important):" 10 60 "optional" 3>&1 1>&2 2>&3) | |
if [ $? -ne 0 ]; then | |
whiptail --title "Cancelled" --msgbox "Priority input cancelled for $package. Skipping..." 8 78 | |
continue | |
fi | |
section=$(whiptail --title "Package Section" --inputbox "Enter the section for package $package (e.g., editors, net):" 10 60 "misc" 3>&1 1>&2 2>&3) | |
if [ $? -ne 0 ]; then | |
whiptail --title "Cancelled" --msgbox "Section input cancelled for $package. Skipping..." 8 78 | |
continue | |
fi | |
# Add the package to the binoverride file | |
echo "$package $priority $section" >> "$binoverride_file" | |
done | |
whiptail --title "Packages Saved" --msgbox "The selected packages and their overrides have been saved successfully." 8 78 | |
} | |
# Function to generate the override file | |
generate_md5sum() { | |
# Ensure the extracted directory exists | |
if [ ! -d "$EXTRACTED_DIR" ]; then | |
whiptail --title "Error" --msgbox "The extracted directory does not exist. Please extract the ISO first." 8 78 | |
return 1 | |
fi | |
# Generate the MD5 checksum file in the extracted directory | |
local md5_file="$EXTRACTED_DIR/md5sum.txt" | |
find "$EXTRACTED_DIR" -type f -exec md5sum {} \; > "$md5_file" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to generate the MD5 checksum file." 8 78 | |
return 1 | |
fi | |
whiptail --title "MD5 Checksum Generated" --msgbox "The MD5 checksum file has been created successfully at $md5_file." 8 78 | |
} | |
# Function to generate MD5 sum | |
generate_md5sum() { | |
# Ensure the extracted directory exists | |
if [ ! -d "$EXTRACTED_DIR" ]; then | |
whiptail --title "Error" --msgbox "The extracted directory does not exist. Please extract the ISO first." 8 78 | |
return 1 | |
fi | |
# Generate the MD5 checksum file in the extracted directory | |
local md5_file="$EXTRACTED_DIR/md5sum.txt" | |
find "$EXTRACTED_DIR" -type f -exec md5sum {} \; > "$md5_file" | |
if [ $? -ne 0 ]; then | |
whiptail --title "Error" --msgbox "Failed to generate the MD5 checksum file." 8 78 | |
return 1 | |
fi | |
whiptail --title "MD5 Checksum Generated" --msgbox "The MD5 checksum file has been created successfully at $md5_file." 8 78 | |
} | |
create_preseed_cfg() { | |
# Define common values for the preseed file | |
# rootpassword | |
ROOT_PASS_ENCRYPTED="\$6\$rounds=4096\$FZ5F4qMlgVt2\$F9zFJtQAxmTTItdbdwDQaxWkh9OGOVAWm8Nz/27HV0a" | |
# userpassword | |
USER_PASS_ENCRYPTED="\$6\$rounds=4096\$PbE1bYr9dfb1\$mSuW7OSXnHzxaSzGRmWTnx0DTX2d4hZpy2K02x1ptFc" | |
PACKAGE_SELECTION="standard, ssh-server" | |
MIRROR_HOSTNAME="ftp.us.debian.org" | |
MIRROR_COUNTRY="US" | |
TIMEZONE="America/New_York" | |
KEYMAP_LOCALE="en_US.UTF-8" | |
cat <<EOF > debian_extracted/preseed.cfg | |
# Default preseed.cfg for automated Debian installation | |
# Language settings | |
d-i localechooser/language-name string en | |
d-i localechooser/locale string en_US.UTF-8 | |
d-i keyboard-configuration/xkb-keymap select us | |
# Network configuration | |
d-i netcfg/choose_interface select auto | |
d-i netcfg/get_hostname string debian | |
# Timezone settings | |
d-i time/zone string $TIMEZONE | |
# Mirror settings | |
d-i mirror/country string $MIRROR_COUNTRY | |
d-i mirror/http/hostname string $MIRROR_HOSTNAME | |
d-i mirror/http/directory string /debian | |
# Disk partitioning (use entire disk) | |
d-i partman-auto/method string regular | |
d-i partman-auto/choose_recipe select atomic | |
# Package selection | |
tasksel tasksel/first multiselect $PACKAGE_SELECTION | |
# Set up the root password | |
d-i passwd/root-password-crypted password $ROOT_PASS_ENCRYPTED | |
# User account setup | |
d-i passwd/user-fullname string User | |
d-i passwd/username string user | |
d-i passwd/user-password-crypted password $USER_PASS_ENCRYPTED | |
# Autoinstallation settings | |
d-i preseed/early_command string anna-install libdebconfclient | |
d-i preseed/late_command string in-target apt-get update | |
# Reboot after installation | |
d-i finish-install/reboot_in_progress note | |
EOF | |
whiptail --title "Preseed File Created" --msgbox "The preseed.cfg has been created successfully." 8 78 | |
} | |
# Function to edit preseed.cfg | |
edit_preseed() { | |
preseed_file="debian_extracted/preseed.cfg" | |
# If the preseed.cfg file doesn't exist, create it with default content | |
if [ ! -f "$preseed_file" ]; then | |
create_preseed_cfg | |
fi | |
# Allow the user to edit the preseed.cfg file using nano | |
vim "$preseed_file" | |
} | |
# Function to modify preseed.cfg with guided options | |
modify_preseed() { | |
preseed_file="debian_extracted/preseed.cfg" | |
# If preseed.cfg doesn't exist, create a default one | |
if [ ! -f "$preseed_file" ]; then | |
create_preseed_cfg | |
fi | |
while true; do | |
# Display a menu for modifying preseed settings | |
CHOICE=$(whiptail --title "Modify Preseed File" --menu "Select a setting to modify:" 15 60 7 \ | |
"1" "Root Password" \ | |
"2" "User Account" \ | |
"3" "Package Selection" \ | |
"4" "Timezone" \ | |
"5" "Keyboard, Locale, and Language" \ | |
"6" "Mirror Settings" \ | |
"7" "Back to Main Menu" 3>&1 1>&2 2>&3) | |
# Handle user cancellation | |
if [ $? -ne 0 ]; then | |
break | |
fi | |
case $CHOICE in | |
1) # Modify root password | |
ROOT_PASS=$(whiptail --title "Root Password" --inputbox "Enter root password:" 10 60 "" 3>&1 1>&2 2>&3) | |
if [ $? -eq 0 ]; then | |
sed -i "s|^d-i passwd/root-password-crypted.*|d-i passwd/root-password-crypted password $ROOT_PASS|g" "$preseed_file" | |
fi | |
;; | |
2) # Modify user account details | |
USERNAME=$(whiptail --title "Username" --inputbox "Enter the username for the user account:" 10 60 "user" 3>&1 1>&2 2>&3) | |
USER_PASS=$(whiptail --title "User Password" --inputbox "Enter password for $USERNAME:" 10 60 "" 3>&1 1>&2 2>&3) | |
if [ $? -eq 0 ]; then | |
USER_PASS_ENCRYPTED=$(openssl passwd -6 "$USER_PASS") | |
sed -i "s|^d-i passwd/username.*|d-i passwd/username string $USERNAME|g" "$preseed_file" | |
sed -i "s|^d-i passwd/user-password-crypted.*|d-i passwd/user-password-crypted password $USER_PASS_ENCRYPTED|g" "$preseed_file" | |
fi | |
;; | |
3) # Modify package selection | |
PACKAGE_SELECTION=$(whiptail --title "Package Selection" --inputbox "Enter package selection (comma separated, e.g. ssh-server, standard):" 10 60 "ssh-server, standard" 3>&1 1>&2 2>&3) | |
if [ $? -eq 0 ]; then | |
sed -i "s|^tasksel tasksel/first.*|tasksel tasksel/first multiselect $PACKAGE_SELECTION|g" "$preseed_file" | |
fi | |
;; | |
4) # Modify timezone | |
TIMEZONE=$(whiptail --title "Timezone" --menu "Select your timezone" 15 60 5 \ | |
"America/Chicago" "" \ | |
"America/New_York" "" \ | |
"Europe/London" "" \ | |
"Asia/Kolkata" "" \ | |
"Asia/Tokyo" "" 3>&1 1>&2 2>&3) | |
if [ $? -eq 0 ]; then | |
sed -i "s|^d-i time/zone.*|d-i time/zone string $TIMEZONE|g" "$preseed_file" | |
fi | |
;; | |
5) # Modify keyboard, locale, and language | |
KEYMAP_LOCALE=$(whiptail --title "Keyboard, Locale, and Language" --menu "Select keyboard, locale, and language" 15 60 5 \ | |
"en_US.UTF-8" "" \ | |
"fr_FR.UTF-8" "" \ | |
"de_DE.UTF-8" "" \ | |
"es_ES.UTF-8" "" \ | |
"it_IT.UTF-8" "" 3>&1 1>&2 2>&3) | |
if [ $? -eq 0 ]; then | |
sed -i "s|^d-i localechooser/language-name.*|d-i localechooser/language-name string $KEYMAP_LOCALE|g" "$preseed_file" | |
sed -i "s|^d-i localechooser/locale.*|d-i localechooser/locale string $KEYMAP_LOCALE|g" "$preseed_file" | |
sed -i "s|^d-i keyboard-configuration/xkb-keymap.*|d-i keyboard-configuration/xkb-keymap select us|g" "$preseed_file" | |
fi | |
;; | |
6) # Modify mirror settings | |
MIRROR_HOSTNAME=$(whiptail --title "Mirror Hostname" --inputbox "Enter the mirror hostname (e.g. ftp.us.debian.org):" 10 60 "ftp.us.debian.org" 3>&1 1>&2 2>&3) | |
MIRROR_COUNTRY=$(whiptail --title "Mirror Country" --inputbox "Enter your mirror country code (e.g. US):" 10 60 "US" 3>&1 1>&2 2>&3) | |
if [ $? -eq 0 ]; then | |
sed -i "s|^d-i mirror/http/hostname.*|d-i mirror/http/hostname string $MIRROR_HOSTNAME|g" "$preseed_file" | |
sed -i "s|^d-i mirror/country.*|d-i mirror/country string $MIRROR_COUNTRY|g" "$preseed_file" | |
fi | |
;; | |
7) # Exit | |
break | |
;; | |
*) # Invalid option | |
whiptail --title "Invalid Option" --msgbox "Invalid option selected. Please try again." 8 60 | |
;; | |
esac | |
done | |
whiptail --title "Preseed File Updated" --msgbox "The preseed.cfg has been updated successfully." 8 78 | |
} | |
# Function to create the new image | |
create_new_image() { | |
# Define the paths for the extracted ISO and the output ISO | |
local di_rw=${1:-$EXTRACTED_DIR} | |
local di_iso=${2:-"$WORK_DIR/custom_debian.iso"} | |
# Call the dipk function to create the new ISO | |
dipk "$di_iso" "$di_rw" | |
if [ $? -ne 0 ]; then | |
whiptail --title "ISO Creation Error" --msgbox "Failed to create the new image." 8 78 | |
return 1 | |
fi | |
whiptail --title "ISO Created" --msgbox "The new image has been created successfully as $di_iso." 8 78 | |
} | |
# Main menu function | |
main_menu() { | |
# Define menu options in an array (function and description) | |
local menu_options=( | |
"Download Debian ISO" "download_iso" | |
"Extract ISO" "extract_iso" | |
"Choose Packages" "choose_packages" | |
"Generate Override File" "generate_override" | |
"Edit preseed.cfg" "edit_preseed" | |
"Modify preseed.cfg" "modify_preseed" | |
"Generate MD5" "generate_md5sum" | |
"Create New Image" "create_new_image" | |
"Exit" "exit" | |
) | |
local num_items=$(( ${#menu_options[@]} )) | |
local height=10 | |
while true; do | |
# Create the options array for whiptail | |
OPTIONS=() | |
n=1 | |
for ((i = 0; i < num_items; i+=2)); do | |
OPTIONS+=("$n" "${menu_options[$i]}") | |
((n++)) | |
done | |
# Show the menu with whiptail | |
CHOICE=$(whiptail --title "Debian ISO Creator" \ | |
--menu "Choose an option" \ | |
$((num_items / 2 + 7)) 60 $((num_items / 2)) \ | |
"${OPTIONS[@]}" 3>&1 1>&2 2>&3) | |
# If the user canceled, exit | |
if [ $? -ne 0 ]; then | |
break | |
fi | |
# Find the corresponding function to call | |
for ((i = 0; i < num_items; i+=2)); do | |
if [[ "$((i / 2 + 1))" == "$CHOICE" ]]; then | |
FUNC="${menu_options[$((i + 1))]}" # Get the function name | |
break | |
fi | |
done | |
# Call the selected function if it's not "exit" | |
if [[ "$FUNC" != "exit" ]]; then | |
$FUNC | |
else | |
break | |
fi | |
done | |
} | |
# Main script execution | |
check_root | |
check_tools | |
main_menu | |
trap cleanup EXIT |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment