From f7c44144cf84205c466e8c093e639a8583995716 Mon Sep 17 00:00:00 2001
From: ping <dev@guillaumepin.ch>
Date: Tue, 7 Jan 2025 11:06:55 +0100
Subject: [PATCH] Refactor of live_exam_os for ubuntu

---
 live_exam_os/.env.example                     |  20 +
 live_exam_os/.gitignore                       |   4 +-
 live_exam_os/Dockerfile                       |  30 +-
 live_exam_os/Makefile                         |  45 +--
 live_exam_os/README.md                        | 167 ++++----
 live_exam_os/build.sh                         | 376 +++++++++---------
 live_exam_os/config/00-bootloader/limine.cfg  |   7 -
 live_exam_os/config/00-bootloader/limine.conf |   7 +
 .../config/00-bootloader/limine_casper.conf   |   7 +
 .../config/00-bootloader/limine_pxe.conf      |   7 +
 live_exam_os/config/01-initramfs/init         |  55 ---
 live_exam_os/config/01-initramfs/init_no_luks |  53 ---
 .../config/01-packages_install/packages       |  21 +
 .../NetworkManager/NetworkManager.conf.bak    |   8 +
 .../conf.d/10-default-wired.conf.bak          |  10 +
 .../conf.d/10-globally-managed-devices.conf   |   0
 .../etc/NetworkManager/conf.d/dns.conf.bak    |   2 +
 .../wifi.nmconnection.example1                |   0
 .../wifi.nmconnection.example2                |   0
 .../config/02-customisation/etc/challenge     |   1 +
 .../02-customisation/etc/default/keyboard     |  10 +
 .../etc/initramfs-tools/hooks/nexus           |   6 +
 .../etc/initramfs-tools/hooks/pxe             |   9 +
 .../etc/initramfs-tools/hooks/yubikey         |   7 +
 .../etc/initramfs-tools/scripts/init          |  68 ++++
 .../etc/initramfs-tools/scripts/pxe           |  93 +++++
 .../getty@tty1.service.d/autologin.conf       |   3 +
 .../etc/xdg/autostart/nexus-exam.desktop      |   0
 .../xfce-perchannel-xml/xfce4-desktop.xml     |   0
 .../xfce-perchannel-xml/xfce4-panel.xml       |   0
 .../xfce4-power-manager.xml                   |   0
 .../xfce4-settings-manager.xml                |   0
 .../xfconf/xfce-perchannel-xml/xfwm4.xml      |   0
 .../02-customisation/home/user/.profile       |   5 +
 .../home/user/.xinitrc                        |   0
 .../usr/local/bin/nexus-exam.desktop          |   0
 .../config/02-packages_install/packages       |   3 -
 .../system-connections/wifi.nmconnection      |  32 --
 .../03-customisation/etc/default/keyboard     |  10 -
 .../config/03-customisation/etc/inittab       |  17 -
 .../03-customisation/home/user/.profile       |   1 -
 .../03-post_install/1000-create-user.sh       |  10 +
 .../03-post_install/1000-disable_root.sh      |   6 +
 .../03-post_install/2000-enable_services.sh   |   7 +
 .../config/03-post_install/3000-nexus_exam.sh |  17 +
 .../config/03-post_install/4000-firewall.sh   |  16 +
 .../config/03-post_install/5000-pxe.sh        |   8 +
 .../config/03-post_install/9999-initramfs.sh  |   7 +
 .../04-post_install/1000-create-user.sh       |  16 -
 .../04-post_install/1000-disable_root.sh      |   8 -
 .../04-post_install/2000-enable_services.sh   |  13 -
 .../config/04-post_install/9999-firewall.sh   |  18 -
 live_exam_os/tools/functions.sh               |  39 ++
 53 files changed, 708 insertions(+), 541 deletions(-)
 create mode 100644 live_exam_os/.env.example
 delete mode 100644 live_exam_os/config/00-bootloader/limine.cfg
 create mode 100644 live_exam_os/config/00-bootloader/limine.conf
 create mode 100644 live_exam_os/config/00-bootloader/limine_casper.conf
 create mode 100644 live_exam_os/config/00-bootloader/limine_pxe.conf
 delete mode 100644 live_exam_os/config/01-initramfs/init
 delete mode 100644 live_exam_os/config/01-initramfs/init_no_luks
 create mode 100644 live_exam_os/config/01-packages_install/packages
 create mode 100644 live_exam_os/config/02-customisation/etc/NetworkManager/NetworkManager.conf.bak
 create mode 100644 live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/10-default-wired.conf.bak
 create mode 100644 live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/10-globally-managed-devices.conf
 create mode 100644 live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/dns.conf.bak
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/NetworkManager/system-connections/wifi.nmconnection.example1 (100%)
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/NetworkManager/system-connections/wifi.nmconnection.example2 (100%)
 create mode 100644 live_exam_os/config/02-customisation/etc/challenge
 create mode 100644 live_exam_os/config/02-customisation/etc/default/keyboard
 create mode 100755 live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/nexus
 create mode 100755 live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/pxe
 create mode 100755 live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/yubikey
 create mode 100755 live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/init
 create mode 100755 live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/pxe
 create mode 100644 live_exam_os/config/02-customisation/etc/systemd/system/getty@tty1.service.d/autologin.conf
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/xdg/autostart/nexus-exam.desktop (100%)
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml (100%)
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml (100%)
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml (100%)
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-settings-manager.xml (100%)
 rename live_exam_os/config/{03-customisation => 02-customisation}/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml (100%)
 create mode 100644 live_exam_os/config/02-customisation/home/user/.profile
 rename live_exam_os/config/{03-customisation => 02-customisation}/home/user/.xinitrc (100%)
 rename live_exam_os/config/{03-customisation => 02-customisation}/usr/local/bin/nexus-exam.desktop (100%)
 delete mode 100644 live_exam_os/config/02-packages_install/packages
 delete mode 100644 live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection
 delete mode 100644 live_exam_os/config/03-customisation/etc/default/keyboard
 delete mode 100644 live_exam_os/config/03-customisation/etc/inittab
 delete mode 100644 live_exam_os/config/03-customisation/home/user/.profile
 create mode 100755 live_exam_os/config/03-post_install/1000-create-user.sh
 create mode 100755 live_exam_os/config/03-post_install/1000-disable_root.sh
 create mode 100755 live_exam_os/config/03-post_install/2000-enable_services.sh
 create mode 100755 live_exam_os/config/03-post_install/3000-nexus_exam.sh
 create mode 100755 live_exam_os/config/03-post_install/4000-firewall.sh
 create mode 100755 live_exam_os/config/03-post_install/5000-pxe.sh
 create mode 100755 live_exam_os/config/03-post_install/9999-initramfs.sh
 delete mode 100755 live_exam_os/config/04-post_install/1000-create-user.sh
 delete mode 100755 live_exam_os/config/04-post_install/1000-disable_root.sh
 delete mode 100755 live_exam_os/config/04-post_install/2000-enable_services.sh
 delete mode 100755 live_exam_os/config/04-post_install/9999-firewall.sh
 create mode 100755 live_exam_os/tools/functions.sh

diff --git a/live_exam_os/.env.example b/live_exam_os/.env.example
new file mode 100644
index 0000000..c0e640d
--- /dev/null
+++ b/live_exam_os/.env.example
@@ -0,0 +1,20 @@
+# Location of generated files
+export SQUASHFS="/tmp/squashfs"
+export ROOTFS_DIR="/tmp/rootfs"
+export ISO_DIR="/tmp/iso"
+export BOOT_FOLDER="$ISO_DIR/boot"
+export LUKS_IMG="squash.rootfs.luks"
+
+# 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 VERBOSE=false
+#export PXE_URL="127.0.0.1:8000"
+export OUTPUT="build"
+export CACHE_FS="cache"
diff --git a/live_exam_os/.gitignore b/live_exam_os/.gitignore
index 9d78b0d..d8019d8 100644
--- a/live_exam_os/.gitignore
+++ b/live_exam_os/.gitignore
@@ -1,2 +1,4 @@
-output/
 *.iso
+.env
+cache/
+config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection
diff --git a/live_exam_os/Dockerfile b/live_exam_os/Dockerfile
index becfe63..c8909d9 100644
--- a/live_exam_os/Dockerfile
+++ b/live_exam_os/Dockerfile
@@ -1,25 +1,23 @@
-#ARG ALPINE_VERSION
-
 ARG DEBIAN_FRONTEND=noninteractive
-#FROM alpine:${ALPINE_VERSION}
 FROM ubuntu:22.04
 
-#RUN apk add mtools xorriso squashfs-tools cryptsetup e2fsprogs limine-x86_64 limine-cd
-
-
+ENV archive=go1.22.6.linux-amd64.tar.gz
+ENV PATH=$PATH:/usr/local/go/bin
 
