Skip to content
Snippets Groups Projects
Commit c7363dd4 authored by ping's avatar ping
Browse files

Improve Clarity and Robustness

parent bf83715e
Branches
No related tags found
No related merge requests found
# Location of generated files
export SQUASHFS="/tmp/squashfs"
export ROOTFS_DIR="/tmp/rootfs"
export ISO_DIR="/tmp/iso"
export BOOT_FOLDER="$ISO_DIR/boot"
# Nexus build configuration
export SERVER="127.0.0.1:1077"
export CERT="ca-cert.pem"
export EXAM_USER="user"
export EXAM_PWD="password"
# Build parameters
export LUKS_PASSPHRASE="passphrase"
export ADDITIONAL_KEYS="keys keyss"
export CHALLENGE="challenge"
export VERBOSE=false
export RAM="squashfs_tmpfs"
#export PXE_URL="127.0.0.1:8000"
export OUTPUT="build"
export CACHE_FS="cache"
*.iso *.iso
.env .env*
cache/ cache/
config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection
# Live Exam OS Builder # Live Exam OS Builder
This project provides a set of tools and scripts to build a customized ISO image for live examination environments. It supports features such as PXE booting, LUKS encryption, and user environment setup. This project provides a set of tools and scripts to build a customized ISO image for live examination environments. It supports features such as PXE booting, LUKS encryption, user environment setup, and secure boot.
---
## Important Notice
**This script should be run inside a container or a virtual machine (VM).** The script binds directories like `/dev`, `/sys`, and others to the new filesystem. If a problem occurs, it could corrupt the host system, necessitating a reboot. Running the script in an isolated environment like a container or VM helps prevent these issues.
--- ---
## Usage ## Usage
To use the script, run it with the following command: To build the ISO image, you should use the provided Docker setup. The script `build.sh` should not be run directly on the host system. Instead, use the following methods:
```bash ### Using Makefile
./build.sh [options]
```
### Requirements The Makefile simplifies the process of building and running the project in a Docker container.
The `build.sh` script should be executed on a Ubuntu/Debian environment with the following tools installed: 1. **Build the Docker Image**:
- `debootstrap` ```bash
- Other necessary dependencies for building ISO images. make build
```
For simpler deployment on any environment that supports Docker, we provide a `Dockerfile` and `Makefile`. These tools allow you to build and run the project without worrying about host system dependencies. 2. **Run the Build Script**:
```bash
make run PARAM="<param>"
```
Replace <param> with the desired parameters for the build.sh script.
### Options ### Using Docker Directly
| Option | Description | If you prefer to use Docker commands directly, you can run the script with the following command:
|-----------------------|-------------|
| `-v, --verbose` | Enable verbose mode for detailed output. | ```bash
| `--env` | Specify the path to an environment file with the required parameters. | docker run -it --rm -v $(pwd)/..:/data --workdir /data/live_exam_os --privileged <image_name> ./build.sh <param>
| `--output` | Define the output folder (default: `.`). | ```
| `--luks-passphrase` | Enable LUKS encryption with a passphrase. |
| `--luks-keys` | Provide a list of additional keys for LUKS encryption. | Replace <image_name> with the name of your Docker image and <param> with the desired parameters for the build.sh script.
| `--ram` | Using the system in RAM. |
| `--challenge` | Challenge in use by yubikeys. | ### Options
| `--arch` | Set the architecture of the system (e.g., amd64). | | Option | Description |
| `--pxe` | Set the url of the pxe and generate an initramfs, kernel and squashfs for the pxe to use (use the url of the folder where the squashfs is stored, not the direct link to the squashfs). | |:- |:---|
| `--cache` | Path to a folder with a clean fs already downloaded. | | -v, --verbose | Enable verbose mode for detailed output. |
| `--version` | Version of Ubuntu (e.g., Noble) | | --env | Specify the path to an environment file with the required parameters. |
| --output | Define the output folder (default: .). |
| --luks-passphrase | Enable LUKS encryption with a passphrase. |
| --luks-keys | Provide a list of additional keys for LUKS encryption. |
| --ram | Use the system in RAM. |
| --challenge | Specify the challenge in use by YubiKeys. |
| --arch | Set the architecture of the system (e.g., amd64). |
| --pxe | Set the URL of the PXE and generate an initramfs, kernel, and squashfs for the PXE to use (use the URL of the folder where the squashfs is stored, not the direct link to the squashfs). |
| --cache | Path to a folder with a clean filesystem already downloaded. |
| --version | Version of Ubuntu (e.g., Noble). |
### Environment Setup Parameters ### Environment Setup Parameters
| SQUASHFS | Path to the SquashFS file (e.g., out/squash.rootfs). |
|:- |:------------------------------------ |
| ROOTFS_DIR | Path to the temporary filesystem directory (e.g., out/rootfs). |
| ISO_DIR | Path to the temporary ISO directory (e.g., out/iso). |
| SERVER | IP address of the Nexus server (e.g., 127.0.0.1:1077). |
| CERT | Path to the certificate file (e.g., ca-cert.pem). |
| EXAM_USER | Default username for the exam client (e.g., user). |
| EXAM_PWD | Default password for the exam client (e.g., password). |
### .env File
The .env file is used to configure the build environment. Below is an example of what the .env file might look like:
| Parameter | Description | ```bash
|----------------|-------------| # Location of generated files
| `SQUASHFS` | Path to the SquashFS file (e.g., `out/squash.rootfs`). | export SQUASHFS="output/squashfs"
| `ROOTFS_DIR` | Path to the temporary filesystem directory (e.g., `out/rootfs`). | export ROOTFS_DIR="output/rootfs"
| `ISO_DIR` | Path to the temporary ISO directory (e.g., `out/iso`). | export ISO_DIR="output/iso"
| `SERVER` | IP address of the Nexus server (e.g., `127.0.0.1:1077`). | export BOOT_FOLDER="$ISO_DIR/boot"
| `CERT` | Path to the certificate file (e.g., `ca-cert.pem`). |
| `EXAM_USER` | Default username for the exam client (e.g., `user`). | # Nexus build configuration
| `EXAM_PWD` | Default password for the exam client (e.g., `password`). | export SERVER="127.0.0.1:1077"
export CERT="ca-cert.pem"
export EXAM_USER="user"
export EXAM_PWD="password"
# Build parameters
export LUKS_PASSPHRASE="passphrase"
export ADDITIONAL_KEYS="key1 key2"
export CHALLENGE="challenge"
export VERBOSE=false
#export RAM="squashfs_tmpfs"
#export PXE_URL="127.0.0.1:8000"
export OUTPUT="build"
export CACHE_FS="cache"
```
Uncomment and set the necessary variables to customize your build environment.
--- ### Example Usage
## Example Usage Here are some examples of how to use the script with the Makefile:
Here are some examples of how to use the script: #### Example 1
### Example 1
Build an ISO image with LUKS encryption: Build an ISO image with LUKS encryption:
```bash ```bash
./build.sh --env .env make run PARAM="--env .env"
``` ```
### Example 2 #### Example 2
Build an ISO image without LUKS encryption: Build an ISO image without LUKS encryption:
```bash ```bash
./build.sh --output build --luks-passphrase 'my_luks_pass' --cache cache --pxe make run PARAM="--output build --luks-passphrase 'my_luks_pass' --cache cache --pxe 127.0.0.1:8000"
``` ```
#### Makefile Targets
---
## Makefile Targets
The Makefile includes targets to facilitate the building, running, and testing processes. The Makefile includes targets to facilitate the building, running, and testing processes.
| Target | Description |
|:- |:---------- |
| build | Build the Docker image for the project. |
| run | Run the Docker container to execute the build script. |
| bios | Run the ISO in QEMU using BIOS mode. |
| bios_cd | Run the ISO in QEMU using BIOS mode with a CD-ROM interface. |
| uefi | Run the ISO in QEMU using UEFI mode. |
### Available Targets #### Running Makefile Targets
| Target | Description |
|-----------|-------------|
| `build` | Build the Docker image for the project. |
| `run` | Run the Docker container to execute the build script. |
| `bios` | Run the ISO in QEMU using BIOS mode. |
| `bios_cd` | Run the ISO in QEMU using BIOS mode with a CD-ROM interface. |
| `uefi` | Run the ISO in QEMU using UEFI mode with network and serial options. |
### Running Makefile Targets
1. **Build the Docker Image**:
```bash
make build
```
2. **Run the Build Script**: 1. Build the Docker Image:
```bash ```bash
make run PARAM="--env .env" make build
``` ```
3. **Test the ISO in QEMU**: 2. Run the Build Script:
- BIOS mode: ```bash
```bash make run PARAM="<param>"
make bios ISO=image.iso ```
```
- BIOS with CD-ROM:
```bash
make bios_cd ISO=image.iso
```
- UEFI mode:
```bash
make uefi ISO=image.iso
```
3. Test the ISO in QEMU:
- BIOS mode:
```bash
make bios ISO=image.iso
```
- BIOS with CD-ROM:
```bash
make bios_cd ISO=image.iso
```
- UEFI mode:
```bash
make uefi ISO=image.iso
```
--- ---
## Project Components ## Project Components
### Scripts ### Scripts
- **build.sh**: Main script to build the ISO image and configure the environment. - **build.sh**: Main script to build the ISO image and configure the environment.
- **tools/functions.sh**: Contains helper functions used by the build.sh script to streamline operations and ensure consistency.
### Docker ### Docker
- **Dockerfile**: Defines the Docker image used to build the live examination environment. - **Dockerfile**: Defines the Docker image used to build the live examination environment.
- **Makefile**: Simplifies the process of building and running the project in a Docker container. - **Makefile**: Simplifies the process of building and running the project in a Docker container.
### Configuration Files ### Configuration Files
- **Environment file**: Provides parameters and paths required by the build script. The configuration files are organized in the config/ directory and include the following subdirectories:
- **config/00-bootloader**: Contains bootloader configuration files.
- grub.cfg, grub.efi.cfg, limine.conf
- **config/01-packages_install**: Lists packages to be installed.
- packages
- **config/02-customisation**: Contains customization files for the filesystem.
- etc/, home/, usr/
- **config/03-post_install**: Contains post-installation scripts to further customize the environment.
- 1000-create-user.sh, 2000-enable_services.sh, 3000-nexus_exam.sh, 5000-push_challenge.sh, 8000-initramfs.sh, 1000-disable_root.sh, 2500-disable_services.sh, 4000-firewall.sh, 5000-pxe.sh, 9999-cleanup.sh
--- ---
## Notes ## Requirements (For Advanced Users)
- Ensure that all required dependencies are installed before running the script or Makefile. The build.sh script should be executed in an environment with the following tools installed. These requirements are already satisfied within the provided Dockerfile. Advanced users who wish to modify the Dockerfile or run the script outside of Docker should ensure these tools are available:
- For UEFI testing, verify that the `OVMF` firmware is installed on your system (e.g., `/usr/share/OVMF/x64/OVMF.fd`).
- debootstrap
- chroot
- sed
- mount
- umount
- fallocate
- mkfs.vfat
- mksquashfs
- cryptsetup
- bash
- xorriso
- limine
## Notes
- Ensure that all required dependencies are installed before running the script or Makefile.
- For UEFI testing, verify that the OVMF firmware is installed on your system (e.g., /usr/share/OVMF/x64/OVMF.fd).
- When specifying a cache directory or a folder for downloading the filesystem, avoid using /tmp in the container, as it is often set with the noexec attribute, which can prevent tools like debootstrap from functioning correctly. Choose a directory with execution permissions instead.
...@@ -15,6 +15,10 @@ export UBUNTU_VERSION="noble" ...@@ -15,6 +15,10 @@ export UBUNTU_VERSION="noble"
export CHALLENGE="default_challenge" export CHALLENGE="default_challenge"
export ARCH="amd64" export ARCH="amd64"
TMP_KERNEL=$(mktemp /tmp/vmlinuz.XXXXXX)
TMP_INITRD=$(mktemp /tmp/initrd.XXXXXX)
TMP_SQUASHFS_IMG=$(mktemp /tmp/squashfs_img.XXXXXX)
helper() { helper() {
echo "USAGE: $(basename "$0") [options]" echo "USAGE: $(basename "$0") [options]"
echo echo
...@@ -37,9 +41,9 @@ helper() { ...@@ -37,9 +41,9 @@ helper() {
echo " ROOTFS_DIR Path to the temporary filesystem directory (e.g., out/rootfs)" echo " ROOTFS_DIR Path to the temporary filesystem directory (e.g., out/rootfs)"
echo " ISO_DIR Path to the temporary ISO directory (e.g., out/iso)" echo " ISO_DIR Path to the temporary ISO directory (e.g., out/iso)"
echo " SERVER IP of the nexus server (e.g., 127.0.0.1:1077)" echo " SERVER IP of the nexus server (e.g., 127.0.0.1:1077)"
echo " CERT Path to the Certificate file (e.g., ca-cert.pem)" echo " CERT Path to the Certificate file (e.g., ca-cert.pem)"
echo " EXAM_USER Default user for exam client (e.g., user)" echo " EXAM_USER Default user for exam client (e.g., user)"
echo " EXAM_PWD Default password for exam client (e.g., password)" echo " EXAM_PWD Default password for exam client (e.g., password)"
echo echo
echo "Example Usage:" echo "Example Usage:"
echo " $(basename "$0") --env .env" echo " $(basename "$0") --env .env"
...@@ -50,10 +54,15 @@ helper() { ...@@ -50,10 +54,15 @@ helper() {
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
case "$1" in case "$1" in
--env) --env)
source $2 > /dev/null if [ -f "$2" ]; then
source "$2" > /dev/null
else
echo "Error: File '$2' not found." >&2
helper
fi
shift 2 shift 2
;; ;;
--ouput) --output)
if [ -n "$2" ]; then if [ -n "$2" ]; then
export OUTPUT="$2" export OUTPUT="$2"
shift 2 shift 2
...@@ -67,7 +76,7 @@ while [ "$#" -gt 0 ]; do ...@@ -67,7 +76,7 @@ while [ "$#" -gt 0 ]; do
LUKS_PASSPHRASE="$2" LUKS_PASSPHRASE="$2"
shift 2 shift 2
else else
echo "Error: --luks-keys requires an argument" >&2 echo "Error: --luks-passphrase requires an argument" >&2
helper helper
fi fi
;; ;;
...@@ -85,7 +94,7 @@ while [ "$#" -gt 0 ]; do ...@@ -85,7 +94,7 @@ while [ "$#" -gt 0 ]; do
CHALLENGE="$2" CHALLENGE="$2"
shift 2 shift 2
else else
echo "Error: --luks-keys requires an argument" >&2 echo "Error: --challenge requires an argument" >&2
helper helper
fi fi
;; ;;
...@@ -98,21 +107,17 @@ while [ "$#" -gt 0 ]; do ...@@ -98,21 +107,17 @@ while [ "$#" -gt 0 ]; do
helper helper
fi fi
;; ;;
-v)
export VERBOSE=true
shift
;;
--ram) --ram)
export RAM="squashfs_tmpfs" export RAM="squashfs_tmpfs"
shift shift
;; ;;
--verbose) -v|--verbose)
export VERBOSE=true export VERBOSE=true
shift shift
;; ;;
--cache) --cache)
if [ -n "$2" ]; then if [ -n "$2" ]; then
export CACHE_FS=$2 export CACHE_FS="$2"
shift 2 shift 2
else else
echo "Error: --cache requires an argument" >&2 echo "Error: --cache requires an argument" >&2
...@@ -121,19 +126,19 @@ while [ "$#" -gt 0 ]; do ...@@ -121,19 +126,19 @@ while [ "$#" -gt 0 ]; do
;; ;;
--version) --version)
if [ -n "$2" ]; then if [ -n "$2" ]; then
export UBUNTU_VERSION=$2 export UBUNTU_VERSION="$2"
shift 2 shift 2
else else
echo "Error: --cache requires an argument" >&2 echo "Error: --version requires an argument" >&2
helper helper
fi fi
;; ;;
--arch) --arch)
if [ -n "$2" ]; then if [ -n "$2" ]; then
export ARCH=$2 export ARCH="$2"
shift 2 shift 2
else else
echo "Error: --cache requires an argument" >&2 echo "Error: --arch requires an argument" >&2
helper helper
fi fi
;; ;;
...@@ -144,151 +149,205 @@ while [ "$#" -gt 0 ]; do ...@@ -144,151 +149,205 @@ while [ "$#" -gt 0 ]; do
esac esac
done done
check_inside_container
check_environment_var check_environment_var
check_dependencies
CMDLINE="boot=nexus quiet splash $RAM modprobe.blacklist=floppy" CMDLINE="boot=nexus quiet splash $RAM modprobe.blacklist=floppy"
echo "[Cleanup $ROOTFS_DIR]"
ROOTFS_PATH="${ROOTFS_DIR%/}"
child_mounts=$(findmnt -rn -o TARGET | grep -E "^${ROOTFS_PATH}/[^/]+$")
if [ -n "$child_mounts" ]; then
echo "WARNING: The following mount points are directly under $ROOTFS_DIR:"
echo "$child_mounts"
echo
read -p "Do you want to unmount these mount points? [y/N]: " confirmation
case "$confirmation" in
[yY][eE][sS]|[yY])
while IFS= read -r mount_point; do
echo "Unmounting $mount_point..."
if ! umount "$mount_point"; then
echo "Error: Failed to unmount $mount_point. Please unmount manually or reboot the system to avoid issues."
exit 1
fi
done <<< "$child_mounts"
;;
*)
echo "Cleanup aborted by user."
exit 1
;;
esac
fi
run_command rm -rf "$ROOTFS_DIR"
echo "[Cleanup $OUTPUT]"
run_command rm -rf "$OUTPUT"
echo "[Create filesystem...]" echo "[Create filesystem...]"
rm -rf "$ROOTFS_DIR" "$OUTPUT"
mkdir -p "$ROOTFS_DIR" mkdir -p "$ROOTFS_DIR"
if [ -z $CACHE_FS ]; then if [ -z "$CACHE_FS" ]; then
run_command debootstrap --arch=$ARCH $UBUNTU_VERSION $ROOTFS_DIR http://archive.ubuntu.com/ubuntu/ run_command debootstrap --arch="$ARCH" "$UBUNTU_VERSION" "$ROOTFS_DIR" http://archive.ubuntu.com/ubuntu/
mount -t proc /proc $ROOTFS_DIR/proc run_command mount -t proc /proc "$ROOTFS_DIR/proc"
mount --rbind /sys $ROOTFS_DIR/sys run_command mount --rbind /sys "$ROOTFS_DIR/sys"
mount --rbind /dev $ROOTFS_DIR/dev run_command mount --rbind /dev "$ROOTFS_DIR/dev"
mount --rbind /run $ROOTFS_DIR/run run_command mount --rbind /run "$ROOTFS_DIR/run"
mount -t tmpfs tmpfs $ROOTFS_DIR/tmp run_command mount -t tmpfs tmpfs "$ROOTFS_DIR/tmp"
echo "[Installing packages...]" echo "[Installing packages...]"
packages=$(tr '\n' ' ' < config/01-packages_install/packages) packages=$(tr '\n' ' ' < config/01-packages_install/packages)
echo "deb http://archive.ubuntu.com/ubuntu $UBUNTU_VERSION main universe" > $ROOTFS_DIR/etc/apt/sources.list echo "deb http://archive.ubuntu.com/ubuntu $UBUNTU_VERSION main universe" > "$ROOTFS_DIR/etc/apt/sources.list"
run_command_chroot apt update run_command_chroot apt update
check_exit_code $? "Error during apt update" run_command_chroot apt install -y --no-install-recommends "$packages"
run_command_chroot apt install -y --no-install-recommends $packages
check_exit_code $? "Error during packages installation"
else else
if [ ! -d $CACHE_FS ]; then if [ ! -d "$CACHE_FS" ]; then
mkdir $CACHE_FS mkdir "$CACHE_FS"
run_command debootstrap --arch=$ARCH $UBUNTU_VERSION $CACHE_FS http://archive.ubuntu.com/ubuntu/ run_command debootstrap --arch="$ARCH" "$UBUNTU_VERSION" "$CACHE_FS" http://archive.ubuntu.com/ubuntu/
mount -t proc /proc $CACHE_FS/proc run_command mount -t proc /proc "$CACHE_FS/proc"
mount --rbind /sys $CACHE_FS/sys run_command mount --rbind /sys "$CACHE_FS/sys"
mount --rbind /dev $CACHE_FS/dev run_command mount --rbind /dev "$CACHE_FS/dev"
mount --rbind /run $CACHE_FS/run run_command mount --rbind /run "$CACHE_FS/run"
mount -t tmpfs tmpfs $CACHE_FS/tmp run_command mount -t tmpfs tmpfs "$CACHE_FS/tmp"
echo "[Installing packages...]" echo "[Installing packages...]"
packages=$(tr '\n' ' ' < config/01-packages_install/packages) packages=$(tr '\n' ' ' < config/01-packages_install/packages)
echo "deb http://archive.ubuntu.com/ubuntu $UBUNTU_VERSION main universe" > $CACHE_FS/etc/apt/sources.list echo "deb http://archive.ubuntu.com/ubuntu $UBUNTU_VERSION main universe" > "$CACHE_FS/etc/apt/sources.list"
run_command chroot $CACHE_FS apt update run_command chroot "$CACHE_FS" apt update
check_exit_code $? "Error during apt update" run_command chroot "$CACHE_FS" apt install -y --no-install-recommends "$packages"
run_command chroot $CACHE_FS apt install -y --no-install-recommends $packages
check_exit_code $? "Error during packages installation" run_command umount -l "$CACHE_FS/proc"
run_command umount -l "$CACHE_FS/sys"
umount -l $CACHE_FS/proc run_command umount -l "$CACHE_FS/dev"
umount -l $CACHE_FS/sys run_command umount -l "$CACHE_FS/run"
umount -l $CACHE_FS/dev run_command umount -l "$CACHE_FS/tmp"
umount -l $CACHE_FS/run
umount -l $CACHE_FS/tmp
else else
echo " [Skip through cache]" echo " [Skip through cache]"
fi fi
cp -r $CACHE_FS/* $ROOTFS_DIR run_command cp -r "$CACHE_FS"/. "$ROOTFS_DIR"/
mount -t proc /proc $ROOTFS_DIR/proc run_command mount -t proc /proc "$ROOTFS_DIR/proc"
mount --rbind /sys $ROOTFS_DIR/sys run_command mount --rbind /sys "$ROOTFS_DIR/sys"
mount --rbind /dev $ROOTFS_DIR/dev run_command mount --rbind /dev "$ROOTFS_DIR/dev"
mount --rbind /run $ROOTFS_DIR/run run_command mount --rbind /run "$ROOTFS_DIR/run"
mount -t tmpfs tmpfs $ROOTFS_DIR/tmp run_command mount -t tmpfs tmpfs "$ROOTFS_DIR/tmp"
fi fi
echo "[Uploading configuration file...]" echo "[Uploading configuration file...]"
cp -rf config/02-customisation/* $ROOTFS_DIR run_command cp -rf config/02-customisation/* "$ROOTFS_DIR"
echo "[Checking for required dependencies...]"
if [ ! -d "/opt/limine" ]; then
echo "Error: /opt/limine not found. Please install the Limine bootloader files in /opt/limine."
exit 1
fi
if [ ! -f "$ROOTFS_DIR/usr/lib/shim/shimx64.efi.signed.latest" ] || [ ! -f "$ROOTFS_DIR/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed" ]; then
echo "Error: Required EFI files not found in $ROOTFS_DIR."
exit 1
fi
if [ -z $PXE_URL ]; then if [ -z "$PXE_URL" ]; then
EFIBOOT=$(mktemp /tmp/efiboot.img.XXXXXX)
EFIBOOT_MOUNT=$(mktemp -d /tmp/efiboot.XXXXXX)
echo "[EFI img preparation]" echo "[EFI img preparation]"
mkdir -p "$ISO_DIR/boot/grub" run_command mkdir -p "$ISO_DIR/boot/grub"
sed "s/CMDLINE/$CMDLINE/g" config/00-bootloader/grub.cfg > "$ISO_DIR/boot/grub/grub.cfg" run_command "sed 's/CMDLINE/$CMDLINE/g' config/00-bootloader/grub.cfg > $ISO_DIR/boot/grub/grub.cfg"
EFIBOOT=/tmp/efiboot.img SIZE_EFIBOOT=$(get_total_size "$ROOTFS_DIR/usr/lib/shim/shimx64.efi.signed.latest" "$ROOTFS_DIR/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed")
EFIBOOT_MOUNT=/tmp/efiboot
SIZE_EFIBOOT=$(get_total_size $ROOTFS_DIR/usr/lib/shim/shimx64.efi.signed.latest $ROOTFS_DIR/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed)
OFFSET=$(( 150 * 1024 )) # Some space for fat header and grub.cfg file OFFSET=$(( 150 * 1024 )) # Some space for fat header and grub.cfg file
fallocate -l $(( $SIZE_EFIBOOT + $OFFSET)) $EFIBOOT run_command fallocate -l $(( $SIZE_EFIBOOT + $OFFSET)) "$EFIBOOT"
run_command mkfs.vfat $EFIBOOT run_command mkfs.vfat "$EFIBOOT"
mkdir $EFIBOOT_MOUNT run_command mount -o loop "$EFIBOOT" "$EFIBOOT_MOUNT"
mount -o loop $EFIBOOT $EFIBOOT_MOUNT run_command mkdir -p "$EFIBOOT_MOUNT/EFI/BOOT"
mkdir -p $EFIBOOT_MOUNT/EFI/BOOT run_command cp config/00-bootloader/grub.efi.cfg "$EFIBOOT_MOUNT/EFI/BOOT/grub.cfg"
cp config/00-bootloader/grub.efi.cfg $EFIBOOT_MOUNT/EFI/BOOT/grub.cfg run_command cp "$ROOTFS_DIR/usr/lib/shim/shimx64.efi.signed.latest" "$EFIBOOT_MOUNT/EFI/BOOT/BOOTx64.EFI"
cp $ROOTFS_DIR/usr/lib/shim/shimx64.efi.signed.latest "$EFIBOOT_MOUNT/EFI/BOOT/BOOTx64.EFI" run_command cp "$ROOTFS_DIR/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed" "$EFIBOOT_MOUNT/EFI/BOOT/grubx64.efi"
cp $ROOTFS_DIR/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed "$EFIBOOT_MOUNT/EFI/BOOT/grubx64.efi" run_command umount "$EFIBOOT_MOUNT"
umount $EFIBOOT_MOUNT run_command rmdir "$EFIBOOT_MOUNT"
fi fi
echo "[Post-install...]" echo "[Post-install...]"
for script in config/03-post_install/*.sh; do for script in config/03-post_install/*.sh; do
./$script ./"$script"
done done
echo "[Moving kernel...]" echo "[Moving kernel...]"
cp $ROOTFS_DIR/boot/vmlinuz-* /tmp/vmlinuz KERNEL_FILE=$(ls -1 "$ROOTFS_DIR/boot/vmlinuz-"* 2>/dev/null | head -n 1)
cp $ROOTFS_DIR/boot/initrd.img /tmp/initrd if [ -z "$KERNEL_FILE" ]; then
rm -rf $ROOTFS_DIR/boot echo "Error: No kernel file found in $ROOTFS_DIR/boot"
exit 1
fi
run_command cp "$KERNEL_FILE" "$TMP_KERNEL"
run_command cp "$ROOTFS_DIR/boot/initrd.img" "$TMP_INITRD"
run_command rm -rf "$ROOTFS_DIR/boot"
echo "[Unmount subsystem...]" echo "[Unmount subsystem...]"
umount -l $ROOTFS_DIR/proc run_command umount -l "$ROOTFS_DIR/proc"
umount -l $ROOTFS_DIR/sys run_command umount -l "$ROOTFS_DIR/sys"
umount -l $ROOTFS_DIR/dev run_command umount -l "$ROOTFS_DIR/dev"
umount -l $ROOTFS_DIR/run run_command umount -l "$ROOTFS_DIR/run"
umount -l $ROOTFS_DIR/tmp run_command umount -l "$ROOTFS_DIR/tmp"
echo "[Create squash.rootfs...]" echo "[Create squash.rootfs...]"
run_command mksquashfs "$ROOTFS_DIR" "$SQUASHFS" run_command mksquashfs "$ROOTFS_DIR" "$SQUASHFS"
check_exit_code $? "Error during squashfs generation"
if [ ! -z $LUKS_PASSPHRASE ]; then if [ ! -z "$LUKS_PASSPHRASE" ]; then
echo "[Encrypt squash.rootfs...]" echo "[Encrypt squash.rootfs...]"
SQUASHFS_SIZE=$(stat -c %s "$SQUASHFS") SQUASHFS_SIZE=$(stat -c %s "$SQUASHFS")
LUKS_HEADER_SIZE=$((1024 * 1024 * 16)) # 16 MiB header LUKS2 LUKS_HEADER_SIZE=$((1024 * 1024 * 16)) # 16 MiB header LUKS2
TOTAL_SIZE=$((SQUASHFS_SIZE + LUKS_HEADER_SIZE)) TOTAL_SIZE=$((SQUASHFS_SIZE + LUKS_HEADER_SIZE))
SECTOR_SIZE=512 SECTOR_SIZE=512
fallocate -l $TOTAL_SIZE "/tmp/$SQUASHFS_IMG" run_command fallocate -l "$TOTAL_SIZE" "$TMP_SQUASHFS_IMG"
echo -n "$LUKS_PASSPHRASE" | cryptsetup luksFormat "/tmp/$SQUASHFS_IMG" --batch-mode run_command bash -c "cat <<EOF | cryptsetup luksFormat '$TMP_SQUASHFS_IMG' --batch-mode
echo -n "$LUKS_PASSPHRASE" | cryptsetup luksOpen "/tmp/$SQUASHFS_IMG" container $LUKS_PASSPHRASE
run_command dd if="$SQUASHFS" of=/dev/mapper/container bs=4M EOF"
cryptsetup luksClose container
run_command bash -c "cat <<EOF | cryptsetup luksOpen '$TMP_SQUASHFS_IMG' container
if [ ! -z $ADDITIONAL_KEYS ]; then $LUKS_PASSPHRASE
EOF"
run_command dd if="$SQUASHFS" of=/dev/mapper/container bs=4M
run_command cryptsetup luksClose container
if [ ! -z "$ADDITIONAL_KEYS" ]; then
for key in $ADDITIONAL_KEYS; do for key in $ADDITIONAL_KEYS; do
echo -e "$LUKS_PASSPHRASE\n$key" | cryptsetup luksAddKey "/tmp/$SQUASHFS_IMG" key_file=$(mktemp)
echo "$key" > "$key_file"
run_command bash -c "cat <<EOF | cryptsetup luksAddKey '$TMP_SQUASHFS_IMG'
$LUKS_PASSPHRASE
$key
EOF"
rm -f "$key_file"
done done
fi fi
else else
cp "$SQUASHFS" "/tmp/$SQUASHFS_IMG" cp "$SQUASHFS" "$TMP_SQUASHFS_IMG"
fi fi
mkdir $OUTPUT mkdir "$OUTPUT"
if [ ! -z $PXE_URL ]; then if [ ! -z "$PXE_URL" ]; then
cp /tmp/vmlinuz $OUTPUT run_command cp "$TMP_KERNEL" "$OUTPUT/vmlinuz"
cp /tmp/initrd $OUTPUT run_command cp "$TMP_INITRD" "$OUTPUT/initrd"
cp /tmp/$SQUASHFS_IMG $OUTPUT run_command cp "$TMP_SQUASHFS_IMG" "$OUTPUT/$SQUASHFS_IMG"
run_command cp "$ROOTFS_DIR/usr/lib/shim/shimx64.efi.signed.latest" "$OUTPUT/BOOTx64.EFI"
run_command cp "$ROOTFS_DIR/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed" "$OUTPUT/grubx64.efi"
CMDLINE="boot=pxe quiet splash $RAM modprobe.blacklist=floppy"
run_command "sed 's/CMDLINE/$CMDLINE/g' config/00-bootloader/grub.cfg > $OUTPUT/grub.cfg"
else else
echo "[Moving kernel && squashfs from rootfs to iso/boot...]" echo "[Moving kernel && squashfs from rootfs to iso/boot...]"
mkdir -p $BOOT_FOLDER run_command mkdir -p "$BOOT_FOLDER"
cp /tmp/vmlinuz $BOOT_FOLDER/vmlinuz run_command cp "$TMP_KERNEL" "$BOOT_FOLDER/vmlinuz"
cp /tmp/initrd $BOOT_FOLDER/initrd run_command cp "$TMP_INITRD" "$BOOT_FOLDER/initrd"
echo "[Create iso...]" echo "[Create iso...]"
cp /tmp/$SQUASHFS_IMG $ISO_DIR/$SQUASHFS_IMG run_command cp "$TMP_SQUASHFS_IMG" "$ISO_DIR/$SQUASHFS_IMG"
cp /opt/limine/*.bin "$ISO_DIR/" run_command cp /opt/limine/*.bin "$ISO_DIR/"
cp /opt/limine/*.sys "$ISO_DIR/" run_command cp /opt/limine/*.sys "$ISO_DIR/"
cp $EFIBOOT $ISO_DIR run_command cp "$EFIBOOT" "$ISO_DIR/efiboot.img"
sed "s/CMDLINE/$CMDLINE/g" config/00-bootloader/limine.conf > "$ISO_DIR/boot/limine.conf" run_command "sed 's/CMDLINE/$CMDLINE/g' config/00-bootloader/limine.conf > $ISO_DIR/boot/limine.conf"
run_command xorriso -as mkisofs -R -r -J -b "limine-bios-cd.bin" \ run_command xorriso -as mkisofs -R -r -J -b "limine-bios-cd.bin" \
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \ -no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
-apm-block-size 2048 --efi-boot "efiboot.img" \ -apm-block-size 2048 --efi-boot "efiboot.img" \
...@@ -296,8 +355,10 @@ else ...@@ -296,8 +355,10 @@ else
-volid "NEXUSCLIENTISO" \ -volid "NEXUSCLIENTISO" \
"$ISO_DIR" -o "$OUTPUT/$ISO_NAME" "$ISO_DIR" -o "$OUTPUT/$ISO_NAME"
check_exit_code $? "Error during iso creation"
run_command limine bios-install "$OUTPUT/$ISO_NAME" run_command limine bios-install "$OUTPUT/$ISO_NAME"
fi fi
chown -R 1000:1000 "$OUTPUT" chown -R 1000:1000 "$OUTPUT"
echo "[Cleanup temporary files...]"
rm -f "$TMP_KERNEL" "$TMP_INITRD" "$TMP_SQUASHFS_IMG" "$EFIBOOT"
menu hidden
menu autoboot "Booting nexus-live-exam..."
menu background black.png
menu title nexus-live-exam
include live.cfg
menu disable
menu end
default vesamenu.c32
prompt 0
timeout 1
totaltimeout 1
live_exam_os/config/00-bootloader/isolinux.png

2.38 KiB

live_exam_os/config/01-build_hooks/wallpapers/wallpaper.png

194 KiB

#!/bin/sh #!/bin/bash
. tools/functions.sh . tools/functions.sh
......
#!/bin/sh #!/bin/bash
. tools/functions.sh . tools/functions.sh
......
#/bin/bash
run() { run() {
chroot "$ROOTFS_DIR" $@ chroot "$ROOTFS_DIR" $@
} }
...@@ -12,7 +14,7 @@ run_command() { ...@@ -12,7 +14,7 @@ run_command() {
bash -c "$cmd" > /dev/null 2>&1 bash -c "$cmd" > /dev/null 2>&1
EXIT_CODE=$? EXIT_CODE=$?
fi fi
return $EXIT_CODE check_exit_code $EXIT_CODE "Error durring command execution : $cmd"
} }
run_command_chroot() { run_command_chroot() {
...@@ -23,7 +25,7 @@ check_exit_code() { ...@@ -23,7 +25,7 @@ check_exit_code() {
EXIT_CODE=$1 EXIT_CODE=$1
if [ ! $EXIT_CODE -eq 0 ]; then if [ ! $EXIT_CODE -eq 0 ]; then
echo $2 echo $2
exit exit 1
fi fi
} }
...@@ -49,3 +51,29 @@ get_total_size() { ...@@ -49,3 +51,29 @@ get_total_size() {
done done
echo "$total" echo "$total"
} }
check_inside_container() {
if [ ! -f "/.dockerenv" ] && [ ! -f "/run/.containerenv" ]; then
echo "Error: This script must be run inside a Docker or Podman container."
exit 1
fi
}
check_dependencies() {
local dependencies=(debootstrap chroot sed mount umount fallocate mkfs.vfat mksquashfs cryptsetup bash xorriso limine)
local missing=()
for cmd in "${dependencies[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
missing+=("$cmd")
fi
done
if [ "${#missing[@]}" -ne 0 ]; then
echo "Error: The following required tools are missing or not in the PATH:" >&2
for tool in "${missing[@]}"; do
echo " - $tool" >&2
done
exit 1
fi
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment