chroot – a menu system?

Below is an example of a complete Bash script that provides a text‐based “GUI” (menu) for managing chroot environments on Debian 12. This script assumes you’re running on a build machine (with most of the tools already installed) and will handle basic tasks such as creating, entering, listing, and removing chroot jails using debootstrap. Error trapping and simple prompts are built in so you don’t have to manually type out every command.

You can save this as, say, chroot_frontend.sh, make it executable, and run it as root. (It uses debootstrap to install a minimal Debian Bookworm environment into each chroot.)

Yes – it’s probably lacking everywhere – but – it’s here, and comments are turned off for a reason.

#!/bin/bash
# chroot_frontend.sh - A minimal Bash frontend for managing chroot environments on Debian 12 (Bookworm)

# Enable error trapping and exit immediately if a command fails.
set -e
trap 'error_handler ${LINENO}' ERR

# Error handler: prints the line number where the error occurred.
function error_handler {
    echo "Error occurred at line ${1}. Exiting."
    exit 1
}

# Ensure the script is being run as root.
if [ "$EUID" -ne 0 ]; then
    echo "Please run this script as root."
    exit 1
fi

# Global variable: Base directory where all chroot environments will reside.
CHROOT_BASE="/var/chroots"

# Create the base directory if it doesn't exist.
if [ ! -d "$CHROOT_BASE" ]; then
    mkdir -p "$CHROOT_BASE"
fi

# Check that required commands are installed.
function check_prerequisites {
    for cmd in debootstrap chroot mount umount; do
        command -v $cmd >/dev/null 2>&1 || { echo "Required command '$cmd' not found. Please install it."; exit 1; }
    done
}
check_prerequisites

# --------------------------------------------------------------------
# Function: create_chroot
# Description: Uses debootstrap to create a minimal Debian Bookworm environment.
# --------------------------------------------------------------------
function create_chroot {
    read -p "Enter a name for the new chroot environment: " CHROOT_NAME
    CHROOT_DIR="${CHROOT_BASE}/${CHROOT_NAME}"
    
    if [ -d "$CHROOT_DIR" ]; then
        echo "Error: Chroot environment '$CHROOT_NAME' already exists."
        return 1
    fi

    mkdir -p "$CHROOT_DIR"
    echo "Creating chroot environment in ${CHROOT_DIR}..."
    
    # Using debootstrap to install a minimal Debian (Bookworm) system
    debootstrap --arch=amd64 bookworm "$CHROOT_DIR" http://deb.debian.org/debian || { echo "debootstrap failed."; return 1; }
    echo "Chroot '$CHROOT_NAME' created successfully."
}

# --------------------------------------------------------------------
# Function: enter_chroot
# Description: Binds necessary system directories and drops you into a shell inside the chroot.
# --------------------------------------------------------------------
function enter_chroot {
    read -p "Enter the name of the chroot environment to enter: " CHROOT_NAME
    CHROOT_DIR="${CHROOT_BASE}/${CHROOT_NAME}"
    
    if [ ! -d "$CHROOT_DIR" ]; then
        echo "Error: Chroot environment '$CHROOT_NAME' does not exist."
        return 1
    fi

    # Bind mount system directories for a functional chroot.
    mount --bind /proc "$CHROOT_DIR/proc" || { echo "Failed to bind /proc"; return 1; }
    mount --bind /sys "$CHROOT_DIR/sys" || { echo "Failed to bind /sys"; return 1; }
    mount --bind /dev "$CHROOT_DIR/dev" || { echo "Failed to bind /dev"; return 1; }
    
    echo "Entering chroot environment '$CHROOT_NAME'. Type 'exit' when finished."
    chroot "$CHROOT_DIR" /bin/bash # Launches a new Bash shell inside the chroot.

    # Unmount the bound directories after exiting the chroot.
    umount "$CHROOT_DIR/proc" || true
    umount "$CHROOT_DIR/sys" || true
    umount "$CHROOT_DIR/dev" || true
}

# --------------------------------------------------------------------
# Function: remove_chroot
# Description: Deletes a specified chroot environment.
# --------------------------------------------------------------------
function remove_chroot {
    read -p "Enter the name of the chroot environment to remove: " CHROOT_NAME
    CHROOT_DIR="${CHROOT_BASE}/${CHROOT_NAME}"
    
    if [ ! -d "$CHROOT_DIR" ]; then
        echo "Error: Chroot environment '$CHROOT_NAME' does not exist."
        return 1
    fi

    read -p "Are you sure you want to remove '$CHROOT_NAME'? This will delete its contents. (y/N): " confirm
    if [[ "$confirm" =~ ^[Yy]$ ]]; then
        rm -rf "$CHROOT_DIR"
        echo "Chroot environment '$CHROOT_NAME' has been removed."
    else
        echo "Removal cancelled."
    fi
}

# --------------------------------------------------------------------
# Function: list_chroots
# Description: Lists all chroot environments under CHROOT_BASE.
# --------------------------------------------------------------------
function list_chroots {
    echo "Available chroot environments in ${CHROOT_BASE}:"
    if [ -d "$CHROOT_BASE" ]; then
        ls -1 "$CHROOT_BASE"
    else
        echo "No chroot environments found."
    fi
}

# --------------------------------------------------------------------
# Main Menu
# Description: Provides a simple menu and calls the appropriate functions.
# --------------------------------------------------------------------
function main_menu {
    while true; do
        clear
        echo "=================================="
        echo "Chroot Management Frontend (Debian 12)"
        echo "=================================="
        echo "1) Create a new chroot environment"
        echo "2) Enter an existing chroot environment"
        echo "3) Remove a chroot environment"
        echo "4) List available chroot environments"
        echo "5) Exit"
        echo "=================================="
        read -p "Choose an option [1-5]: " option
        case $option in
            1)
                create_chroot
                read -p "Press Enter to continue..."
                ;;
            2)
                enter_chroot
                read -p "Press Enter to continue..."
                ;;
            3)
                remove_chroot
                read -p "Press Enter to continue..."
                ;;
            4)
                list_chroots
                read -p "Press Enter to continue..."
                ;;
            5)
                echo "Exiting."
                exit 0
                ;;
            *)
                echo "Invalid option. Try again."
                read -p "Press Enter to continue..."
                ;;
        esac
    done
}

# Start the program
main_menu