-RUN apt-get update && apt-get install -y gcc pkg-config git wget make ca-certificates libglfw3-dev libxcursor-dev libxinerama-dev libxi-dev libxxf86vm-dev upx-ucl
+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y gcc pkg-config git wget make ca-certificates libglfw3-dev libxcursor-dev libxinerama-dev libxi-dev libxxf86vm-dev upx-ucl curl cryptsetup squashfs-tools fakechroot debootstrap xorriso
 
-RUN DEBIAN_FRONTEND=noninteractive apt install -y cryptsetup squashfs-tools
-RUN apt install -y debootstrap schroot
+RUN git clone https://github.com/limine-bootloader/limine.git --branch=v8.x-binary --depth=1 /opt/limine && \
+    cd /opt/limine && \
+    make && \
+    cp /opt/limine/limine /bin/
 
-RUN git clone https://github.com/limine-bootloader/limine.git --branch=v8.x-binary --depth=1 /opt/limine
+RUN wget https://go.dev/dl/$archive && tar -C /usr/local -xzf $archive
 
-# Install go 1.22 from the official GO site
-ENV archive=go1.22.6.linux-amd64.tar.gz
-ENV PATH=$PATH:/usr/local/go/bin
+WORKDIR /nexus
 
-RUN wget https://go.dev/dl/$archive
-RUN tar -C /usr/local -xzf $archive
+RUN mkdir src
+COPY src src
+COPY Makefile .
+COPY ca-cert.pem .
 
-RUN apt install -y xorriso
+RUN make build_nexus-exam SERVER="127.0.0.1:1077" CERT="ca-cert.pem" EXAM_USER="user" EXAM_PWD="pwd"
diff --git a/live_exam_os/Makefile b/live_exam_os/Makefile
index edc51ea..254f262 100644
--- a/live_exam_os/Makefile
+++ b/live_exam_os/Makefile
@@ -1,41 +1,20 @@
-image_name := builder_alpine_iso
-alpine_version := "3.20.3"
-iso_file := image.iso
-output := output
-squashfs_file := ${output}/squash.rootfs
-root_fs := ${output}/rootfs
-initrd_fs := ${output}/initrd
-iso_path := ${output}/iso
-server_ip := "127.0.0.1"
-server_port := "1077"
-cert := "ca-cert.pem"
-exam_user := "user"
-exam_pwd := "password"
+image_name := builder_nexus_iso
 
-all: build
+all: build 
 
-build: build_container clean
-	sudo docker run -it --rm -v $(PWD)/..:/data --workdir /data/live_exam_os --privileged -e SQUASHFS=${squashfs_file} -e ROOTFS_DIR=${root_fs} -e INITRD_DIR=${initrd_fs} -e ISO_DIR=${iso_path} -e SERVER="${server_ip}:${server_port}" -e CERT=${cert} -e EXAM_USER=${exam_user} -e EXAM_PWD=${exam_pwd} ${image_name} ./build.sh ${iso_file} "123" --alpine-version ${alpine_version} --user-password "0"
-	sudo chown ${USER}:${USER} ${iso_file}
+run:
+	sudo docker run -it --rm -v $(PWD)/..:/data --workdir /data/live_exam_os --privileged ${image_name} ./build.sh $(PARAM)
 
-no_luks: build_container clean
-	sudo docker run -it --rm -v $(PWD)/..:/data --workdir /data/live_exam_os --privileged -e SQUASHFS=${squashfs_file} -e ROOTFS_DIR=${root_fs} -e INITRD_DIR=${initrd_fs} -e ISO_DIR=${iso_path} -e SERVER="${server_ip}:${server_port}" -e CERT=${cert} -e EXAM_USER=${exam_user} -e EXAM_PWD=${exam_pwd} ${image_name} ./build.sh ${iso_file} '' --no-luks --alpine-version ${alpine_version} --user-password "0"
-	sudo chown ${USER}:${USER} ${iso_file}
-
-build_container:
-	sudo docker build -t ${image_name} --build-arg ALPINE_VERSION=${alpine_version} . 
-
-clean:
-	sudo rm -rf ${iso_file} ${output}
-
-uefi:
-	qemu-system-x86_64 -bios /usr/share/OVMF/x64/OVMF.fd -drive file=${iso_file},format=raw -boot d -m 16G -smp 4 -netdev user,id=n1 -device virtio-net-pci,netdev=n1
+build:
+	cd .. && sudo docker build -t ${image_name} -f live_exam_os/Dockerfile .
 
 bios:
-	qemu-system-x86_64 -drive file=${iso_file},format=raw -boot d -m 4G -smp 4
+	qemu-system-x86_64 -drive file=$(ISO),format=raw -boot d -m 4G -smp 4
 
 bios_cd:
-	qemu-system-x86_64 -drive file=${iso_file},media=cdrom,if=ide,readonly=on -boot d -m 4G -smp 4
+	qemu-system-x86_64 -drive file=$(ISO),media=cdrom,if=ide,readonly=on -boot d -m 4G -smp 4
+
+uefi:
+	qemu-system-x86_64 -bios /usr/share/OVMF/x64/OVMF.fd -drive file=$(ISO),format=raw -boot d -m 16G -smp 4 -netdev user,id=n1 -device virtio-net-pci,netdev=n1 -serial mon:stdio
 
-uefiserie:
-	qemu-system-x86_64 -bios /usr/share/OVMF/x64/OVMF.fd -drive file=${iso_file},format=raw -boot d -m 16G -smp 4 -netdev user,id=n1 -device virtio-net-pci,netdev=n1 -serial mon:stdio
+.PHONY: build
diff --git a/live_exam_os/README.md b/live_exam_os/README.md
index 2a6989a..05ca500 100644
--- a/live_exam_os/README.md
+++ b/live_exam_os/README.md
@@ -1,103 +1,126 @@
-# live_exam_os
+# Live Exam OS Builder
 
-This project aims to create a minimal live operating system in the form of an ISO image, specifically designed for use on any computer. The generated ISO boots directly into a lightweight XFCE desktop environment and automatically launches the nexus-client. The focus is on simplicity, speed and portability.
+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.
 
-The ISO is based on Alpine Linux, known for its small footprint and security. LUKS encryption to secure the filesystem is enabled by default and can be disabled.
+---
 
-## Features
+## Usage
 
- - Minimal ISO: Starts with a lightweight Alpine Linux base.
- - Encryption: Utilizes LUKS encryption for securing the filesystem (optional).
- - Desktop Environment: Configured for autologin with a minimal desktop environment.
- - Nexus Client: Auto-launches the nexus-client at startup.
- - Customizable: Flexible options for user credentials, Alpine version, and additional files.
+To use the script, run it with the following command:
 
-## Prerequisites
-
- - Docker: Used to containerize the build process.
- - QEMU: Optional, for testing the generated ISO.
-
-## Environment Setup
-
-The build.sh script use several environment variables for flexibility:
+```bash
+./build.sh [options]
+```
 
-| Variable	| Description	|Example|
-|-|-|-|
-| SQUASHFS	| Path to SquashFS file	| out/squash.rootfs |
-| ROOTFS_DIR |	Temporary root filesystem directory |	out/rootfs |
-| INITRD_DIR |	Temporary initrd directory	| out/initrd |
-| ISO_DIR|	Temporary ISO directory	| out/iso |
-| SERVER |	Server details | 127.0.0.1:1077 |
-| CERT|	Path to Certificate file	|ca-cert.pem |
-| EXAM_USER|	Default user for exam client|	user |
-| EXAM_PWD|	Default password for exam client |	password |
+### Requirements
 
-## build.sh Script
+The `build.sh` script should be executed on a Ubuntu/Debian environment with the following tools installed:
+- `debootstrap`
+- Other necessary dependencies for building ISO images.
 
-The script build.sh generates the live ISO with various options for customization.
+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.
 
-### Syntax
+### Options
 
-./build.sh iso_output_path luks_passphrase [options]
+| Option                | Description |
+|-----------------------|-------------|
+| `-v, --verbose`      | Enable verbose mode for detailed output. |
+| `--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. |
+| `--pxe`              | Set the URL of the PXE and generate an initramfs, kernel, and SquashFS for PXE use. |
+| `--cache`            | Specify the path to a folder containing a pre-downloaded clean filesystem. |
 
-### Required Arguments
+### Environment Setup Parameters
 
- - iso_output_path: Path to save the generated ISO image (e.g., out/iso/alpine.iso).
- - luks_passphrase: Passphrase for LUKS encryption. Leave blank when using --no-luks.
+| Parameter      | Description |
+|----------------|-------------|
+| `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`). |
 
-### Options
+---
 
- - --no-luks: Disable LUKS encryption (makes luks_passphrase optional).
- - --alpine-version: Specify Alpine Linux version (default: 3.20.3).
- - --root-enabled: Enable root access (default: disabled).
- - --root-password: Set the root password (ignored if root is disabled).
- - --user-password: Set the default user password.
+## Example Usage
 
-### Example Usage
-
-#### With Encryption:
+Here are some examples of how to use the script:
 
+### Example 1
+Build an ISO image with LUKS encryption:
 ```bash
