Installing LMDE 7 (Gigi) with full disk encryption using RAID1 (mdadm), LUKS2, LVM2, UKI, systemd-boot, and USB unlock

Semyon A Mironov

by Semyon A Mironov, 03.10.2025

This document describes the creation of the following scheme

Disk marking scheme


Table of Contents


Installer: Welcome


  1. Getting the current LMDE ISO image
    1. Open the official Linux Mint project website: https://linuxmint.com

    2. Navigate to the download page for the current/latest LMDE image

    3. Click the download button

    4. Select the Linux Mint repository mirror closest to your location and click the link to begin the ISO file download

    5. Write the downloaded image to a USB drive:

  2. Clearing secure boot keys

    For security reasons, remove the existing certificates from the UEFI firmware to add your own certificates during the operating system installation.

  3. Booting from a LIVE-ISO

    To properly install the proprietary video driver, before booting the LMDE 7 Live image, disable the kernel-integrated video driver using the command line parameter for your video card:

    nomodeset module_blacklist=amdgpu  # Modern AMD GPUs (GCN 1.0 architecture and newer)
    nomodeset module_blacklist=i915    # Integrated Intel graphics (HD Graphics, Iris Xe, etc.)
    nomodeset module_blacklist=nouveau # Most NVIDIA GPUs (GeForce, etc.)
    nomodeset module_blacklist=radeon  # Older/Legacy AMD/ATI GPUs (pre-GCN)

    The kernel’s command-line parameters Description
    quiet [KNL,EARLY] Disable most log messages
    splash Load a splash image for XNU
    nomodeset Disable kernel modesetting. Most systems' firmware sets up a display mode and provides framebuffer memory for output. With nomodeset, DRM and fbdev drivers will not load if they could possibly displace the pre-initialized output. Only the system framebuffer will be available for use. The respective drivers will not perform display-mode changes or accelerated rendering.
    Useful as error fallback, or for testing and debugging.
    module_blacklist [KNL] Do not load a comma-separated list of modules. Useful for debugging problem modules.
  4. Preparing a LIVE system

    Further in this guide, a software RAID array with LVM2 will be created. In the future, to identify the host on which they were created, it is necessary to set the correct hostname and current date to save them in the disk subsystem metadata.

    1. Changing the host name
      1. Open the terminal:

        Open the terminal

        terminal

      2. Switch to the root user:

        sudo --shell
      3. Save the domain name in a variable:

        export DOMAIN_NAME="mgmsam.pro"

        DOMAIN_NAME variable is required later for creating Secure Boot keys for UEFI.

      4. Save the new hostname in a variable:

        export HOST_NAME="ws.$DOMAIN_NAME"
      5. Change the host name:

        hostname "$HOST_NAME"
      6. Check the host name:

        hostname --fqdn

        Change the host name

      Additional commands

      To display the new fqdn (fully qualified domain name) in the terminal

      1. Edit the PS1 variable:

        sed --in-place '/^[[:blank:]]*PS1=/ s%\\h%\\H%' /home/mint/.bashrc
      2. Switch to the root user again:

        exit
        sudo --shell
      3. Include the new .bashrc:

        . /home/mint/.bashrc
      4. Resave the domain name and new hostname in a variable:

        export DOMAIN_NAME="mgmsam.pro"
        export HOST_NAME="ws.$DOMAIN_NAME"

        Show FQDN

    2. Setting up time in a LIVE system
      1. Set the timezone:

        dpkg-reconfigure tzdata
      2. Syncing the time:

        service systemd-timesyncd restart

  5. Preparing the disks
    1. Creating partitions
      1. List information about block devices:

        lsblk

        List information about block devices

      2. Save the disk names in variables:

        export SDA="/dev/sda"
        export SDB="/dev/sdb"
      3. Create two partitions on SDA for ESP and mirror array:

        1. Run the fdisk program for the SDA disk:

          fdisk "$SDA"
        2. Create partitions on the disk by following the following list of commands:

               m # print help
               p # print the partition table
               g # create a new empty GPT partition table
               n # add a new partition No.1
               1 # partition number
                 # first sector (2048)
             +1G # last sector
               p # print the partition table
               n # add a new partition No.2
               2 # partition number
                 # first sector (206848)
                 # last sector
               p # print the partition table
               l # list known partition types
               q # quit from list known partition types
               t # change a partition type No.1
               1 # partition number
               1 # EFI System
               t # change a partition type No.2
               2 # partition number
              42 # Linux RAID
               p # print the partition table
               x # extra functionality (experts only)
               m # print help (for GPT)
               n # change partition name No.1
               1 # partition number
            ESP1 # new name No.1
               n # change partition name No.2
               2 # partition number
           RAID1 # new name No.2
               p # print the partition table
               r # return to main menu
               p # print the partition table
               w # write table to disk and exit

          List information about sda devices

      4. Create two partitions on SDB for ESP and the mirror array:

        cat <<FDISK | fdisk "$SDB"
            g # create a new empty GPT partition table
            n # add a new partition No.1
            1
        
          +1G
            p # print the partition table
            n # add a new partition No.2
            2
        
        
            p # print the partition table
            t # change a partition type No.1
            1
            1
            t # change a partition type No.2
            2
           42
            p # print the partition table
            x # extra functionality (experts only)
            n # change partition name No.1
            1
         ESP2
            n # change partition name No.2
            2
        RAID1
            p # print the partition table
            r # return to main menu
            p # print the partition table
            w # write table to disk and exit
        FDISK

        Comments are allowed only when calling commands. Spaces at the beginning and end of commands and values are ignored.

        List information about sdb devices

    2. Creating a mirror array with MDADM

      MDADM - Multiple Disk and Device Management

      1. Save the name of the RAID array in a variable:

        export RAID_DEVICE="/dev/md0"
      2. Create an array:

        mdadm --verbose --create "$RAID_DEVICE" --level 1 --raid-devices 2 "${SDA}2" "${SDB}2"
      3. Check the RAID array status:

        cat /proc/mdstat

        MDADM Create an array

        MDADM lsblk

      Additional commands

      Show help

      mdadm --help

      Display details of an array

      mdadm --verbose --detail --scan | grep '^ARRAY'

      Save the array configuration

      nano /etc/mdadm/mdadm.conf

      Stop the array

      mdadm --verbose --stop /dev/md0

      Assemble a previously created array

      mdadm --verbose --assemble --scan

      Hotadd subsequent devices to the array

      mdadm --verbose /dev/md0 --add /dev/sdc2

      Subsequent devices are re-added

      mdadm --verbose /dev/md0 --re-add /dev/sde2

      Delete super-blocks on the disks from which the array is assembled

      mdadm --verbose --zero-superblock /dev/sda2 /dev/sde2
    3. Encryption with LUKS2

      LUKS - Linux Unified Key Setup

      I need to encrypt a RAID array (mdadm), but the installer uses filesystem encryption only for LVM:

      Installer: Encrypt the operating system

      1. Save LUKS device in variable:

        export LUKS_DEVICE="${RAID_DEVICE:-/dev/md0}"
      2. Fill the disk with random data (optional):

        Please be patient, this can take hours...

        badblocks -c 10240 -s -w -t random -v "$LUKS_DEVICE"

        This terminal command does the same thing as the installer:

        Installer: Fill the disk with random data

      3. Encrypt the partition:

        cryptsetup --verbose luksFormat --type luks2 --hash sha512 --key-size 512 "$LUKS_DEVICE"

        Default options for luks1 and luks2:

        Option LUKS1 LUKS2
        --pbkdf pbkdf2 argon2id
        --key-size 256 256
        --hash sha256 sha256
        --cipher aes-cbc-essiv aes-xts-plain64
        --iter-time 2000ms 2000ms

        Where options mean the following:

        Option Description
        --verbose Shows more detailed error messages.
        luksFormat Formats a LUKS device.
        --pbkdf=STRING PBKDF algorithm.
        --key-size=BITS The size of the encryption key.
        --hash=STRING The hash used to create the encryption key from the passphrase.
        --cipher=STRING The cipher used to encrypt the disk.
        --iter-time=msecs PBKDF iteration time for LUKS (in ms).
      4. Save LUKS name in variable:

        export LUKS_NAME="lvmlmde"

        lvmlmde: Is the default name when using the installer, you can specify something else.

      5. Open the LUKS partition:

        cryptsetup --verbose luksOpen "$LUKS_DEVICE" "$LUKS_NAME"

        LUKS

        LUKS lsblk

      Additional commands

      Show help

      cryptsetup --help

      Close LUKS device (remove mapping)

      cryptsetup close /dev/mapper/lvmlmde

      Show LUKS device status

      cryptsetup status /dev/mapper/lvmlmde

      Dump LUKS partition information

      cryptsetup luksDump /dev/md0

      Add key to LUKS device

      cryptsetup luksAddKey /dev/md0 [<new key file>]

      Changes supplied key or key file of LUKS device

      cryptsetup luksChangeKey /dev/md0 <key slot>

      Removes supplied key or key file from LUKS device

      cryptsetup luksRemoveKey /dev/md0 [<new key file>]

      Wipes key with number <key slot> from LUKS device

      cryptsetup luksKillSlot /dev/md0 <key slot>
    4. Setup LVM

      LVM - Logical volume manager

      1. Initializing LVM
        1. Save the device name in variable:

          LVM_PHYSICAL_VOLUME="/dev/mapper/lvmlmde"
        2. Initialize physical volume:

          pvcreate --verbose "$LVM_PHYSICAL_VOLUME"

          Display various attributes of physical volume(s)

          pvdisplay

          or display information about physical volumes

          pvs

          LVM pvcreate

      2. Creating a volume group
        1. Save the volume group name in a variable:

          export LVM_VOLUME_GROUP="lvmlmde"

          lvmlmde: Is the default volume group name when using the installer, you can specify something else.

        2. Create a volume group:

          vgcreate --verbose "$LVM_VOLUME_GROUP" "$LVM_PHYSICAL_VOLUME"

          Display volume group information

          vgdisplay

          or display information about volume groups

          vgs

          LVM vgcreate

      3. Creating the logical volume
        1. Create the root logical volume:

          lvcreate --verbose --name root --size 50G "$LVM_VOLUME_GROUP"
        2. Create the home logical volume:

          lvcreate --verbose --name home --size 50G "$LVM_VOLUME_GROUP"

          Display information about a logical volume

          lvdisplay

          or display information about logical volumes

          lvs

          LVM lvcreate

          LVM lsblk

      Additional commands

      Deactivation/activation LVM

      1. Deactivating Volume Groups:

        vgchange --verbose --activate n lvmlmde
      2. Activating Volume Groups:

        vgchange --verbose --activate y lvmlmde

      Rename LVM

      1. Rename a logical volume:

        lvrename --verbose lvmlmde root linux

        or

        lvrename --verbose /dev/lvmlmde/root linux
      2. Rename a volume group:

        vgrename --verbose lvmlmde sys

      Remove LVM

      1. Remove logical volume(s):

        lvremove --verbose /dev/lvmlmde/root
        lvremove --verbose /dev/lvmlmde/home

        or remove all logical volumes in the volume group

        lvremove --verbose lvmlmde
      2. Remove volume group(s):

        vgremove --verbose lvmlmde
      3. Remove LVM label(s) from physical volume(s):

        pvremove --verbose /dev/mapper/lvmlmde
    5. Formatting partitions
      1. Format the ESP:

        mkfs.fat -v -F 32 -n ESP1 "${SDA}1"
        mkfs.fat -v -F 32 -n ESP2 "${SDB}1"

        mkfs ESP

      2. Format the root partition:

        mkfs.xfs -L root "/dev/mapper/$LVM_VOLUME_GROUP-root"

        mkfs root

      3. Format the home partition:

        mkfs.xfs -L home "/dev/mapper/$LVM_VOLUME_GROUP-home"

        mkfs home

      Additional commands

      Remove a file system

      dd if=/dev/zero of=/dev/sda1 bs=2048 count=1 conv=notrunc
  6. Installing the system
    1. Mounting ISO image
      1. Create a directory for mounting ISO image:

        mkdir --verbose /source
      2. Mount the ISO image:

        mount --verbose --options loop --types squashfs /run/live/medium/live/filesystem.squashfs /source

        mount source

    2. Mounting /target
      1. Create the root mount directory:

        mkdir --verbose /target
      2. Mount the root partition:

        mount --verbose "/dev/mapper/$LVM_VOLUME_GROUP-root" /target

        mount root

      3. Create a directory to mount the home partition:

        mkdir --verbose /target/home
      4. Mount the home partition:

        mount --verbose "/dev/mapper/$LVM_VOLUME_GROUP-home" /target/home

        mount home

      5. Create a directory to mount the ESP:

        mkdir --verbose --parents /target/boot/efi
      6. Mount the ESP:

        mount --verbose --options umask=0077 "${SDA}1" /target/boot/efi

        mount ESP

    3. Transferring the files
      1. Copy the operating system files from the ISO image to the root partition:

        EXCLUDE_DIRS="home/* dev/* proc/* sys/* tmp/* run/* mnt/* media/* lost+found source target"
        set -f
        RSYNC_FILTER=
        for d in $EXCLUDE_DIRS
        do
            RSYNC_FILTER="${RSYNC_FILTER:-} --exclude=/$d"
        done
        set +f

        RSYNC_FILTER="--exclude=/home/* --exclude=/dev/* --exclude=/proc/* ..."

        rsync vars

        rsync --verbose --archive --no-D --acls --hard-links --xattrs $RSYNC_FILTER /source/* /target/

        Description of rsync options:

        Option Description
        --verbose Increase verbosity.
        --archive Archive mode is -rlptgoD (no -A,-X,-U,-N,-H).
        --recursive, -r Recurse into directories.
        --links, -l Copy symlinks as symlinks.
        --perms, -p Preserve permissions.
        --times, -t Preserve modification times.
        --group, -g Preserve group.
        --owner, -o Preserve owner (super-user only).
        -D Same as --devices --specials.
        --devices Preserve device files (super-user only).
        --specials Preserve special files.
        --no-* Turn off an implied OPTION.
        --acls Preserve ACLs (implies --perms).
        --hard-links Preserve hard links.
        --xattrs Preserve extended attributes.
        --exclude Exclude files matching PATTERN.

        rsync start

        rsync end

        Additional commands

        To set the current date on the operating system files:

        rsync --verbose --recursive --links --perms --group --owner --acls --hard-links --xattrs \
            $RSYNC_FILTER \
            /source/* \
            /target/
        rsync --verbose --perms --group --owner --acls --hard-links --xattrs --times \
            /source/var/lib/apt/lists/*Release \
            /target/var/lib/apt/lists/

        rsync expert

      2. Copy the local domain name system configuration file:

        mv --verbose --force /target/etc/resolv.conf /target/etc/resolv.conf.bk
        cp --verbose --force /etc/resolv.conf /target/etc/resolv.conf
      3. Unmount ISO image:

        umount --verbose /source

        umount source

  7. Configuring the system
    1. Entering the system
      1. Mount essential system directories:

        mkdir --verbose --parents /target/sys/firmware/efi/efivars
        for FS in /dev /dev/shm /dev/pts /proc /run /sys /sys/firmware/efi/efivars
        do
            mount --verbose --bind "$FS" "/target$FS"
        done

        Description of mounted directories:

        Directory Description
        /dev Devices and special files.
        /dev/shm Overview of POSIX shared memory.
        /dev/pts Pseudoterminal master and slave.
        /proc Kernel and process information virtual filesystem.
        /run Run-time variable data.
        /sys Kernel and system information virtual filesystem.
        /sys/firmware/efi/efivars efivarfs - a (U)EFI variable filesystem.
      2. Chroot:

        chroot /target

        chroot

        Additional commands

        To display the new fqdn (fully qualified domain name) in the terminal:

        1. Editing the PS1 variable:

          sed --in-place '
             /[[:blank:]]*PS1=/ {
                s%\\h%\\u@\\H%
                s%^\([[:blank:]]*\)#[#[:blank:]]*\([^[:blank:]#]\)%\1\2%
             }
          ' /root/.bashrc
        2. Exec to the chroot user again:

          exit
          chroot /target

          Show chroot FQDN

    2. Removing packages
      1. Remove LIVE packages and their system-wide configuration files:

        apt purge live-config* live-installer* live-boot* live-tools*

        Removing live configuration

      2. Remove LIVE leftovers:

        rm --verbose --force --recursive \
            /etc/live \
            /lib/live \
            /etc/casper* \
            /lib/casper \
            /usr/lib/casper \
            /usr/share/casper \
            /usr/share/applications/debian-installer-launcher.desktop
      3. Remove all packages related to the grub boot loader:

        apt purge grub-*
      4. Remove grub leftovers:

        rm --verbose --force --recursive /boot/grub /etc/default/grub.d /etc/grub.d

    3. Setting the timezone

      Installer: timezone

      dpkg-reconfigure tzdata

    4. Setting the locale

      Installer: language

      1. Reconfigure the system's locale settings:

        dpkg-reconfigure locales

      2. Add system locale variables:

        cat <<LOCALE > /etc/default/locale
        #  File generated by update-locale
        LC_CTYPE="en_US.UTF-8"
        LC_ALL="en_US.UTF-8"
        LANG="en_US.UTF-8"
        LANGUAGE="en_US:en"
        LOCALE
    5. Configuring keyboard

      Installer: keyboard layout

      dpkg-reconfigure keyboard-configuration

    6. Setting up users
      1. Lock and delete root password:

        passwd --delete --lock root

        Set a password for logging in to the system as root

        WARNING: For experts only !

        passwd root
      2. Add a new user:

        1. Set variables for use in subsequent commands:

          USER_NAME="sam"
          REAL_NAME="Semyon A Mironov"
          USER_GROUPS="adm,audio,bluetooth,cdrom,dialout,dip,fax,floppy,lpadmin,netdev,plugdev,scanner,sudo,tape,users,video"

          The group list is obtained from the operating system installed by the installer:

          User and groups

        2. Create a user:

          Choose to Create a user with home directory encryption or Create a user without encryption

          • Create a user with home directory encryption:

            Installer: Create a user with home directory encryption

            1. Create a user:

              adduser --disabled-password --encrypt-home --logmsglevel info --shell /bin/bash \
                  ${REAL_NAME:+--comment "$REAL_NAME"} \
                  "$USER_NAME"
            2. Add a user to groups:

              usermod --append --groups "$USER_GROUPS" "$USER_NAME"
            3. Enable termination of user processes after logout:

              sed --in-place 's%^#\+\(KillUserProcesses\)=.*$%\1=yes%' /etc/systemd/logind.conf

              useradd

              Additional commands

              If you need to delete a user:

              perl /usr/sbin/deluser "$USER_NAME"
          • Create a user without encryption:

            Installer: Create a user without encryption

            useradd --create-home --groups "$USER_GROUPS" --shell /bin/bash \
                ${REAL_NAME:+--comment "$REAL_NAME"} \
                "$USER_NAME"

            useradd

            Additional commands

            If you need to delete a user:

            deluser --remove-home "$USER_NAME"
        3. Set user password:

          passwd "$USER_NAME"
        4. Set LightDM to show user list by default:

          If this step is not performed, the user list will be hidden:

          sed --in-place '
              s%^#\?\(greeter-hide-users\)[[:blank:]]*=.*%\1=false%
          ' /etc/lightdm/lightdm.conf
        5. Set autologin (optional):

          Installer: User: Log in automatically

          This parameter is ignored for the root user and for users with an encrypted home directory.

          sed --in-place "
              s%^#\?\(autologin-user\)[[:blank:]]*=.*%\1=$USER_NAME%
          " /etc/lightdm/lightdm.conf
        6. Enable manual username entry in the login window:

          This step must be completed if you set a password for the root user and wish to be able to log in to the system using that account.

          sed --in-place '
              s%^#\?\(greeter-show-manual-login\)[[:blank:]]*=.*%\1=true%
          ' /etc/lightdm/lightdm.conf
    7. Writing hostname

      Installer: Your computer's name:

      1. Edit the /etc/hostname file:

        echo "$HOST_NAME" > /etc/hostname
      2. Check the /etc/hostname file:

        cat /etc/hostname
      3. Editing the /etc/hosts file:

        Save a text file that contains a database of domain names and is used when translating them to network host addresses.

        cat <<HOSTS > /etc/hosts
        127.0.0.1   localhost
        127.0.1.1   $HOST_NAME
        # The following lines are desirable for IPv6 capable hosts
        ::1     localhost ip6-localhost ip6-loopback
        fe00::0 ip6-localnet
        ff00::0 ip6-mcastprefix
        ff02::1 ip6-allnodes
        ff02::2 ip6-allrouters
        ff02::3 ip6-allhosts
        HOSTS
      4. Check the /etc/hosts file:

        cat /etc/hosts

        hostname

    8. Configuring MDADM
      1. Generate a new /etc/mdadm/mdadm.conf file:

        bash /usr/share/mdadm/mkconf force-generate
      2. Save the RAID configuration:

        RAID_ARRAY="$(mdadm --verbose --detail --scan | grep '^ARRAY')"
      3. Check the RAID_ARRAY variable:

        echo "$RAID_ARRAY"
      4. Update the RAID configuration:

        sed --in-place "s|^ARRAY.*$|$RAID_ARRAY|" /etc/mdadm/mdadm.conf

        MDADM update config

      5. Check the /etc/mdadm/mdadm.conf file:

        cat /etc/mdadm/mdadm.conf

        MDADM updated config

    9. Configuring LUKS

      Follow the steps in this section if you followed the steps described in the Encryption with LUKS2 section.

      Choose to Configuring LUKS with password unlock or Configuring LUKS with password and USB unlock

      • Configuring LUKS with password unlock
        1. Get UUID of LUKS device:

          LUKS_UUID="$(cryptsetup luksUUID "$LUKS_DEVICE")"
        2. Check LUKS UUID variable:

          echo "LUKS_UUID: $LUKS_UUID"
        3. Save configuration for encrypted block devices:

          cat <<CRYPTTAB > /etc/crypttab
          # <target name> <source device>                           <key file> <options>
          $LUKS_NAME         UUID=$LUKS_UUID none       luks,discard,tries=3
          CRYPTTAB
        4. Check /etc/crypttab file:

          cat /etc/crypttab

          LUKS crypttab

      • Configuring LUKS with password and USB unlock

        Source: https://github.com/mgmsam/decrypt_keyfile

        1. Insert the USB drive into the host and define it in the lsblk output:

          lsblk USB drive

        2. Set variables for use in subsequent commands:

          USB="/dev/sdc"           # The USB drive from the `lsblk` output
          USB_MOUNT="/mnt"         # Specify an existing empty directory for connecting the USB drive
          USB_KEY="$HOST_NAME.lek" # The name of the key file to create on the USB drive. (*.lek - LUKS Encryption Key)
        3. Check USB variables:

          echo "      USB: $USB"
          echo "USB_MOUNT: $USB_MOUNT"
          echo "  USB_KEY: $USB_KEY"

          USB vars

        4. Create partitions on USB drive:

          cat <<FDISK | fdisk "$USB"
               g # create a new empty GPT partition table
               n # add a new partition No.1
               1
          
           +100M
               p # print the partition table
               n # add a new partition No.2
               2
          
          
               p # print the partition table
               t # change a partition type No.1
               1
               1
               p # print the partition table
               x # extra functionality (experts only)
               n # change partition name No.1
               1
          EFIUSB
               p # print the partition table
               n # change partition name No.2
               2
             USB
               p # print the partition table
               r # return to main menu
               p # print the partition table
               w # write table to disk and exit
          FDISK

          USB fdisk lsblk

        5. Format the EFIUSB partition:

          mkfs.fat -v -F 32 -n EFIUSB "${USB}1"
        6. Format the USB partition:

          mkfs.exfat --volume-label USB "${USB}2"
        7. Mount the EFIUSB partition:

          mount --verbose "${USB}1" "$USB_MOUNT"

          mount USB lsblk

        8. Create a 512-byte key file with random data:

          dd if=/dev/urandom of="$USB_MOUNT/$USB_KEY" bs=1 count=512 status=progress

          The contents of the key file can be anything, for example, a photo

        9. Add key to LUKS device:

          cryptsetup --verbose luksAddKey "$LUKS_DEVICE" "$USB_MOUNT/$USB_KEY"

          LUKS2 create key

        10. Save script:

          wget --directory-prefix "/usr/lib/cryptsetup/scripts" \
              https://raw.githubusercontent.com/mgmsam/decrypt_keyfile/refs/heads/main/decrypt_keyfile
        11. Make the script executable:

          chmod --verbose u+rwx,go+rx "/usr/lib/cryptsetup/scripts/decrypt_keyfile"

          LUKS2 get script

        12. Check script:

          cat "/usr/lib/cryptsetup/scripts/decrypt_keyfile"
        13. Get UUID of LUKS device:

          LUKS_UUID="$(cryptsetup luksUUID "$LUKS_DEVICE")"
        14. Get UUID of USB device:

          USB_UUID="$(blkid --match-tag UUID --output value "${USB}1")"
        15. Check UUIDs variables:

          echo "LUKS_UUID: $LUKS_UUID"
          echo " USB_UUID: $USB_UUID"
        16. Save configuration for encrypted block devices:

          cat <<CRYPTTAB > /etc/crypttab
          # <target name> <source device>                           <key file>                           <options>
          $LUKS_NAME         UUID=$LUKS_UUID UUID=$USB_UUID:/$USB_KEY:10 luks,discard,tries=3,keyscript=decrypt_keyfile
          CRYPTTAB
        17. Check the /etc/crypttab file:

          cat /etc/crypttab

          LUKS2 crypttab whith USB script

        18. Unmount the EFIUSB partition:

          umount --verbose "${USB}1"
    10. Creating swap
      1. Set the swap file path and size:

        SWAP_FILE="/swapfile"
        # Specify the swap file size in mebibytes: 16384 - 16Gb
        SWAP_SIZE="16384M"
        # or use a swap file equal to the amount of RAM
        #SWAP_SIZE="$(cat /proc/meminfo | awk '/MemTotal/ {print $2}')K"
      2. Create the swap file:

        fallocate --verbose --length "$SWAP_SIZE" "$SWAP_FILE"
      3. Set the file permissions:

        chmod --verbose 600 "$SWAP_FILE"
      4. Initialize the file as a swap file:

        mkswap --verbose "$SWAP_FILE"
      5. Configure kernel parameters for swap:

        cat <<SWAP.CONF > /etc/sysctl.d/swap.conf
        vm.swappiness=60
        vm.vfs_cache_pressure=100
        SWAP.CONF

        The specified options have default values

        Where options mean the following:

        Option Description
        vm.swappiness
        vm.vfs_cache_pressure
        https://docs.kernel.org/admin-guide/sysctl/vm.html.

        Creating swap

    11. Writing fstab
      1. Get UUID of the system partitions:

        ESP1_UUID="$(blkid --match-tag UUID --output value "${SDA}1")"
        ROOT_UUID="$(blkid --match-tag UUID --output value "/dev/mapper/$LVM_VOLUME_GROUP-root")"
        HOME_UUID="$(blkid --match-tag UUID --output value "/dev/mapper/$LVM_VOLUME_GROUP-home")"
      2. Check UUIDs variables:

        echo "ESP1_UUID: $ESP1_UUID"
        echo "ROOT_UUID: $ROOT_UUID"
        echo "HOME_UUID: $HOME_UUID"

        UUIDs

      3. Save the mounting points of the system partitions:

        cat <<FSTAB > /etc/fstab
        # /etc/fstab: static file system information.
        #
        # Use 'blkid' to print the universally unique identifier for a
        # device; this may be used with UUID= as a more robust way to name devices
        # that works even if disks are added and removed. See fstab(5).
        #
        # <file system>                           <mount point>  <type> <options>  <dump> <pass>
        proc                                      /proc          proc   defaults   0      0
        UUID=$ESP1_UUID                            /boot/efi      vfat   umask=0077 0      1
        UUID=$ROOT_UUID /              xfs    defaults   0      1
        UUID=$HOME_UUID /home          xfs    defaults   0      0
        $SWAP_FILE                                 none           swap   sw         0      0
        FSTAB
      4. Check the /etc/fstab file:

        cat /etc/fstab

        fstab

    12. Configuring initramfs
      1. If you follow the steps in Encryption with LUKS2, add some initramfs modules:

        cat <<MODULES >> /etc/initramfs-tools/modules
        aes-i586
        aes_x86_64
        dm-crypt
        dm-mod
        xts
        MODULES
      2. If you follow the steps in Configuring LUKS with password and USB unlock, add some initramfs modules:

        cat <<MODULES >> /etc/initramfs-tools/modules
        vfat
        nls_cp437
        nls_ascii
        usb_storage
        libblkid
        MODULES
      3. Check the modules file:

        cat /etc/initramfs-tools/modules

        initramfs modules

    13. Converting APT source list to Deb822 format

      Source: https://wiki.debian.org/SourcesList

      1. Create Debian source list:

        cat <<DEBIAN.SOURCES > /etc/apt/sources.list.d/debian.sources
        Types: deb deb-src
        URIs: https://deb.debian.org/debian
        Suites: trixie trixie-updates trixie-backports
        Components: main contrib non-free non-free-firmware
        Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
        Enabled: yes
        
        Types: deb deb-src
        URIs: https://security.debian.org/debian-security
        Suites: trixie-security
        Components: main contrib non-free non-free-firmware
        Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
        Enabled: yes
        DEBIAN.SOURCES
      2. Create LinuxMint source list:

        cat <<LINUXMINT.SOURCES > /etc/apt/sources.list.d/linuxmint.sources
        Types: deb deb-src
        URIs: http://packages.linuxmint.com
        Suites: gigi
        Components: main upstream import backport
        Signed-By: /usr/share/keyrings/linuxmint-keyring.gpg
        Enabled: yes
        LINUXMINT.SOURCES
      3. Disable official-package-repositories.list:

        mv --verbose /etc/apt/sources.list.d/official-package-repositories.list \
                     /etc/apt/sources.list.d/official-package-repositories.list.disabled
      4. Update list of available packages:

        apt update
    14. Configuring secure boot mode
      1. Creating certificates

        Source: https://pve.proxmox.com/wiki/Secure_Boot_Setup

        1. Install cert-to-efi-sig-list and sign-efi-sig-list:

          apt install --no-install-recommends efitools

          Install efitools

        2. Specify a secure path to store certificates:

          SB_DIR="/root/secureboot"
        3. Create a directory to store certificates:

          mkdir --verbose --parents "$SB_DIR"
          cd "$SB_DIR"

          Create a directory to store certificates

        4. Generate the GUID:

          uuidgen --random > GUID.txt
        5. Create the self-signed PK:

          openssl req \
             -x509 \
             -nodes \
             -new \
             -sha512 \
             -days   3650 \
             -newkey rsa:4096 \
             -subj   "/CN=$DOMAIN_NAME PK/" \
             -keyout PK.key \
             -out    PK.crt
          
          openssl x509 \
             -outform DER \
             -in      PK.crt \
             -out     PK.der
          
          cert-to-efi-sig-list \
             -g "$(< GUID.txt)" \
             PK.crt PK.esl
          
          sign-efi-sig-list \
             -g "$(< GUID.txt)" \
             -k PK.key \
             -c PK.crt \
             PK PK.esl PK.auth
        6. Create the KEK, signed by the PK:

          openssl req \
             -x509 \
             -nodes \
             -new \
             -sha512 \
             -days   3650 \
             -newkey rsa:4096 \
             -subj   "/CN=$DOMAIN_NAME KEK/" \
             -keyout KEK.key \
             -out    KEK.crt
          
          openssl x509 \
             -outform DER \
             -in      KEK.crt \
             -out     KEK.der
          
          cert-to-efi-sig-list \
             -g "$(< GUID.txt)" \
             KEK.crt KEK.esl
          
          sign-efi-sig-list \
             -g "$(< GUID.txt)" \
             -k PK.key \
             -c PK.crt \
             KEK KEK.esl KEK.auth
        7. Create the db key, signed by the KEK:

          openssl req \
             -x509 \
             -nodes \
             -new \
             -sha512 \
             -days    3650 \
             -newkey  rsa:4096 \
             -subj    "/CN=$DOMAIN_NAME DB/" \
             -keyout  db.key \
             -out     db.crt
          
          openssl x509 \
             -outform DER \
             -in      db.crt \
             -out     db.der
          
          cert-to-efi-sig-list \
             -g "$(< GUID.txt)" \
             db.crt db.esl
          
          sign-efi-sig-list \
             -g "$(< GUID.txt)" \
             -k KEK.key \
             -c KEK.crt \
             db db.esl db.auth

          WARNING: Note that the keys (*.key files) should be stored in a safe place. If no shim (and no MOKs) will be used, the db key needs to be available to the system in order to sign the installed kernels!

          Creating certificates

      2. Updating secure variables
        1. Add platform key:

          efi-updatevar -f PK.auth  PK
        2. Add key exchange key:

          efi-updatevar -f KEK.auth KEK
        3. Add database:

          efi-updatevar -f db.auth  db
        4. Check secure variables:

          efi-readvar

          Updating secure variables

    15. Configuring kernel build
      1. Configure automatic DKMS module signing:

        DKMS - Dynamic Kernel Module Support

        cat <<DKMS > /etc/dkms/framework.conf.d/$DOMAIN_NAME.conf
        # Location of the key and certificate files used for Secure boot. \$kernelver
        # can be used in path to represent the target kernel version.
        # mok_signing_key can also be a "pkcs11:..." string for PKCS#11 engine, as
        # long as the sign_file program supports it.
        # (default: /var/lib/dkms):
        mok_signing_key=$SB_DIR/db.key
        mok_certificate=$SB_DIR/db.crt
        DKMS
      2. Check the DKMS Configuration:

        cat /etc/dkms/framework.conf.d/$DOMAIN_NAME.conf

        Check the DKMS Configuration

      3. Configure kernel-install:

        cat <<KERNEL > /etc/kernel/install.conf
        #  This file is part of systemd.
        #
        #  systemd is free software; you can redistribute it and/or modify it under the
        #  terms of the GNU Lesser General Public License as published by the Free
        #  Software Foundation; either version 2.1 of the License, or (at your option)
        #  any later version.
        #
        # See kernel-install(8) for details.
        
        layout=uki
        initrd_generator=initramfs-tools
        uki_generator=ukify
        KERNEL
      4. Configure UKI:

        UKI - Unified Kernel Image

        cat <<UKI > /etc/kernel/uki.conf
        #  This file is part of systemd.
        #
        #  systemd is free software; you can redistribute it and/or modify it under the
        #  terms of the GNU Lesser General Public License as published by the Free
        #  Software Foundation; either version 2.1 of the License, or (at your option)
        #  any later version.
        #
        # Ini-style configuration file for ukify(1) which is only effective when
        # \$KERNEL_INSTALL_LAYOUT or layout= in install.conf is set to uki and
        # \$KERNEL_INSTALL_UKI_GENERATOR or uki_generator= in install.conf is set to
        # ukify, or is unset. \$KERNEL_INSTALL_CONF_ROOT may be used to override the
        # search path.
        #
        # See kernel-install(8) for details.
        
        [UKI]
        #Initrd=
        #Microcode=
        #Splash=
        #PCRPKey=
        #PCRBanks=
        SecureBootSigningTool = sbsign
        SecureBootPrivateKey  = $SB_DIR/db.key
        SecureBootCertificate = $SB_DIR/db.crt
        #SecureBootCertificateDir=
        #SecureBootCertificateName=
        #SecureBootCertificateValidity=
        #SigningEngine=
        SignKernel = yes
        OSRelease = @/etc/os-release
        
        #[PCRSignature:NAME]
        #PCRPrivateKey=/etc/systemd/tpm2-pcr-private-key.pem
        #PCRPublicKey=/etc/systemd/tpm2-pcr-public-key.pem
        #Phases=
        UKI
      5. Check the UKI Configuration:

        cat /etc/kernel/uki.conf

        Check the UKI Configuration

      6. Specify the name of the UKI to be created:

        By default, the UKI name is generated from the host's unique ID:

        UKI name by machine id

        UKI_NAME="linuxmint"
        echo "$UKI_NAME" > /etc/kernel/entry-token
    16. Configuring kernel command line
      1. Get UUID of RAID device:

        RAID_UUID="$(mdadm --detail "${RAID_DEVICE:-/dev/md0}" | grep 'UUID' | awk '{print $3}')"
      2. Get UUID of LUKS device:

        LUKS_UUID="$(cryptsetup luksUUID "$LUKS_DEVICE")"
      3. Get UUID of root logical volume:

        ROOT_UUID="$(blkid --match-tag UUID --output value "/dev/mapper/$LVM_VOLUME_GROUP-root")"
      4. Save kernel command line parameters:

        If you require Hibernation, you must disable Secure Boot. The limitations are explained here: UEFI / Secure Boot.

        Choose to Set up Hibernation or Without Hibernation

        • Set up Hibernation
          1. Get the UUID of the swapfile's partition:

            SWAP_UUID="$(findmnt -no UUID -T "$SWAP_FILE")"
          2. Get the swapfile offset:

            SWAP_OFFSET="$(filefrag -v "$SWAP_FILE" | grep " 0:" | awk '{gsub(/[^0-9]*/, "", $4); print $4}')"
          3. Check kernel command line variables:

            echo "RAID_UUID: $RAID_UUID"
            echo "LUKS_UUID: $LUKS_UUID"
            echo "ROOT_UUID: $ROOT_UUID"
            echo "SWAP_UUID: $SWAP_UUID"
            echo "SWAP_OFFSET: $SWAP_OFFSET"
          4. Save kernel command line parameters:

            cat <<CMDLINE > /etc/kernel/cmdline
            rd.md.uuid=$RAID_UUID rd.luks.uuid=$LUKS_UUID root=UUID=$ROOT_UUID resume=UUID=$SWAP_UUID resume_offset=$SWAP_OFFSET rw quiet splash
            CMDLINE
          5. Check kernel command line parameters:

            cat /etc/kernel/cmdline

            Check kernel command line parameters

          6. Save the initramfs hibernation parameters:

            cat <<CMDLINE > /etc/initramfs-tools/conf.d/resume
            RESUME=UUID=$SWAP_UUID resume_offset=$SWAP_OFFSET
            CMDLINE
          7. Check the hibernation configuration parameters:

            cat /etc/initramfs-tools/conf.d/resume

            Check the hibernation configuration parameters

        • Without Hibernation
          1. Check kernel command line variables:

            echo "RAID_UUID: $RAID_UUID"
            echo "LUKS_UUID: $LUKS_UUID"
            echo "ROOT_UUID: $ROOT_UUID"
          2. Save kernel command line parameters:

            cat <<CMDLINE > /etc/kernel/cmdline
            rd.md.uuid=$RAID_UUID rd.luks.uuid=$LUKS_UUID root=UUID=$ROOT_UUID rw quiet splash
            CMDLINE
          3. Check kernel command line parameters:

            cat /etc/kernel/cmdline

            Check kernel command line parameters

    17. Automatic ESP syncing

      Source: https://github.com/mgmsam/esp-sync

      1. Get UUID of the ESPs:

        ESP1_UUID="$(blkid --match-tag UUID --output value "${SDA}1")"
        ESP2_UUID="$(blkid --match-tag UUID --output value "${SDB}1")"
      2. Check ESP UUIDs:

        echo "ESP1_UUID: $ESP1_UUID"
        echo "ESP2_UUID: $ESP2_UUID"
      3. Create esp-sync config:

        cat <<ESP_SYNC.CONF > /etc/initramfs-tools/conf.d/esp-sync.conf
        # Configuration file of the '/etc/initramfs/post-update.d/zz-esp-sync' hook
        # used after creating the initramfs image.
        
        # Specifies a space-separated list of UUIDs for all ESPs that should be
        # synchronized. In a single-ESP configuration, the variable may be left blank.
        ESP_SYNC_UUIDS="$ESP1_UUID $ESP2_UUID"
        ESP_SYNC.CONF
      4. Check esp-sync config:

        cat /etc/initramfs-tools/conf.d/esp-sync.conf

        Check esp-sync config

      5. Create the initramfs hook directory:

        mkdir --verbose --parents /etc/initramfs/post-update.d
      6. Create an automatic ESP syncing hook:

        wget --output-document "/etc/initramfs/post-update.d/zz-esp-sync" \
            https://raw.githubusercontent.com/mgmsam/esp-sync/refs/heads/main/esp-sync
      7. Make the initramfs hook executable:

        chmod --verbose u+rwx,go+rx "/etc/initramfs/post-update.d/zz-esp-sync"

        Get esp-sync script

    18. Configuring the bootloader
      1. Install the systemd-boot and linuxx64.efi.stub packages:

        apt install --no-install-recommends systemd-boot systemd-boot-efi systemd-ukify

        Install bootloader

      2. Sign an EFI boot image for use with secure boot:

        sbsign \
            --key    db.key \
            --cert   db.crt \
            --output /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed \
                     /usr/lib/systemd/boot/efi/systemd-bootx64.efi
      3. Check bootloader signature systemd-bootx64.efi.signed:

        sbverify --cert db.crt /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed
        sbverify --list        /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed

        Check bootloader signature systemd-bootx64.efi.signed

      4. Remove systemd-boot from the ESP and EFI variables:

        bootctl remove
      5. List contents of /boot directory in a tree-like format:

        tree /boot
      6. Remove bootloader leftovers from ESP:

        rm --verbose --force --recursive /boot/efi/EFI

        Remove bootloader

      7. See the UEFI boot manager configuration:

        efibootmgr
      8. Remove all unnecessary bootloaders:

        efibootmgr --delete-bootnum --bootnum 0

        Remove all unnecessary bootloaders

      9. Install systemd-boot to the ESP and EFI variables:

        bootctl install

        Reinstall bootloader

        Status bootloader

      10. Configure the systemd-boot bootloader:

        cat <<LOADER > /boot/efi/loader/loader.conf
        default            $UKI_NAME-*.efi
        timeout            5
        console-mode       keep
        editor             off
        auto-entries       off
        auto-firmware      on
        auto-reboot        on
        auto-poweroff      on
        secure-boot-enroll off
        LOADER
    19. Updating initramfs
      1. Run initrd image update:

        update-initramfs -v -t -u -k all

      2. Check for UKI existence:

        tree /boot

        check UKI

      3. If all UKI variables are correct, you should see it in the boot menu:

        bootctl --no-pager list

        check boot list

  8. Installing the video driver
    1. Create a textmode UKI:

      To solve potential problems arising after incorrect video driver installation, you will find a UKI with a command line that disables all video drivers useful for performing repair work in console mode.

      . /etc/os-release
      KERNEL_VERSION="$(uname -r)"
      CMDLINE="\
      rd.md.uuid=$RAID_UUID \
      rd.luks.uuid=$LUKS_UUID \
      root=UUID=$ROOT_UUID \
      resume=UUID=$SWAP_UUID \
      resume_offset=$SWAP_OFFSET \
      rw \
      nomodeset \
      module_blacklist=amdgpu \
      module_blacklist=i915 \
      module_blacklist=nouveau \
      module_blacklist=radeon \
      systemd.unit=multi-user.target"
      ukify build \
          --linux "/boot/vmlinuz-$KERNEL_VERSION" \
          --initrd "/boot/initrd.img-$KERNEL_VERSION" \
          --output "/boot/efi/EFI/Linux/$UKI_NAME-$KERNEL_VERSION-textmode.efi" \
          --uname "$KERNEL_VERSION" \
          --cmdline "$CMDLINE" \
          --os-release "PRETTY_NAME=$PRETTY_NAME textmode" \
          --signtool sbsign \
          --sign-kernel \
          --secureboot-private-key "$SB_DIR/db.key" \
          --secureboot-certificate "$SB_DIR/db.crt"

      Provided the UKI is created successfully and all variables are correct, it will appear in the boot menu:

      bootctl --no-pager list

      UKI textmode

    2. Installing the video driver:

      Choose to Installing the AMD driver, Installing the INTEL driver or Installing the NVIDIA driver.

      • Installing the AMD driver

        At the moment, I don't own an AMD GPU, but my next one will definitely be from AMD/the red team.

      • Installing the INTEL driver

        At the moment, I don't own an Intel GPU.

      • Installing the NVIDIA driver

        Source: https://wiki.debian.org/NvidiaGraphicsDrivers

        1. Install nvidia-detect:

          apt install nvidia-detect
        2. Detect GPU:

          nvidia-detect

          NVIDIA Detect GPU

        3. Install the NVIDIA driver package:

          Choose to For older video cards (legacy driver) or For modern video cards (current driver)

          • For older video cards (legacy driver)
            1. Add the Debian unstable repository:

              cat <<DEBIAN.SOURCES > /etc/apt/sources.list.d/unstable.sources
              Types: deb deb-src
              URIs: https://deb.debian.org/debian
              Suites: unstable
              Components: main contrib non-free non-free-firmware
              Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
              Enabled: yes
              DEBIAN.SOURCES
            2. Configure the unstable repository priority:

              cat <<DEBIAN.SOURCES > /etc/apt/preferences.d/unstable.pref
              Package: *
              Pin: release a=unstable
              Pin-Priority: -10
              DEBIAN.SOURCES
            3. Update list of available packages:

              apt update
            4. Install the NVIDIA legacy driver:

              apt install -t unstable nvidia-tesla-470-driver

          • For modern video cards (current driver)
            apt install nvidia-driver
        4. Check NVIDIA driver:

          nvidia-smi

          NVIDIA nvidia-smi

        5. Install the NVTOP package:

          apt install nvtop

          NVIDIA nvtop

  9. System upgrade
    apt full-upgrade

    System upgrade

  10. Cleaning APT
    dpkg --configure --pending
    apt autoremove --yes

    Cleaning APT

  11. Exiting the chroot environment
    exit

    exit

  12. Unmounting the file systems of the installed system
    1. Restore the local domain name system configuration file:

      mv --verbose --force /target/etc/resolv.conf.bk /target/etc/resolv.conf
    2. Unmount essential system directories:

      for FS in /dev/shm /dev/pts /dev /proc /run /sys/firmware/efi/efivars /sys
      do
          umount --verbose "/target$FS"
      done
    3. Unmount the ESP:

      umount --verbose "${SDA}1"
    4. Unmount the home partition:

      umount --verbose "/dev/mapper/$LVM_VOLUME_GROUP-home"
    5. Unmount the root (/) partition:

      umount --verbose "/dev/mapper/$LVM_VOLUME_GROUP-root"
    6. Deactivate volume groups:

      vgchange --verbose --activate n "$LVM_VOLUME_GROUP"
    7. Close LUKS devices:

      cryptsetup close "/dev/mapper/$LUKS_NAME"
    8. Stop the arrays:

      mdadm --verbose --stop "${RAID_DEVICE:-/dev/md0}"

      Unmount essential system directories

      Unmounted disks

  13. Rebooting the machine
    shutdown --reboot now
  14. Checking the secure boot certificates

  15. Booting LMDE 7
    1. Boot LMDE 7 with USB key

    2. Boot LMDE 7 without USB key

  16. Using hibernation
    1. Reboot and disable the Secureboot:

    2. Hibernate:

    3. Resume hibernation:

  17. Emergency boot

  18. Installing LMDE to nvme mdadm raid

    Best order of raid lvm and luks

    Encrypted Storage with LUKS, RAID and LVM2

    LVM-HOWTO