-./build.sh out/iso/alpine.iso 'my_luks_pass' --alpine-version 3.16 --root-enabled yes --root-password 'rootpass' --user-password 'userpass'
+./build.sh --env .env
 ```
 
-#### Without Encryption:
+### Example 2
+Build an ISO image without LUKS encryption:
 ```bash
-./build.sh out/iso/alpine.iso '' --no-luks --alpine-version 3.18
+./build.sh --output build --luks-passphrase 'my_luks_pass' --cache cache --pxe
 ```
 
+---
 
-## Usage Instructions
-### Build the ISO
+## Makefile Targets
 
-The core ISO creation is handled by the script build.sh. For development, a Makefile is included to set up the environment and execute the script inside a Docker container.
+The Makefile includes targets to facilitate the building, running, and testing processes.
 
-#### Buld the ISO with encryption
-Builds an encrypted ISO using LUKS with a default password of "123".
-```
-make build
-```
+### Available Targets
 
-#### Build the ISO without encryption
-```
-make no_luks
-```
+| 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. |
 
-### Testing the ISO
+### Running Makefile Targets
 
-After building the ISO, you can test it using QEMU:
+1. **Build the Docker Image**:
+   ```bash
+   make build
+   ```
 
-#### UEFI Environment:
-```
-make uefi
-```
+2. **Run the Build Script**:
+   ```bash
+   make run PARAM="--env .env"
+   ```
 
-#### BIOS Environment:
-```
-make bios
-```
+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
+     ```
 
-#### BIOS as CD-ROM:
-```
-make bios_cd
-```
+---
+
+## Project Components
+
+### Scripts
+- **build.sh**: Main script to build the ISO image and configure the environment.
+
+### Docker
+- **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.
+
+### Configuration Files
+- **Environment file**: Provides parameters and paths required by the build script.
+
+---
+
+## 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`).
diff --git a/live_exam_os/build.sh b/live_exam_os/build.sh
index 9837640..f222c65 100755
--- a/live_exam_os/build.sh
+++ b/live_exam_os/build.sh
@@ -1,31 +1,32 @@
-#!/bin/sh
+#!/bin/bash
 
-ALPINE_VERSION="3.20.3"
-ROOT_ENABLED="no"
-LUKS_ENABLED="yes"
-ROOT_PASSWORD=""
-USER_PASSWORD=""
-LUKS_IMG="squash.rootfs.luks"
-BOOT_FOLDER="$ISO_DIR/boot"
+. tools/functions.sh
+
+# Default variables
+export SQUASHFS="/tmp/squashfs"
+export ROOTFS_DIR="/tmp/rootfs"
+export ISO_DIR="/tmp/iso"
+export BOOT_FOLDER="$ISO_DIR/boot"
+export LUKS_IMG="squash.rootfs.luks"
+export VERBOSE=false
+export OUTPUT="."
+export ISO_NAME="nexus.iso"
 
 helper() {
-  echo "USAGE: $(basename "$0") iso_output_path luks_passphrase [options]"
-  echo
-  echo "Required arguments:"
-  echo "  iso_output_path       Path where the generated ISO image will be saved (e.g., out/iso/alpine.iso)"
-  echo "  luks_passphrase       LUKS encryption passphrase for securing the filesystem"
+  echo "USAGE: $(basename "$0") [options]"
   echo
   echo "Options:"
-  echo "  --no-luks             Disable LUKS encryption (makes luks_passphrase optional)"
-  echo "  --alpine-version      Specify the Alpine Linux version to use (default: 3.20.3)"
-  echo "  --root-enabled        Enable root access (default: disabled)"
-  echo "  --root-password       Set the root password (ignored if root is disabled)"
-  echo "  --user-password       Set the default user password"
+  echo "  -v, --verbose         Set verbose mode"
+  echo "  --env                 Path to an env file with all described parameters"
+  echo "  --output              Set the output folder (default: .)"
+  echo "  --luks-passphrase     Enable LUKS encryption with passphrase"
+  echo "  --luks-keys           List of additional keys"
+  echo "  --pxe                 Set the url of the pxe and generate an initramfs, kernel and squashfs for pxe use"
+  echo "  --cache               Path to a folder with a clean fs already downloaded"
   echo
   echo "Environment Setup Parameters:"
   echo "  SQUASHFS              Path to the SquashFS file (e.g., out/squash.rootfs)"
   echo "  ROOTFS_DIR            Path to the temporary filesystem directory (e.g., out/rootfs)"
-  echo "  INITRD_DIR            Temporary directory for initrd (e.g., out/initrd)"
   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 "  CERT 	                Path to the Certificate file 	(e.g., ca-cert.pem)"
@@ -33,88 +34,62 @@ helper() {
   echo "  EXAM_PWD              Default password for exam client 	(e.g., password)"
   echo
   echo "Example Usage:"
-  echo "  $(basename "$0") out/iso/alpine.iso 'my_luks_pass' --alpine-version 3.16 --root-enabled yes --root-password 'rootpass' --user-password 'userpass'"
-  echo "  $(basename "$0") out/iso/alpine.iso '' --no-luks --alpine-version 3.18"
+  echo "  $(basename "$0") --env .env"
+  echo "  $(basename "$0") --luks-passphrase mypassphrase --cache cache -v"
   exit 1
 }
 
-check_container_and_alpine_version() {
-  if [ ! -f "/.dockerenv" ] && [ ! -f "/run/.containerenv" ]; then
-    echo "Error: This script should be run inside a container environment on Alpine Linux version $ALPINE_VERSION."
-    helper
-  fi
-
-  if [ -f "/etc/os-release" ]; then
-    . /etc/os-release
-    if [ "$ID" != "alpine" ] || [ "$VERSION_ID" != "$ALPINE_VERSION" ]; then
-      echo "Error: This script should be run inside a container environment on Alpine Linux version $ALPINE_VERSION."
-      echo "Actual version: $VERSION_ID"
-      helper
-    fi
-  else
-    echo "Error: This script should be run inside a container environment on Alpine Linux version $ALPINE_VERSION."
-    helper
-  fi
-}
-
-check_environment_var() {
-  if [ -z $SQUASHFS ] || [ -z $ROOTFS_DIR ] || [ -z $INITRD_DIR ] || [ -z $ISO_DIR ]; then
-    echo "Error: Environment variables aren't set"
-    helper
-  fi
-}
-
-run() {
-  chroot "$ROOTFS_DIR" $@
-}
-
-if [ "$#" -lt 2 ]; then
-  helper
-fi
-
-ISO_OUTPUT_PATH="$1"
-LUKS_PASSPHRASE="$2"
-shift 2
-
 while [ "$#" -gt 0 ]; do
   case "$1" in
-    --no-luks)
-      LUKS_ENABLED="no"
-      shift
+    --env)
+      source $2 > /dev/null
+      shift 2
       ;;
-    --alpine-version)
+    --ouput)
       if [ -n "$2" ]; then
-        ALPINE_VERSION="$2"
+        export OUTPUT="$2"
         shift 2
       else
-        echo "Error: --alpine-version requires an argument" >&2
+        echo "Error: --output requires an argument" >&2
         helper
       fi
       ;;
-    --root-enabled)
-      if [ "$2" = "yes" ] || [ "$2" = "no" ]; then
-        ROOT_ENABLED="$2"
+    --luks-passphrase)
+      LUKS_PASSPHRASE="$2"
+      shit 2
+      ;;
+    --luks-keys)
+      if [ -n "$2" ]; then
+        ADDITIONAL_KEYS="$2"
         shift 2
       else
-        echo "Error: --root-enabled must be 'yes' or 'no'" >&2
+        echo "Error: --luks-keys requires an argument" >&2
         helper
       fi
       ;;
-    --root-password)
+    --pxe)
       if [ -n "$2" ]; then
-        ROOT_PASSWORD="$2"
+        export PXE_URL="$2"
         shift 2
       else
-        echo "Error: --root-password requires an argument" >&2
+        echo "Error: --pxe requires an argument" >&2
         helper
       fi
       ;;
-    --user-password)
+    -v)
+      export VERBOSE=true
+      shift
+      ;;
+    --verbose)
+      export VERBOSE=true
+      shift
+      ;;
+    --cache)
       if [ -n "$2" ]; then
-        USER_PASSWORD="$2"
+        export CACHE_FS=$2
         shift 2
       else
-        echo "Error: --user-password requires an argument" >&2
+        echo "Error: --cache requires an argument" >&2
         helper
       fi
       ;;
@@ -125,149 +100,178 @@ while [ "$#" -gt 0 ]; do
   esac
 done
 
-if [ "$LUKS_ENABLED" = "yes" ] && [ -z "$LUKS_PASSPHRASE" ]; then
-  echo "Error: LUKS encryption is enabled, but no passphrase was provided." >&2
-  helper
-fi
-
-#check_container_and_alpine_version
 check_environment_var
 
-#echo "[Compiling nexus-exam...]"
-#cd ..
-#make build_nexus-exam
-#mkdir -p live_exam_os/$ROOTFS_DIR/usr/local/bin
-#cp build/nexus-exam live_exam_os/$ROOTFS_DIR/usr/local/bin/nexus-exam
-#make clean_client
-#cd -
-
-echo "[Create initramfs...]"
-rm -rf $INITRD_DIR
-mkdir -p "$INITRD_DIR"
-if [ "$LUKS_ENABLED" = "yes" ]; then
-    packages="busybox cryptsetup libblkid1 libuuid1 libdevmapper1.02.1 libcryptsetup12 \
-              libargon2-1 libjson-c5 libudev1 kmod zlib1g xz-utils zstd"
-else
-    packages="busybox libblkid1 libudev1 kmod zlib1g xz-utils zstd"
-fi
-
-chmod 777 $INITRD_DIR
-
-cd $INITRD_DIR
-for package in $packages; do
-    apt download "$package" --allow-unauthenticated 
-done
-
-for deb in *.deb; do
-  echo "$deb"
-    dpkg-deb -x "$deb" .
-    rm "$deb"
-done
-cd ../..
-
-
-#apk update
-#if [ $LUKS_ENABLED = "yes" ]; then
-#  cp config/01-initramfs/init $INITRD_DIR/init
-#  packages="busybox musl cryptsetup cryptsetup-libs popt libuuid libblkid 
-#            device-mapper-libs libcrypto3 argon2-libs json-c libeconf 
-#            udev kmod-libs zlib xz-libs zstd-libs"
-#else
-#  cp config/01-initramfs/init_no_luks $INITRD_DIR/init
-#  packages="busybox musl libblkid libeconf libcrypto3
-#            udev kmod-libs zlib xz-libs zstd-libs"
-#fi
-#chmod +x $INITRD_DIR/init
-#for package in $packages; do
-#  apk fetch -s "$package" > "$INITRD_DIR/$package.apk"
-#  tar -xzf "$INITRD_DIR/$package.apk" -C $INITRD_DIR
-#  rm "$INITRD_DIR/$package.apk"
-#done
 
 echo "[Create filesystem...]"
+rm -rf "$ROOTFS_DIR" "$OUTPUT"
 mkdir -p "$ROOTFS_DIR"
-#apk add --initdb --root "$ROOTFS_DIR"
-#cp /etc/apk/repositories "$ROOTFS_DIR/etc/apk/repositories"
 
-echo "[Installing packages...]"
-debootstrap --arch=amd64 focal $ROOTFS_DIR http://archive.ubuntu.com/ubuntu/
-chroot $ROOTFS_DIR /bin/bash -c "
-apt update &&
-DEBIAN_FRONTEND=noninteractive apt install -y \$(cat config/02-packages_install/packages)"
+if [ -z $CACHE_FS ]; then
+  echo "debootstrap --arch=amd64 noble $ROOTFS_DIR http://archive.ubuntu.com/ubuntu/"
+  debootstrap --arch=amd64 noble $ROOTFS_DIR http://archive.ubuntu.com/ubuntu/
+  mount -t proc /proc $ROOTFS_DIR/proc
+  mount --rbind /sys $ROOTFS_DIR/sys
+  mount --rbind /dev $ROOTFS_DIR/dev
+  mount --rbind /run $ROOTFS_DIR/run
+  mount -t tmpfs tmpfs $ROOTFS_DIR/tmp
+  
+  
+  echo "[Installing packages...]"
+  packages=$(tr '\n' ' ' < config/01-packages_install/packages)
+  echo "deb http://archive.ubuntu.com/ubuntu noble main universe" > $ROOTFS_DIR/etc/apt/sources.list
+  run_command_chroot apt update
+  check_exit_code $? "Error during apt update"
+  run_command_chroot apt install -y --no-install-recommends zstd initramfs-tools linux-image-generic linux-firmware casper cryptsetup-initramfs $packages
+  check_exit_code $? "Error during packages installation"
+else
+  if [ ! -d $CACHE_FS ]; then
+    mkdir $CACHE_FS
+    debootstrap --arch=amd64 noble $CACHE_FS http://archive.ubuntu.com/ubuntu/
+
+    mount -t proc /proc $CACHE_FS/proc
+    mount --rbind /sys $CACHE_FS/sys
+    mount --rbind /dev $CACHE_FS/dev
+    mount --rbind /run $CACHE_FS/run
+    mount -t tmpfs tmpfs $CACHE_FS/tmp
+    
+    
+    echo "[Installing packages...]"
+    packages=$(tr '\n' ' ' < config/01-packages_install/packages)
+    echo "deb http://archive.ubuntu.com/ubuntu noble main universe" > $CACHE_FS/etc/apt/sources.list
+    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 zstd initramfs-tools linux-image-generic linux-firmware casper cryptsetup-initramfs $packages
+    check_exit_code $? "Error during packages installation"
+
+    umount -l $CACHE_FS/proc
+    umount -l $CACHE_FS/sys
+    umount -l $CACHE_FS/dev
+    umount -l $CACHE_FS/run
+    umount -l $CACHE_FS/tmp
+  else
+    echo "Skip through cache"
+  fi
 
-echo "[Installing kernel...]"
-chroot $ROOTFS_DIR /bin/bash -c "
-apt update &&
-DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends linux-image-generic"
-# &&
-#update-initramfs -c -k all"
+  cp -r $CACHE_FS/* $ROOTFS_DIR
 
-#apk update --root "$ROOTFS_DIR" --allow-untrusted
-#apk add --root "$ROOTFS_DIR" --allow-untrusted $(cat config/02-packages_install/packages) &>/dev/null
-mkdir -p $INITRD_DIR/lib
-cp -r $ROOTFS_DIR/lib/modules $INITRD_DIR/lib/
+  mount -t proc /proc $ROOTFS_DIR/proc
+  mount --rbind /sys $ROOTFS_DIR/sys
+  mount --rbind /dev $ROOTFS_DIR/dev
+  mount --rbind /run $ROOTFS_DIR/run
+  mount -t tmpfs tmpfs $ROOTFS_DIR/tmp
+fi
 
 echo "[Uploading configuration file...]"
-cd config/03-customisation
-cp -R --parents * ../../$ROOTFS_DIR
-cd ../..
+cp -rf config/02-customisation/* $ROOTFS_DIR
 
 echo "[Post-install...]"
-for script in config/04-post_install/*.sh; do
+for script in config/03-post_install/*.sh; do
   ./$script
 done
 
-echo "[Moving kernel from rootfs to iso/boot...]"
-mkdir -p $BOOT_FOLDER
-cp $ROOTFS_DIR/boot/vmlinuz-* $BOOT_FOLDER
+echo "[Moving kernel..]"
+cp $ROOTFS_DIR/boot/vmlinuz-* /tmp/vmlinuz
+cp $ROOTFS_DIR/boot/initrd.img /tmp/initrd
 rm -rf $ROOTFS_DIR/boot
 
-echo "[Create initrd...]"
-mkdir -p "$INITRD_DIR/usr/bin"
-chroot "$INITRD_DIR" /bin/busybox --install
-TMP_PWD=$(pwd)
-cd $INITRD_DIR
-find . | cpio -R root:root -H newc -o | gzip > $TMP_PWD/$BOOT_FOLDER/initrd
-cd $TMP_PWD
+echo "[Unmount subsystem...]"
+umount -l $ROOTFS_DIR/proc
+umount -l $ROOTFS_DIR/sys
+umount -l $ROOTFS_DIR/dev
+umount -l $ROOTFS_DIR/run
+umount -l $ROOTFS_DIR/tmp
 
 echo "[Create squash.rootfs..]"
-mksquashfs "$ROOTFS_DIR" "$SQUASHFS" &>/dev/null
+run_command mksquashfs "$ROOTFS_DIR" "$SQUASHFS"
+check_exit_code $? "Error during squashfs generation"
 
-if [ $LUKS_ENABLED = "yes" ]; then
+if [ ! -z $LUKS_PASSPHRASE ]; then
   echo "[Encrypt squash.rootfs..]"
   SQUASHFS_SIZE=$(stat -c %s "$SQUASHFS")
   LUKS_HEADER_SIZE=$((1024 * 1024 * 16)) # 16 MiB header LUKS2
   TOTAL_SIZE=$((SQUASHFS_SIZE + LUKS_HEADER_SIZE))
   SECTOR_SIZE=512
   TOTAL_SIZE=$(( (TOTAL_SIZE + SECTOR_SIZE - 1) / SECTOR_SIZE * SECTOR_SIZE ))
-  
-  fallocate -l $TOTAL_SIZE "$ISO_DIR/$LUKS_IMG"
-  
-  echo -n "$LUKS_PASSPHRASE" | cryptsetup luksFormat "$ISO_DIR/$LUKS_IMG" --batch-mode
-  echo -n "$LUKS_PASSPHRASE" | cryptsetup luksOpen "$ISO_DIR/$LUKS_IMG" container
-  dd if="$SQUASHFS" of=/dev/mapper/container bs=4M
-  
+
+  fallocate -l $TOTAL_SIZE "/tmp/$LUKS_IMG"
+  echo -n "$LUKS_PASSPHRASE" | cryptsetup luksFormat "/tmp/$LUKS_IMG" --batch-mode
+  echo -n "$LUKS_PASSPHRASE" | cryptsetup luksOpen "/tmp/$LUKS_IMG" container
+  run_command dd if="$SQUASHFS" of=/dev/mapper/container bs=4M 
   cryptsetup luksClose container
+  
+  if [ ! -z $ADDITIONAL_KEYS ]; then
+    for key in $ADDITIONAL_KEYS; do
+      echo -e "$LUKS_PASSPHRASE\n$key" | cryptsetup luksAddKey "/tmp/$LUKS_IMG"
+    done
+  fi
 else
-  cp "$SQUASHFS" "$ISO_DIR/squash.rootfs"
+  mkdir -p $ISO_DIR/casper
+  cp "$SQUASHFS" "$ISO_DIR/casper/filesystem.squashfs"
 fi
 
+mkdir $OUTPUT
+if [ ! -z $PXE_URL ];then
+  cp /tmp/vmlinuz $OUTPUT
+  cp /tmp/initrd $OUTPUT
+  cp /tmp/$LUKS_IMG $OUTPUT
 
-echo "[Create iso...]"
+  echo "[Moving kernel to iso/boot...]"
+  mkdir -p $BOOT_FOLDER
+  cp /tmp/vmlinuz $BOOT_FOLDER/vmlinuz
+  cp /tmp/initrd $BOOT_FOLDER/initrd
 
-mkdir -p "$ISO_DIR/EFI/BOOT"
-
-cp /opt/limine/BOOTX64.EFI "$ISO_DIR/EFI/BOOT/"
-cp /opt/limine/*.bin "$ISO_DIR/"
-cp /opt/limine/*.sys "$ISO_DIR/"
+  echo "[Create iso...]"
+  
+  mkdir -p "$ISO_DIR/EFI/BOOT"
+  
+  cp /opt/limine/*.EFI "$ISO_DIR/EFI/BOOT/"
+  cp /opt/limine/*.bin "$ISO_DIR/"
+  cp /opt/limine/*.sys "$ISO_DIR/"
+  
+  cp config/00-bootloader/limine_pxe.conf "$ISO_DIR/boot/limine.conf"
+
+  run_command xorriso -as mkisofs -R -r -J -b "limine-bios-cd.bin" \
+          -no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
+          -apm-block-size 2048 --efi-boot "limine-uefi-cd.bin" \
+          -efi-boot-part --efi-boot-image --protective-msdos-label \
+          -volid "NEXUSCLIENTISO" \
+          "$ISO_DIR" -o "$OUTPUT/$ISO_NAME"
+  check_exit_code $? "Error during iso creation"
+  
+  run_command limine bios-install "$OUTPUT/$ISO_NAME"
+  check_exit_code $? "Error during add bios header"
+else
+  echo "[Moving kernel && squashfs from rootfs to iso/boot...]"
+  mkdir -p $BOOT_FOLDER
+  cp /tmp/vmlinuz $BOOT_FOLDER/vmlinuz
+  cp /tmp/initrd $BOOT_FOLDER/initrd
+  cp /tmp/$LUKS_IMG $ISO_DIR/$LUKS_IMG
 
-cp config/00-bootloader/limine.cfg "$ISO_DIR/limine.cfg"
+  echo "[Create iso...]"
+  
+  mkdir -p "$ISO_DIR/EFI/BOOT"
+  
+  cp /opt/limine/*.EFI "$ISO_DIR/EFI/BOOT/"
+  cp /opt/limine/*.bin "$ISO_DIR/"
+  cp /opt/limine/*.sys "$ISO_DIR/"
+  
+  if [ ! -z $LUKS_PASSPHRASE ]; then
+    cp config/00-bootloader/limine.conf "$ISO_DIR/boot/"
+  else
+    cp config/00-bootloader/limine_casper.conf "$ISO_DIR/boot/limine.conf"
+  fi
 
-xorriso -as mkisofs -R -r -J -b "limine-bios-cd.bin" \
-        -no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
-        -apm-block-size 2048 --efi-boot "limine-uefi-cd.bin" \
-        -efi-boot-part --efi-boot-image --protective-msdos-label \
-        -volid "NEXUSCLIENTISO" \
-        "$ISO_DIR" -o image.iso
+  run_command xorriso -as mkisofs -R -r -J -b "limine-bios-cd.bin" \
+          -no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
+          -apm-block-size 2048 --efi-boot "limine-uefi-cd.bin" \
+          -efi-boot-part --efi-boot-image --protective-msdos-label \
+          -volid "NEXUSCLIENTISO" \
+          "$ISO_DIR" -o "$OUTPUT/$ISO_NAME"
+  check_exit_code $? "Error during iso creation"
+  
+  run_command limine bios-install "$OUTPUT/$ISO_NAME"
+  check_exit_code $? "Error during add bios header"
+fi
 
-#limine bios-install image.iso
+chown -R 1000:1000 "$OUTPUT"
diff --git a/live_exam_os/config/00-bootloader/limine.cfg b/live_exam_os/config/00-bootloader/limine.cfg
deleted file mode 100644
index 485a990..0000000
--- a/live_exam_os/config/00-bootloader/limine.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-TIMEOUT=0
-
-:AlpineLinux
-    PROTOCOL=linux
-    KERNEL_PATH=boot:///boot/vmlinuz-5.4.0-26-generic
-    KERNEL_CMDLINE=quiet console=ttyS0
-    MODULE_PATH=boot:///boot/initrd
diff --git a/live_exam_os/config/00-bootloader/limine.conf b/live_exam_os/config/00-bootloader/limine.conf
new file mode 100644
index 0000000..a2004d6
--- /dev/null
+++ b/live_exam_os/config/00-bootloader/limine.conf
@@ -0,0 +1,7 @@
+timeout: 0
+
+/Nexus
+    protocol: linux
+    kernel_path: boot():/boot/vmlinuz
+    kernel_cmdline: boot=nexus quiet splash
+    module_path: boot():/boot/initrd
diff --git a/live_exam_os/config/00-bootloader/limine_casper.conf b/live_exam_os/config/00-bootloader/limine_casper.conf
new file mode 100644
index 0000000..853c8c8
--- /dev/null
+++ b/live_exam_os/config/00-bootloader/limine_casper.conf
@@ -0,0 +1,7 @@
+timeout: 0
+
+/Nexus
+    protocol: linux
+    kernel_path: boot():/boot/vmlinuz
+    kernel_cmdline: boot=casper quiet splash
+    module_path: boot():/boot/initrd
diff --git a/live_exam_os/config/00-bootloader/limine_pxe.conf b/live_exam_os/config/00-bootloader/limine_pxe.conf
new file mode 100644
index 0000000..653cf3a
--- /dev/null
+++ b/live_exam_os/config/00-bootloader/limine_pxe.conf
@@ -0,0 +1,7 @@
+timeout: 0
+
+/Nexus
+    protocol: linux
+    kernel_path: boot():/boot/vmlinuz
+    kernel_cmdline: boot=pxe quiet splash
+    module_path: boot():/boot/initrd
diff --git a/live_exam_os/config/01-initramfs/init b/live_exam_os/config/01-initramfs/init
deleted file mode 100644
index 706064b..0000000
--- a/live_exam_os/config/01-initramfs/init
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-echo "Starting Nexus client..."
-dmesg -n 1
-
-mkdir -p /dev /proc /sys /tmp
-mount -t devtmpfs none /dev
-mount -t proc none /proc
-mount -t sysfs none /sys
-mount -t tmpfs none /tmp
-mkdir -p /dev/pts
-mount -t devpts none /dev/pts
-
-modprobe simpledrm
-modprobe usbcore
-modprobe usb_storage
-modprobe usb_common
-modprobe uas
-modprobe scsi_mod
-modprobe sr_mod
-modprobe sd_mod
-modprobe xhci_pci
-modprobe xhci_hcd
-modprobe ata_piix
-modprobe cdrom
-modprobe loop
-
-/bin/sh
-
-udevadm trigger
-
-echo "Mounting cdrom..."
-while [ -z $(blkid | grep "NEXUSCLIENTISO" | cut -d ':' -f1) ]; do
-  echo -n ""
-done
-
-DISK=$(blkid | grep "NEXUSCLIENTISO" | cut -d ':' -f1)
-mkdir -p /cdrom
-mount -t iso9660 $DISK /cdrom
-
-cryptsetup open /cdrom/squash.rootfs.luks data
-
-echo "Mounting overlay..."
-mkdir -p /squash /upper/lib /work /newroot
-mount -t squashfs /dev/mapper/data /squash
-cp -r /lib/modules /upper/lib
-
-mount -t overlay -o lowerdir=/squash,upperdir=/upper,workdir=/work overlayfs /newroot
-
-mount -t devtmpfs none /newroot/dev
-mount -t proc none /newroot/proc
-mount -t sysfs none /newroot/sys
-mount -t tmpfs none /newroot/tmp
-mount -t devpts none /newroot/dev/pts
-
-exec switch_root /newroot /sbin/init
diff --git a/live_exam_os/config/01-initramfs/init_no_luks b/live_exam_os/config/01-initramfs/init_no_luks
deleted file mode 100644
index 32d7ecb..0000000
--- a/live_exam_os/config/01-initramfs/init_no_luks
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh
-echo "Starting Nexus client..."
-dmesg -n 1
-
-mkdir -p /dev /proc /sys /tmp
-mount -t devtmpfs none /dev
-mount -t proc none /proc
-mount -t sysfs none /sys
-mount -t tmpfs none /tmp
-mkdir -p /dev/pts
-mount -t devpts none /dev/pts
-
-modprobe simpledrm
-modprobe usbcore
-modprobe usb_storage
-modprobe usb_common
-modprobe uas
-modprobe scsi_mod
-modprobe sr_mod
-modprobe sd_mod
-modprobe xhci_pci
-modprobe xhci_hcd
-modprobe ata_piix
-modprobe cdrom
-modprobe loop
-
-udevadm trigger
-
-echo "Mounting cdrom..."
-while [ -z $(blkid | grep "NEXUSCLIENTISO" | cut -d ':' -f1) ]; do
-  echo -n ""
-done
-
-DISK=$(blkid | grep "NEXUSCLIENTISO" | cut -d ':' -f1)
-mkdir -p /cdrom
-mount -t iso9660 $DISK /cdrom
-
-/bin/sh
-
-echo "Mounting overlay..."
-mkdir -p /squash /upper/lib /work /newroot
-mount -t squashfs /cdrom/squash.rootfs /squash
-cp -r /lib/modules /upper/lib
-
-mount -t overlay -o lowerdir=/squash,upperdir=/upper,workdir=/work overlayfs /newroot
-
-mount -t devtmpfs none /newroot/dev
-mount -t proc none /newroot/proc
-mount -t sysfs none /newroot/sys
-mount -t tmpfs none /newroot/tmp
-mount -t devpts none /newroot/dev/pts
-
-exec switch_root /newroot /sbin/init
diff --git a/live_exam_os/config/01-packages_install/packages b/live_exam_os/config/01-packages_install/packages
new file mode 100644
index 0000000..f60d5f3
--- /dev/null
+++ b/live_exam_os/config/01-packages_install/packages
@@ -0,0 +1,21 @@
+udev
+network-manager
+xserver-xorg
+xserver-xorg-input-libinput
+xinit
+xfce4
+xfce4-terminal
+systemd
+policykit-1
+adwaita-icon-theme
+dbus
+dbus-x11
+virt-viewer
+mesa-va-drivers
+iptables
+ufw
+sudo
+vim
+rfkill
+wpasupplicant
+yubikey-personalization
diff --git a/live_exam_os/config/02-customisation/etc/NetworkManager/NetworkManager.conf.bak b/live_exam_os/config/02-customisation/etc/NetworkManager/NetworkManager.conf.bak
new file mode 100644
index 0000000..06c5d59
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/NetworkManager/NetworkManager.conf.bak
@@ -0,0 +1,8 @@
+[main]
+plugins=ifupdown,keyfile
+
+[ifupdown]
+managed=true
+
+[device]
+wifi.scan-rand-mac-address=no
diff --git a/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/10-default-wired.conf.bak b/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/10-default-wired.conf.bak
new file mode 100644
index 0000000..5582524
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/10-default-wired.conf.bak
@@ -0,0 +1,10 @@
+[connection]
+id=Auto Ethernet
+type=ethernet
+autoconnect=true
+
+[ipv4]
+method=auto
+
+[ipv6]
+method=auto
diff --git a/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/10-globally-managed-devices.conf b/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/10-globally-managed-devices.conf
new file mode 100644
index 0000000..e69de29
diff --git a/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/dns.conf.bak b/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/dns.conf.bak
new file mode 100644
index 0000000..d435aba
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/NetworkManager/conf.d/dns.conf.bak
@@ -0,0 +1,2 @@
+[main]
+dns=none
diff --git a/live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example1 b/live_exam_os/config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example1
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example1
rename to live_exam_os/config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example1
diff --git a/live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example2 b/live_exam_os/config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example2
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example2
rename to live_exam_os/config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection.example2
diff --git a/live_exam_os/config/02-customisation/etc/challenge b/live_exam_os/config/02-customisation/etc/challenge
new file mode 100644
index 0000000..9daeafb
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/challenge
@@ -0,0 +1 @@
+test
diff --git a/live_exam_os/config/02-customisation/etc/default/keyboard b/live_exam_os/config/02-customisation/etc/default/keyboard
new file mode 100644
index 0000000..c7fe671
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/default/keyboard
@@ -0,0 +1,10 @@
+# KEYBOARD CONFIGURATION FILE
+
+# Consult the keyboard(5) manual page.
+
+#XKBMODEL="pc105"
+#XKBLAYOUT="ch"
+#XKBVARIANT="fr"
+#XKBOPTIONS=""
+#
+#BACKSPACE="guess"
diff --git a/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/nexus b/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/nexus
new file mode 100755
index 0000000..e1a61da
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/nexus
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -e
+
+. /usr/share/initramfs-tools/hook-functions
+
+copy_exec /etc/initramfs-tools/scripts/init /scripts/nexus
diff --git a/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/pxe b/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/pxe
new file mode 100755
index 0000000..887c32d
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/pxe
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -e
+
+. /usr/share/initramfs-tools/hook-functions
+
+if [ -f /etc/squashfs-url ]; then
+  copy_exec /etc/squashfs-url /squashfs-url
+fi
+copy_exec /etc/initramfs-tools/scripts/pxe /scripts/pxe
diff --git a/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/yubikey b/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/yubikey
new file mode 100755
index 0000000..56bc51d
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/initramfs-tools/hooks/yubikey
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -e
+. /usr/share/initramfs-tools/hook-functions
+
+copy_exec /usr/bin/ykchalresp /bin/ykchalresp
+copy_exec /etc/challenge /scripts/challenge
diff --git a/live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/init b/live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/init
new file mode 100755
index 0000000..337eeb8
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/init
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+mount_and_switch() {
+  SQUASHFS_PATH=$1
+
+  echo "Mounting overlay..."
+  mkdir -p /squash /upper /work /newroot
+  mount -t squashfs $SQUASHFS_PATH /squash
+
+  mount -t overlay -o lowerdir=/squash,upperdir=/upper,workdir=/work overlayfs /newroot
+  
+  mount -t devtmpfs none /newroot/dev
+  mount -t proc none /newroot/proc
+  mount -t sysfs none /newroot/sys
+  mount -t tmpfs none /newroot/tmp
+  mount -t devpts none /newroot/dev/pts
+  
+  exec switch_root /newroot /sbin/init
+}
+
+decrypt_with_passphrase() {
+  cryptsetup open /cdrom/squash.rootfs.luks data
+  exit_code=$?
+  
+  if [ "$exit_code" -eq 0 ]; then
+    mount_and_switch /dev/mapper/data
+  fi
+
+  echo "Wrong passphrase"
+}
+
+decrypt_with_challenge() {
+  echo -n "$1" | cryptsetup open /cdrom/squash.rootfs.luks data
+  exit_code=$?
+
+  if [ "$exit_code" -eq 0 ]; then
+    mount_and_switch /dev/mapper/data
+  fi
+
+  echo "Decryption error, possibly wrong Yubikey"
+}
+
+while [ -z $(blkid | grep "NEXUSCLIENTISO" | cut -d ':' -f1) ]; do
+  echo -n ""
+done
+
+DISK=$(blkid | grep "NEXUSCLIENTISO" | cut -d ':' -f1 | sed 's/.$//')
+mkdir -p /cdrom
+mount -t iso9660 $DISK /cdrom
+
+echo "Waiting for Yubikey. Press 'p' to enter the passphrase"
+while true; do
+  output=$(ykchalresp -2 -i /scripts/challenge 2>&1)
+  exit_code=$?
+  
+  if read -t 1 -n 1 input && [ "$input" = "p" ]; then
+    echo ""
+    decrypt_with_passphrase
+    continue
+  fi
+  
+  if [ "$exit_code" -eq 1 ]; then
+      sleep 1
+      continue
+  fi
+
+  decrypt_with_challenge $output
+done
diff --git a/live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/pxe b/live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/pxe
new file mode 100755
index 0000000..6579225
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/initramfs-tools/scripts/pxe
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+LUKS_FILE="/squash.rootfs"
+
+find_active_interface() {
+    for iface in $(ls /sys/class/net); do
+        if [ "$iface" = "lo" ]; then
+            continue
+        fi
+
+        if [ "$(cat /sys/class/net/$iface/type)" = "1" ]; then
+            if ip link show "$iface" | grep -q "<BROADCAST,MULTICAST>"; then
+                echo "Lookup for $iface interface"
+                dhcpcd -q $iface
+                exit_code=$?
+
+                if [ "$exit_code" -eq 0 ]; then
+                  return 0
+                fi
+            fi
+        fi
+    done
+
+    echo "No active network interface found." >&2
+    /bin/sh
+    return 1
+}
+
+mount_and_switch() {
+  SQUASHFS_PATH=$1
+
+  echo "Mounting overlay..."
+  mkdir -p /squash /upper /work /newroot
+  mount -t squashfs $SQUASHFS_PATH /squash
+
+  mount -t overlay -o lowerdir=/squash,upperdir=/upper,workdir=/work overlayfs /newroot
+  
+  mount -t devtmpfs none /newroot/dev
+  mount -t proc none /newroot/proc
+  mount -t sysfs none /newroot/sys
+  mount -t tmpfs none /newroot/tmp
+  mount -t devpts none /newroot/dev/pts
+  
+  exec switch_root /newroot /sbin/init
+}
+
+decrypt_with_passphrase() {
+  cryptsetup open $LUKS_FILE data
+  exit_code=$?
+  
+  if [ "$exit_code" -eq 0 ]; then
+    mount_and_switch /dev/mapper/data
+  fi
+
+  echo "Wrong passphrase"
+}
+
+decrypt_with_challenge() {
+  echo -n "$1" | cryptsetup open $LUKS_FILE data
+  exit_code=$?
+
+  if [ "$exit_code" -eq 0 ]; then
+    mount_and_switch /dev/mapper/data
+  fi
+
+  echo "Decryption error, possibliy wrong Yubikey"
+}
+
+sleep 3
+
+echo "DHCP lookup..."
+find_active_interface
+
+wget $(cat /squashfs-url) -O $LUKS_FILE
+
+echo "Waiting for Yubikey. Press 'p' to enter the passphrase"
+while true; do
+  output=$(ykchalresp -2 -i /scripts/challenge 2>&1)
+  exit_code=$?
+  
+  if read -t 1 -n 1 input && [ "$input" = "p" ]; then
+    echo ""
+    decrypt_with_passphrase
+    continue
+  fi
+  
+  if [ "$exit_code" -eq 1 ]; then
+      sleep 1
+      continue
+  fi
+  
+  decrypt_with_challenge $output
+done
diff --git a/live_exam_os/config/02-customisation/etc/systemd/system/getty@tty1.service.d/autologin.conf b/live_exam_os/config/02-customisation/etc/systemd/system/getty@tty1.service.d/autologin.conf
new file mode 100644
index 0000000..9712e76
--- /dev/null
+++ b/live_exam_os/config/02-customisation/etc/systemd/system/getty@tty1.service.d/autologin.conf
@@ -0,0 +1,3 @@
+[Service]
+ExecStart=
+ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --autologin user %I $TERM
diff --git a/live_exam_os/config/03-customisation/etc/xdg/autostart/nexus-exam.desktop b/live_exam_os/config/02-customisation/etc/xdg/autostart/nexus-exam.desktop
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/xdg/autostart/nexus-exam.desktop
rename to live_exam_os/config/02-customisation/etc/xdg/autostart/nexus-exam.desktop
diff --git a/live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml b/live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml
rename to live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml
diff --git a/live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml b/live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
rename to live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
diff --git a/live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml b/live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
rename to live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
diff --git a/live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-settings-manager.xml b/live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-settings-manager.xml
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-settings-manager.xml
rename to live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-settings-manager.xml
diff --git a/live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml b/live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml
similarity index 100%
rename from live_exam_os/config/03-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml
rename to live_exam_os/config/02-customisation/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml
diff --git a/live_exam_os/config/02-customisation/home/user/.profile b/live_exam_os/config/02-customisation/home/user/.profile
new file mode 100644
index 0000000..9992ad7
--- /dev/null
+++ b/live_exam_os/config/02-customisation/home/user/.profile
@@ -0,0 +1,5 @@
+while [ ! -e /dev/dri/card* ]; do
+    sleep 1
+done
+
+startx
diff --git a/live_exam_os/config/03-customisation/home/user/.xinitrc b/live_exam_os/config/02-customisation/home/user/.xinitrc
similarity index 100%
rename from live_exam_os/config/03-customisation/home/user/.xinitrc
rename to live_exam_os/config/02-customisation/home/user/.xinitrc
diff --git a/live_exam_os/config/03-customisation/usr/local/bin/nexus-exam.desktop b/live_exam_os/config/02-customisation/usr/local/bin/nexus-exam.desktop
similarity index 100%
rename from live_exam_os/config/03-customisation/usr/local/bin/nexus-exam.desktop
rename to live_exam_os/config/02-customisation/usr/local/bin/nexus-exam.desktop
diff --git a/live_exam_os/config/02-packages_install/packages b/live_exam_os/config/02-packages_install/packages
deleted file mode 100644
index 7d571e7..0000000
--- a/live_exam_os/config/02-packages_install/packages
+++ /dev/null
@@ -1,3 +0,0 @@
-linux-generic
-linux-firmware
-ubuntu-minimal
diff --git a/live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection b/live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection
deleted file mode 100644
index 2cfd7e7..0000000
--- a/live_exam_os/config/03-customisation/etc/NetworkManager/system-connections/wifi.nmconnection
+++ /dev/null
@@ -1,32 +0,0 @@
-# On a Debian/Ubuntu system, NetworkManager's WIFI connection files are located in /etc/NetworkManager/system-connections
-
-[connection]
-# Name of the connection as shown by Network Manager
-id=example1
-# Random UUID referencing the connection
-uuid=8a065b14-beb3-4f28-97b5-f560c368ae12
-type=wifi
-
-[wifi]
-# Whether the SSID is hidden or not (true/false)
-hidden=false
-# Name of the WIFI SSID
-ssid=the_empire_strickes_back
-
-[wifi-security]
-key-mgmt=wpa-eap
-
-[802-1x]
-eap=peap;
-identity=luke_skywalker
-password=you_are_not_ready_young_padawan
-phase2-auth=mschapv2
-
-[ipv4]
-method=auto
-
-[ipv6]
-addr-gen-mode=stable-privacy
-method=auto
-
-[proxy]
diff --git a/live_exam_os/config/03-customisation/etc/default/keyboard b/live_exam_os/config/03-customisation/etc/default/keyboard
deleted file mode 100644
index ad849b1..0000000
--- a/live_exam_os/config/03-customisation/etc/default/keyboard
+++ /dev/null
@@ -1,10 +0,0 @@
-# KEYBOARD CONFIGURATION FILE
-
-# Consult the keyboard(5) manual page.
-
-XKBMODEL="pc105"
-XKBLAYOUT="ch"
-XKBVARIANT="fr"
-XKBOPTIONS=""
-
-BACKSPACE="guess"
diff --git a/live_exam_os/config/03-customisation/etc/inittab b/live_exam_os/config/03-customisation/etc/inittab
deleted file mode 100644
index 37a0b90..0000000
--- a/live_exam_os/config/03-customisation/etc/inittab
+++ /dev/null
@@ -1,17 +0,0 @@
-# /etc/inittab
-
-::sysinit:/sbin/openrc sysinit
-::sysinit:/sbin/openrc boot
-::wait:/sbin/openrc default
-
-# Set up a couple of getty's
-tty1::respawn:/sbin/agetty --autologin user tty1 linux
-
-# Put a getty on the serial port
-#ttyS0::respawn:/sbin/getty -L 115200 ttyS0 vt100
-
-# Stuff to do for the 3-finger salute
-::ctrlaltdel:/sbin/reboot
-
-# Stuff to do before rebooting
-::shutdown:/sbin/openrc shutdown
diff --git a/live_exam_os/config/03-customisation/home/user/.profile b/live_exam_os/config/03-customisation/home/user/.profile
deleted file mode 100644
index a3393c0..0000000
--- a/live_exam_os/config/03-customisation/home/user/.profile
+++ /dev/null
@@ -1 +0,0 @@
-startx
diff --git a/live_exam_os/config/03-post_install/1000-create-user.sh b/live_exam_os/config/03-post_install/1000-create-user.sh
new file mode 100755
index 0000000..d46fd38
--- /dev/null
+++ b/live_exam_os/config/03-post_install/1000-create-user.sh
@@ -0,0 +1,10 @@
+#/bin/bash
+
+. tools/functions.sh
+
+echo " [User managing...]"
+run_command_chroot useradd -m user
+run_command_chroot usermod -aG video user
+run_command_chroot usermod -aG input user
+run_command_chroot usermod -aG plugdev user
+run_command_chroot chown -R 1000:1000 /home/user/
diff --git a/live_exam_os/config/03-post_install/1000-disable_root.sh b/live_exam_os/config/03-post_install/1000-disable_root.sh
new file mode 100755
index 0000000..5187b34
--- /dev/null
+++ b/live_exam_os/config/03-post_install/1000-disable_root.sh
@@ -0,0 +1,6 @@
+#/bin/sh
+
+. tools/functions.sh
+
+echo " [Disable root user...]"
+run_command_chroot passwd -l root
diff --git a/live_exam_os/config/03-post_install/2000-enable_services.sh b/live_exam_os/config/03-post_install/2000-enable_services.sh
new file mode 100755
index 0000000..a596813
--- /dev/null
+++ b/live_exam_os/config/03-post_install/2000-enable_services.sh
@@ -0,0 +1,7 @@
+#/bin/sh
+
+. tools/functions.sh
+
+echo " [Enabling services...]"
+run_command_chroot systemctl enable NetworkManager
+run_command_chroot systemctl enable ufw
diff --git a/live_exam_os/config/03-post_install/3000-nexus_exam.sh b/live_exam_os/config/03-post_install/3000-nexus_exam.sh
new file mode 100755
index 0000000..5d80457
--- /dev/null
+++ b/live_exam_os/config/03-post_install/3000-nexus_exam.sh
@@ -0,0 +1,17 @@
+#/bin/bash
+
+. tools/functions.sh
+
+echo " [Compiling nexus-exam...]"
+cd ..
+run_command make build_nexus-exam SERVER=$SERVER CERT=$CERT EXAM_USER=$EXAM_USER EXAM_PWD=$EXAM_PWD
+check_exit_code $? "Error during nexus-exam compilation"
+if [[ "$ROOTFS_DIR" != /* ]]; then
+  mkdir -p live_exam_os/$ROOTFS_DIR/usr/local/bin
+  cp build/nexus-exam live_exam_os/$ROOTFS_DIR/usr/local/bin/nexus-exam
+else
+  mkdir -p $ROOTFS_DIR/usr/local/bin
+  cp build/nexus-exam $ROOTFS_DIR/usr/local/bin/nexus-exam
+fi
+make clean_client
+cd -
diff --git a/live_exam_os/config/03-post_install/4000-firewall.sh b/live_exam_os/config/03-post_install/4000-firewall.sh
new file mode 100755
index 0000000..f56281a
--- /dev/null
+++ b/live_exam_os/config/03-post_install/4000-firewall.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+. tools/functions.sh
+
+IP_SERVER=$(echo $SERVER | cut -d ':' -f1)
+PORT_SERVER=$(echo $SERVER | cut -d ':' -f2)
+
+echo " [Firewall configuration...]"
+
+run_command_chroot ufw default deny incoming
+run_command_chroot ufw default deny outgoing
+run_command_chroot ufw allow out from any to $IP_SERVER port $PORT_SERVER proto tcp
+run_command_chroot ufw allow out from any to any port 123 proto udp
+run_command_chroot ufw allow out from any to any port 53 proto udp
+run_command_chroot ufw allow out from any to $IP_SERVER port 1025:65535 proto tcp
+run_command_chroot ufw enable
diff --git a/live_exam_os/config/03-post_install/5000-pxe.sh b/live_exam_os/config/03-post_install/5000-pxe.sh
new file mode 100755
index 0000000..ecf5afd
--- /dev/null
+++ b/live_exam_os/config/03-post_install/5000-pxe.sh
@@ -0,0 +1,8 @@
+#/bin/bash
+
+. tools/functions.sh
+
+if [ ! -z $PXE_URL ]; then
+  echo " [Adding PXE url...]"
+  echo -n "$PXE_URL/$LUKS_IMG" > $ROOTFS_DIR/etc/squashfs-url
+fi
diff --git a/live_exam_os/config/03-post_install/9999-initramfs.sh b/live_exam_os/config/03-post_install/9999-initramfs.sh
new file mode 100755
index 0000000..a7d37d5
--- /dev/null
+++ b/live_exam_os/config/03-post_install/9999-initramfs.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+. tools/functions.sh
+
+echo " [Update initramfs...]"
+run_command_chroot update-initramfs -u
+check_exit_code $? "Error during initramfs generation"
diff --git a/live_exam_os/config/04-post_install/1000-create-user.sh b/live_exam_os/config/04-post_install/1000-create-user.sh
deleted file mode 100755
index 8fa722d..0000000
--- a/live_exam_os/config/04-post_install/1000-create-user.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#/bin/sh
-
-run() {
-  chroot "$ROOTFS_DIR" $@
-}
-
-echo "[User managing...]"
-run useradd -m user
-run usermod -aG video user
-run usermod -aG input user
-run usermod -aG plugdev user
-run usermod -aG wheel user
-chown -R 1000:1000 $ROOTFS_DIR/home/user/
-USER_PASSWORD="0"
-echo "user:$USER_PASSWORD" | chroot "$ROOTFS_DIR" /usr/sbin/chpasswd
-echo "%wheel ALL=(ALL:ALL) ALL" >> "$ROOTFS_DIR/etc/sudoers.d/wheel"
diff --git a/live_exam_os/config/04-post_install/1000-disable_root.sh b/live_exam_os/config/04-post_install/1000-disable_root.sh
deleted file mode 100755
index 24518d1..0000000
--- a/live_exam_os/config/04-post_install/1000-disable_root.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#/bin/sh
-
-run() {
-  chroot "$ROOTFS_DIR" $@
-}
-
-echo "[Disable root user...]"
-run passwd -l root
diff --git a/live_exam_os/config/04-post_install/2000-enable_services.sh b/live_exam_os/config/04-post_install/2000-enable_services.sh
deleted file mode 100755
index 7c05faa..0000000
--- a/live_exam_os/config/04-post_install/2000-enable_services.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#/bin/sh
-
-run() {
-  chroot "$ROOTFS_DIR" $@
-}
-
-echo "[Enabling services...]"
-run rc-update add dbus
-run setup-devd udev
-run rc-update add polkit
-run rc-update add elogind
-run rc-update add networkmanager
-run rc-update add ufw
diff --git a/live_exam_os/config/04-post_install/9999-firewall.sh b/live_exam_os/config/04-post_install/9999-firewall.sh
deleted file mode 100755
index ead64fa..0000000
--- a/live_exam_os/config/04-post_install/9999-firewall.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-IP_SERVER=$(echo $SERVER | cut -d ':' -f1)
-PORT_SERVER=$(echo $SERVER | cut -d ':' -f2)
-
-run() {
-  chroot "$ROOTFS_DIR" $@
-}
-
-echo "[Firewall configuration...]"
-
-run ufw default deny incoming
-run ufw default deny outgoing
-run ufw allow out from any to $IP_SERVER port $PORT_SERVER proto tcp
-run ufw allow out from any to any port 123 proto udp
-run ufw allow out from any to any port 53 proto udp
-run ufw allow out from any to $IP_SERVER port 1025:65535 proto tcp
-run ufw enable
diff --git a/live_exam_os/tools/functions.sh b/live_exam_os/tools/functions.sh
new file mode 100755
index 0000000..ad9b113
--- /dev/null
+++ b/live_exam_os/tools/functions.sh
@@ -0,0 +1,39 @@
+run() {
+  chroot "$ROOTFS_DIR" $@
+}
+
+run_command() {
+  local cmd="$@"
+  if $VERBOSE; then
+      echo $cmd
+      bash -c "$cmd"
+      EXIT_CODE=$?
+  else
+      bash -c "$cmd" > /dev/null 2>&1
+      EXIT_CODE=$?
+  fi
+  return $EXIT_CODE
+}
+
+run_command_chroot() {
+  run_command chroot "$ROOTFS_DIR" $@
+}
+
+check_exit_code() {
+  EXIT_CODE=$1
+  if [ ! $EXIT_CODE -eq 0 ]; then
+    echo $2
+    exit
+  fi
+}
+
+check_environment_var() {
+  if [ -z $SERVER ] || [ -z $CERT ] || [ -z $EXAM_USER ] || [ -z $EXAM_PWD ]; then
+    echo "Error: Environment variables aren't set"
+    echo "SERVER = $SERVER"
+    echo "CERT = $CERT"
+    echo "EXAM_USER = $EXAM_USER"
+    echo "EXAM_PWD = $EXAM_PWD"
+    helper
+  fi
+}
-- 
GitLab