Compare commits

...

14 Commits

9 changed files with 382 additions and 89 deletions

7
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
github: kevinveenbirkenbach
patreon: kevinveenbirkenbach
buy_me_a_coffee: kevinveenbirkenbach
custom: https://s.veen.world/paypaldonate

154
README.md
View File

@@ -1,62 +1,136 @@
# Linux Image Manager # Linux Image Manager 🖥️🛠️
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](./LICENSE.txt)
This repository contains some shell scripts to download and configure linux images and to transfer them to a storage. [![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-blue?logo=github)](https://github.com/sponsors/kevinveenbirkenbach) [![Patreon](https://img.shields.io/badge/Support-Patreon-orange?logo=patreon)](https://www.patreon.com/c/kevinveenbirkenbach) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-Funding-yellow?logo=buymeacoffee)](https://buymeacoffee.com/kevinveenbirkenbach) [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue?logo=paypal)](https://s.veen.world/paypaldonate)
## Virtual Btrfs RAID1 Setup [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](./LICENSE.txt) [![GitHub stars](https://img.shields.io/github/stars/kevinveenbirkenbach/linux-image-manager.svg?style=social)](https://github.com/kevinveenbirkenbach/linux-image-manager/stargazers)
To setup a virtual btrfs encrypted raid 1 execute: Linux Image Manager (lim) is a powerful collection of shell scripts for downloading, configuring, and managing Linux images. Whether you're setting up encrypted storage, configuring a virtual Btrfs RAID1, performing backups, or chrooting into an image, this tool makes Linux image administration simple and efficient. 🚀
> **Note:** In this project, `lim` is an alias for the **main.py** wrapper script which orchestrates the execution of the various shell scripts.
## Features ✨
- **Image Download & Setup:** Automatically download and prepare Linux distributions.
- **Encrypted Storage:** Configure LUKS encryption for secure image management.
- **Virtual RAID1:** Easily set up virtual Btrfs RAID1 for data redundancy.
- **Backup & Restore:** Create image backups from devices using dd.
- **Chroot Environment:** Easily enter a chroot shell to maintain or modify Linux images.
- **Automated Procedures:** Simplify partitioning, formatting, mounting, and more.
## Installation 📦
Install Linux Image Manager quickly using [Kevin's Package Manager](https://github.com/kevinveenbirkenbach/package-manager) under the alias `lim`. Just run:
```bash ```bash
bash scripts/encryption/storage/raid1/setup.sh package-manager install lim
``` ```
## Setup This command makes Linux Image Manager globally available as `lim` in your terminal. The `lim` alias points to the **main.py** wrapper script.
To install a Linux distribution execute: ## Usage ⚙️
```bash The **main.py** wrapper provides a unified interface to run the different shell scripts included in this project. It supports various script types and allows you to pass additional parameters. The built-in `--help` option displays detailed usage information.
sudo bash ./scripts/image/setup.sh
```
### Cleanup ### Available Script Types
To cleanup the image setup execute: - **Image Setup (`--type image`):**
```bash Executes the Linux image setup located at `scripts/image/setup.sh`. This setup:
fuser -k /dev/mapper/linux-image-manager-*; - Creates partitions and formats them.
umount -f /dev/mapper/linux-image-manager-*; - Transfers the Linux image file to the device.
fuser -k /tmp/linux-image-manager-*; - Configures boot and root partitions.
umount -f /tmp/linux-image-manager-*;
```
Additional you can unmount the device with a command like - **Single Drive Encryption Setup (`--type single`):**
Executes the single-drive encryption setup from `scripts/encryption/storage/single_drive/setup.sh`. This setup:
- Sets up disk encryption using LUKS on one drive.
- Configures a Btrfs file system for secure storage.
```bash - **RAID1 Encryption Setup (`--type raid1`):**
umount -f /dev/sd*; Executes the RAID1 encryption setup found at `scripts/encryption/storage/raid1/setup.sh`. This setup:
``` - Configures a virtual RAID1 with two drives.
- Uses LUKS encryption and a Btrfs RAID1 file system for redundancy.
### Verification - **Backup Image Setup (`--type backup`):**
To verify that the unmounting was successfull, check the result of Executes the backup image setup located at `scripts/image/backup.sh`. This setup:
```bash - Creates an image backup from a memory device to a file.
mount - Uses `dd` to transfer the image from the specified device to an image file.
```
## Chroot - **Chroot Environment Setup (`--type chroot`):**
Executes the chroot setup from `scripts/image/chroot.sh`. This setup:
- Mounts partitions and configures the chroot environment for a Linux image.
- Provides a shell within the Linux image for system maintenance.
To chroot into a Linux distribution on a storage execute: ### Command-Line Options
```bash - **`--type`**
sudo bash ./scripts/image/chroot.sh **(Required)** Choose the type of script to execute. Options include: `image`, `single`, `raid1`, `backup`, and `chroot`.
```
## Backup - **`--extra`**
**(Optional)** Pass any extra parameters directly to the selected shell script.
To backup a image execute: - **`--auto-confirm`**
**(Optional)** Automatically bypass the confirmation prompt before executing the selected script.
```bash - **`--help`**
sudo bash ./scripts/image/backup.sh **(Optional)** Displays detailed help information about the command-line options and usage of the wrapper. Simply run:
``` ```bash
lim --help
```
to view the complete help message.
## License ### Example Commands
The ["GNU GENERAL PUBLIC LICENSE Version 3"](./LICENSE.txt) applies to this project. - **Display Help:**
```bash
lim --help
```
- **Show Information About the Image Setup:**
```bash
lim --type image --info
```
- **Execute the Linux Image Setup (with extra parameters):**
```bash
lim --type image --extra --some-option value
```
- **Run the Single Drive Encryption Setup without a confirmation prompt:**
```bash
lim --type single --auto-confirm
```
- **Execute the RAID1 Encryption Setup:**
```bash
lim --type raid1
```
- **Perform a Backup of an Image:**
```bash
lim --type backup
```
- **Enter a Chroot Environment for a Linux Image:**
```bash
lim --type chroot
```
For additional details on each script and further configuration options, please refer to the `scripts/` and `configuration/` directories.
## Configuration & Customization 🔧
Customize your environment in the `configuration/` folder:
- **General Packages:** Contains common packages for all setup scripts.
- **Server LUKS Packages:** Contains packages needed for setting up LUKS encryption on servers.
## License 📜
This project is licensed under the GNU General Public License Version 3. See the [LICENSE.txt](./LICENSE.txt) file for details.
## Contact & Support 💬
- **Author:** Kevin Veen-Birkenbach
- **Email:** [kevin@veen.world](mailto:kevin@veen.world)
- **Website:** [https://www.veen.world/](https://www.veen.world/)
Feel free to contribute, report issues, or get in touch. Happy Linux managing! 😊
```

118
main.py Executable file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/env python3
import subprocess
import os
import argparse
import sys
def run_script(script_path, extra_args):
if not os.path.exists(script_path):
print(f"[ERROR] Script not found at {script_path}")
exit(1)
command = ["sudo", "bash", script_path] + extra_args
print(f"[INFO] Running command: {' '.join(command)}")
# Pass the parent's stdout and stderr so that progress output shows in real time.
result = subprocess.run(command, stdout=sys.stdout, stderr=sys.stderr)
if result.returncode != 0:
print(f"[ERROR] Script exited with code {result.returncode}")
exit(result.returncode)
print("[SUCCESS] Script executed successfully.")
def main():
# Use os.path.realpath to get the actual path of this file regardless of symlinks.
repo_root = os.path.dirname(os.path.realpath(__file__))
# Define available scripts along with their descriptions.
setup_scripts = {
"image": {
"path": os.path.join(repo_root, "scripts", "image", "setup.sh"),
"description": (
"Linux Image Setup:\n"
" - Creates partitions and formats them.\n"
" - Transfers the Linux image file to the device.\n"
" - Configures boot and root partitions."
)
},
"single": {
"path": os.path.join(repo_root, "scripts", "encryption", "storage", "single_drive", "setup.sh"),
"description": (
"Single Drive Encryption Setup:\n"
" - Sets up disk encryption using LUKS on one drive.\n"
" - Configures a Btrfs file system for secure storage."
)
},
"raid1": {
"path": os.path.join(repo_root, "scripts", "encryption", "storage", "raid1", "setup.sh"),
"description": (
"RAID1 Encryption Setup:\n"
" - Configures a virtual RAID1 with two drives.\n"
" - Uses LUKS encryption and a Btrfs RAID1 file system for redundancy."
)
},
"backup": {
"path": os.path.join(repo_root, "scripts", "image", "backup.sh"),
"description": (
"Backup Image Setup:\n"
" - Creates an image backup from a memory device to a file.\n"
" - Uses dd to transfer the image from the specified device to an image file."
)
},
"chroot": {
"path": os.path.join(repo_root, "scripts", "image", "chroot.sh"),
"description": (
"Chroot Environment Setup:\n"
" - Mounts partitions and configures the chroot environment for a Linux image.\n"
" - Provides a shell within the Linux image for system maintenance."
)
}
}
parser = argparse.ArgumentParser(
description="Wrapper for executing various scripts from Linux Image Manager.",
epilog=(
"Available script types:\n"
" image - Linux Image Setup\n"
" single - Single Drive Encryption Setup\n"
" raid1 - RAID1 Encryption Setup\n"
" backup - Backup Image Setup\n"
" chroot - Chroot Environment Setup\n\n"
"Additional Options:\n"
" --extra Pass extra parameters to the selected script.\n"
" --auto-confirm Bypass the confirmation prompt before execution.\n"
" --help Display this help message and exit."
),
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("--type", required=True, choices=list(setup_scripts.keys()),
help="Select the script type to execute. Options: " + ", ".join(setup_scripts.keys()))
parser.add_argument("--extra", nargs=argparse.REMAINDER, default=[],
help="Extra parameters to pass to the selected script.")
parser.add_argument("--auto-confirm", action="store_true",
help="Automatically confirm execution without prompting the user.")
args = parser.parse_args()
script_info = setup_scripts[args.type]
print("[INFO] Selected script type:", args.type)
print("[INFO] Description:")
print(script_info["description"])
print("[INFO] Script path:", script_info["path"])
if args.extra:
print("[INFO] Extra parameters provided:", " ".join(args.extra))
else:
print("[INFO] No extra parameters provided.")
if not args.auto_confirm:
try:
input("Press Enter to execute the script or Ctrl+C to cancel...")
except KeyboardInterrupt:
print("\n[ERROR] Execution aborted by user.")
exit(1)
run_script(script_info["path"], args.extra)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n[ERROR] Execution aborted by user.")
exit(1)

2
requirements.yml Normal file
View File

@@ -0,0 +1,2 @@
pacman:
- pv

View File

@@ -95,12 +95,32 @@ set_device_path(){
info "Optimal blocksize set to: $OPTIMAL_BLOCKSIZE" || error info "Optimal blocksize set to: $OPTIMAL_BLOCKSIZE" || error
} }
print_partition_table_info() {
echo "##########################################################################################"
echo "Note on Partition Table Deletion:"
echo "---------------------------------------------"
echo "• MBR (Master Boot Record):"
echo " - Typically occupies the first sector (512 bytes), i.e., 1 block."
echo ""
echo "• GPT (GUID Partition Table):"
echo " - Uses a protective MBR (1 block), a GPT header (1 block),"
echo " and usually a partition entry array that takes up about 32 blocks."
echo " - Total: approximately 34 blocks (assuming a 512-byte block size)."
echo ""
echo "Recommendation: For deleting a GPT partition table, use a block size of 512 bytes"
echo " and overwrite at least 34 blocks to ensure the entire table is cleared."
echo "##########################################################################################"
}
overwrite_device() { overwrite_device() {
# Call the function to display the information.
print_partition_table_info
question "Should $device_path be overwritten with zeros before copying? (y/N/block count)" && read -r copy_zeros_to_device question "Should $device_path be overwritten with zeros before copying? (y/N/block count)" && read -r copy_zeros_to_device
case "$copy_zeros_to_device" in case "$copy_zeros_to_device" in
y) y)
info "Overwriting entire device..." && info "Overwriting entire device..." &&
dd if=/dev/zero of="$device_path" bs="$OPTIMAL_BLOCKSIZE" status=progress || error "Overwriting $device_path failed." dd if=/dev/zero of="$device_path" bs="$OPTIMAL_BLOCKSIZE" status=progress && sync || error "Overwriting $device_path failed."
;; ;;
N|'') N|'')
info "Skipping Overwriting..." info "Skipping Overwriting..."
@@ -111,7 +131,7 @@ overwrite_device() {
*) *)
if [[ "$copy_zeros_to_device" =~ ^[0-9]+$ ]]; then if [[ "$copy_zeros_to_device" =~ ^[0-9]+$ ]]; then
info "Overwriting $copy_zeros_to_device blocks..." && info "Overwriting $copy_zeros_to_device blocks..." &&
dd if=/dev/zero of="$device_path" bs="$OPTIMAL_BLOCKSIZE" count="$copy_zeros_to_device" status=progress || error "Overwriting $device_path failed." dd if=/dev/zero of="$device_path" bs="$OPTIMAL_BLOCKSIZE" count="$copy_zeros_to_device" status=progress && sync || error "Overwriting $device_path failed."
else else
error "Invalid input. Block count must be a number." error "Invalid input. Block count must be a number."
fi fi

View File

@@ -31,20 +31,11 @@ create_luks_key_and_update_cryptab(){
then then
warning "File already exists. Overwriting!" warning "File already exists. Overwriting!"
fi fi
sudo dd if=/dev/urandom of="$secret_key_path" bs=512 count=8 && sudo dd if=/dev/urandom of="$secret_key_path" bs=512 count=8 && sync &&
# Check if luks_memory_cost is defined and set the luksAddKey command accordingly
# @see https://chatgpt.com/share/008ea5f1-670c-467c-8320-1ca67f25ac9a
if [ -n "$luks_memory_cost" ]; then
info "Adding key with --pbkdf-memory set to $luks_memory_cost" &&
sudo cryptsetup -v luksAddKey "$2" "$secret_key_path" --pbkdf-memory "$luks_memory_cost" &&
else
info "Adding key without --pbkdf-memory parameter" &&
sudo cryptsetup -v luksAddKey "$2" "$secret_key_path" &&
fi
info "Opening and closing device to verify that everything works fine..." && info "Opening and closing device to verify that everything works fine..." &&
sudo cryptsetup -v luksClose "$1" || info "No need to luksClose $1." && sudo cryptsetup -v luksClose "$1" || info "No need to luksClose $1. Device isn't open." &&
sudo cryptsetup luksAddKey $2 $secret_key_path &&
sudo cryptsetup -v luksOpen "$2" "$1" --key-file="$secret_key_path" && sudo cryptsetup -v luksOpen "$2" "$1" --key-file="$secret_key_path" &&
sudo cryptsetup -v luksClose "$1" && sudo cryptsetup -v luksClose "$1" &&
info "Reading UUID..." && info "Reading UUID..." &&

View File

@@ -3,7 +3,13 @@
# shellcheck disable=SC2154 # Referenced but not assigned # shellcheck disable=SC2154 # Referenced but not assigned
# shellcheck disable=SC2015 #Deactivate bool hint # shellcheck disable=SC2015 #Deactivate bool hint
source "$(dirname "$(readlink -f "${0}")")/base.sh" || (echo "Loading base.sh failed." && exit 1) source "$(dirname "$(readlink -f "${0}")")/base.sh" || (echo "Loading base.sh failed." && exit 1)
info "Automount raid1 encrypted storages..." && info "Activate Automount raid1 encrypted storages..." &&
echo ""
for dev in $(lsblk -dno NAME); do
if sudo cryptsetup isLuks /dev/$dev 2>/dev/null; then
info "/dev/$dev is a LUKS encrypted storage device."
fi
done
set_raid1_devices_mount_partition_and_mapper_paths && set_raid1_devices_mount_partition_and_mapper_paths &&
create_luks_key_and_update_cryptab "$mapper_name_1" "$device_path_1" && create_luks_key_and_update_cryptab "$mapper_name_1" "$device_path_1" &&
info "Creating mount folder unter \"$mount_path_1\"..." && info "Creating mount folder unter \"$mount_path_1\"..." &&

View File

@@ -25,6 +25,6 @@ question "Please confirm by pushing \"Enter\". To cancel use \"Ctrl + Alt + C\""
read -r bestaetigung && echo "$bestaetigung"; read -r bestaetigung && echo "$bestaetigung";
info "Imagetransfer starts. This can take a while..." && info "Imagetransfer starts. This can take a while..." &&
dd if="$device_path" of="$ofi" bs=1M status=progress || error "\"dd\" failed."; dd if="$device_path" of="$ofi" bs=1M status=progress && sync || error "\"dd\" failed.";
success "Imagetransfer successfull." && exit 0; success "Imagetransfer successfull." && exit 0;

View File

@@ -88,16 +88,19 @@ case "$operation_system" in
base_download_url="https://www.fosshub.com/Android-x86.html?dwl=android-x86_64-9.0-r2.iso"; base_download_url="https://www.fosshub.com/Android-x86.html?dwl=android-x86_64-9.0-r2.iso";
image_name="android-x86_64-9.0-r2.iso" image_name="android-x86_64-9.0-r2.iso"
image_checksum="f7eb8fc56f29ad5432335dc054183acf086c539f3990f0b6e9ff58bd6df4604e" image_checksum="f7eb8fc56f29ad5432335dc054183acf086c539f3990f0b6e9ff58bd6df4604e"
boot_size="+500M"
;; ;;
"torbox") "torbox")
base_download_url="https://www.torbox.ch/data/"; base_download_url="https://www.torbox.ch/data/";
image_name="torbox-20220102-v050.gz" image_name="torbox-20220102-v050.gz"
image_checksum="0E1BA7FFD14AAAE5F0462C8293D95B62C3BF1D9E726E26977BD04772C55680D3" image_checksum="0E1BA7FFD14AAAE5F0462C8293D95B62C3BF1D9E726E26977BD04772C55680D3"
boot_size="+200M"
;; ;;
"arch") "arch")
question "Which Raspberry Pi will be used (e.g.: 1, 2, 3b, 3b+, 4...):" && read -r version question "Which Raspberry Pi will be used (e.g.: 1, 2, 3b, 3b+, 4...):" && read -r raspberry_pi_version
boot_size="+500M"
base_download_url="http://os.archlinuxarm.org/os/"; base_download_url="http://os.archlinuxarm.org/os/";
case "$version" in case "$raspberry_pi_version" in
"1") "1")
image_name="ArchLinuxARM-rpi-armv7-latest.tar.gz" image_name="ArchLinuxARM-rpi-armv7-latest.tar.gz"
luks_memory_cost="64000" luks_memory_cost="64000"
@@ -115,13 +118,14 @@ case "$operation_system" in
luks_memory_cost="256000" luks_memory_cost="256000"
;; ;;
*) *)
error "Version $version isn't supported." error "Version $raspberry_pi_version isn't supported."
;; ;;
esac esac
;; ;;
"manjaro") "manjaro")
question "Which version(e.g.:architect,gnome) should be used:" && read -r version question "Which version(e.g.:architect,gnome) should be used:" && read -r gnome_version
case "$version" in boot_size="+500M"
case "$gnome_version" in
"architect") "architect")
image_checksum="6b1c2fce12f244c1e32212767a9d3af2cf8263b2" image_checksum="6b1c2fce12f244c1e32212767a9d3af2cf8263b2"
base_download_url="https://osdn.net/frs/redir.php?m=dotsrc&f=%2Fstorage%2Fg%2Fm%2Fma%2Fmanjaro%2Farchitect%2F20.0%2F"; base_download_url="https://osdn.net/frs/redir.php?m=dotsrc&f=%2Fstorage%2Fg%2Fm%2Fma%2Fmanjaro%2Farchitect%2F20.0%2F";
@@ -143,23 +147,35 @@ case "$operation_system" in
base_download_url="https://download.manjaro.org/gnome/22.1.3/" base_download_url="https://download.manjaro.org/gnome/22.1.3/"
image_name="manjaro-gnome-22.1.3-230529-linux61.iso" image_name="manjaro-gnome-22.1.3-230529-linux61.iso"
;; ;;
"24")
base_download_url="https://download.manjaro.org/gnome/24.2.1/"
image_name="manjaro-gnome-24.2.1-241216-linux612.iso"
;;
"raspberrypi") "raspberrypi")
# at the moment just optimized for raspberry pi 4
base_download_url="https://github.com/manjaro-arm/rpi4-images/releases/download/23.02/" base_download_url="https://github.com/manjaro-arm/rpi4-images/releases/download/23.02/"
image_name="Manjaro-ARM-gnome-rpi4-23.02.img.xz" image_name="Manjaro-ARM-gnome-rpi4-23.02.img.xz"
luks_memory_cost="256000"
raspberry_pi_version="4"
;;
*)
error "Gnome Version $gnome_version isn't supported."
;; ;;
esac esac
;; ;;
esac esac
;; ;;
"moode") "moode")
boot_size="+200M"
image_checksum="185cbc9a4994534bb7a4bc2744c78197" image_checksum="185cbc9a4994534bb7a4bc2744c78197"
base_download_url="https://github.com/moode-player/moode/releases/download/r651prod/" base_download_url="https://github.com/moode-player/moode/releases/download/r651prod/"
image_name="moode-r651-iso.zip"; image_name="moode-r651-iso.zip";
;; ;;
"retropie") "retropie")
question "Which version(e.g.:1,2,3,4) should be used:" && read -r version boot_size="+500M"
question "Which version(e.g.:1,2,3,4) should be used:" && read -r raspberry_pi_version
base_download_url="https://github.com/RetroPie/RetroPie-Setup/releases/download/4.8/"; base_download_url="https://github.com/RetroPie/RetroPie-Setup/releases/download/4.8/";
case "$version" in case "$raspberry_pi_version" in
"1") "1")
image_checksum="95a6f84453df36318830de7e8507170e" image_checksum="95a6f84453df36318830de7e8507170e"
image_name="retropie-buster-4.8-rpi1_zero.img.gz" image_name="retropie-buster-4.8-rpi1_zero.img.gz"
@@ -229,18 +245,28 @@ if [ -z "$image_checksum" ]; then
done done
fi fi
if [[ -v image_checksum ]] if [[ -v image_checksum ]]; then
then info "A checksum is defined for the image."
(info "Checking md5 checksum..." && echo "$image_checksum $image_path"| md5sum -c -) || info "Checksums verify file integrity to ensure that the file was not corrupted during download."
(info "Checking sha1 checksum..." && echo "$image_checksum $image_path"| sha1sum -c -) || info "The script will try verifying the integrity using MD5, then SHA1, and finally SHA256 if needed."
(info "Checking sha256 checksum..." && echo "$image_checksum $image_path"| sha256sum -c -) ||
error "Verification failed. HINT: Force the download of the image." info "Trying MD5 checksum verification..."
else (info "Checking md5 checksum..." && echo "$image_checksum $image_path" | md5sum -c -) ||
warning "Verification is not possible. No checksum is defined." (warning "MD5 verification failed. This may indicate data corruption." &&
info "Trying SHA1 checksum verification for a secondary integrity check..." &&
info "Checking sha1 checksum..." && echo "$image_checksum $image_path" | sha1sum -c -) ||
(warning "SHA1 verification failed. Attempting SHA256 verification for thoroughness." &&
info "SHA256 provides a more robust check and is used as a final integrity measure." &&
info "Checking sha256 checksum..." && echo "$image_checksum $image_path" | sha256sum -c -) ||
error "Verification failed. HINT: Force the download of the image."
else
warning "No checksum is defined. Skipping checksum verification."
fi fi
info "Verifying signature..." info "Note: Checksums verify integrity but do not confirm authenticity."
info "Proceeding to signature verification, which ensures the file comes from a trusted source."
signature_download_url="$download_url.sig" signature_download_url="$download_url.sig"
info "Attempting to download the image signature from: $signature_download_url"
info "Try to download image signature from $signature_download_url." info "Try to download image signature from $signature_download_url."
if wget -q --method=HEAD "$signature_download_url"; then if wget -q --method=HEAD "$signature_download_url"; then
@@ -302,13 +328,8 @@ if [ "$transfer_image" = "y" ]
info "Starting image transfer..." info "Starting image transfer..."
if [ "$distribution" = "arch" ] if [ "$distribution" = "arch" ]
then then
# Set default size of the boot partition
# Default size of the boot partition boot_size=${boot_size:-"+500M"}
default_boot_size="+300M"
# Prompt to adjust the boot partition size
question "What size should the boot partition be? (Default: $default_boot_size):" && read -r boot_size
boot_size=${boot_size:-$default_boot_size}
# Use the provided size or the default size # Use the provided size or the default size
info "The boot partition will be set to $boot_size." info "The boot partition will be set to $boot_size."
@@ -338,8 +359,15 @@ if [ "$transfer_image" = "y" ]
if [ "$encrypt_system" == "y" ] if [ "$encrypt_system" == "y" ]
then then
info "Formating $root_partition_path with LUKS..." && # Check if luks_memory_cost is defined and set the luksAddKey command accordingly
sudo cryptsetup -v luksFormat -c aes-xts-plain64 -s 512 -h sha512 --use-random -i 1000 "$root_partition_path" && # @see https://chatgpt.com/share/008ea5f1-670c-467c-8320-1ca67f25ac9a
if [ -n "$luks_memory_cost" ]; then
info "Formating $root_partition_path with LUKS with --pbkdf-memory set to $luks_memory_cost" &&
sudo cryptsetup -v luksFormat -c aes-xts-plain64 -s 512 -h sha512 --use-random -i 1000 --pbkdf-memory "$luks_memory_cost" "$root_partition_path" || error
else
info "Formating $root_partition_path with LUKS" &&
sudo cryptsetup -v luksFormat -c aes-xts-plain64 -s 512 -h sha512 --use-random -i 1000 "$root_partition_path" || error
fi
decrypt_root || error decrypt_root || error
fi fi
@@ -370,7 +398,13 @@ if [ "$transfer_image" = "y" ]
elif [ "${image_path: -4}" = ".iso" ] elif [ "${image_path: -4}" = ".iso" ]
then then
info "Transfering .iso file..." && info "Transfering .iso file..." &&
sudo dd if="$image_path" of="$device_path" bs="$OPTIMAL_BLOCKSIZE" conv=fsync status=progress && pv "$image_path" | sudo dd of="$device_path" bs="$OPTIMAL_BLOCKSIZE" conv=fsync &&
sync ||
error
elif [ "${image_path: -3}" = ".xz" ]
then
info "Transferring .xz file..." &&
unxz -c "$image_path" | sudo dd of="$device_path" bs="$OPTIMAL_BLOCKSIZE" conv=fsync status=progress &&
sync || sync ||
error error
else else
@@ -380,7 +414,8 @@ if [ "$transfer_image" = "y" ]
info "Skipping image transfer..." info "Skipping image transfer..."
fi fi
if [ "$distribution" != "manjaro" ] # Execute Raspberry Pi specific procedures
if [ -n "$raspberry_pi_version" ]
then then
info "Start regular mounting procedure..." info "Start regular mounting procedure..."
if mount | grep -q "$boot_partition_path" if mount | grep -q "$boot_partition_path"
@@ -404,11 +439,35 @@ if [ "$distribution" != "manjaro" ]
info "Content of $fstab_path:$(cat "$fstab_path")" || error info "Content of $fstab_path:$(cat "$fstab_path")" || error
info "Define target paths..." && info "Define target paths..." &&
administrator_username="administrator"
target_home_path="$root_mount_path""home/" && target_home_path="$root_mount_path""home/" &&
target_username=$(ls "$target_home_path") && default_username=$(ls "$target_home_path") &&
question "Should the $default_username be renamed to $administrator_username? (y/N):" && read -r rename_decision
if [ "$rename_decision" == "y" ];
then
variable_old_username="$default_username" &&
target_username="$administrator_username" &&
info "Rename home directory from $target_home_path$variable_old_username to $target_home_path$target_username..." &&
mv -v "$target_home_path$variable_old_username" "$target_home_path$target_username" || error "Failed to rename home directory"
else
target_username="$default_username"
fi
target_user_home_folder_path="$target_home_path$target_username/" && target_user_home_folder_path="$target_home_path$target_username/" &&
target_user_ssh_folder_path="$target_user_home_folder_path"".ssh/" && target_user_ssh_folder_path="$target_user_home_folder_path"".ssh/" &&
target_authorized_keys="$target_user_ssh_folder_path""authorized_keys" && target_authorized_keys="$target_user_ssh_folder_path""authorized_keys" &&
# Activate later. Here was a bug
question "Should the $target_username have sudo rights? (y/N):" && read -r sudo_decision
if [ "$sudo_decision" == "y" ]; then
sudo_config_dir="$root_mount_path""etc/sudoers.d/"
sudo_config_file="$sudo_config_dir$target_username"
mkdir -vp $sudo_config_dir
echo "$target_username ALL=(ALL:ALL) ALL" > "$sudo_config_file" || error "Failed to create sudoers file for $target_username"
chmod 440 "$sudo_config_file" || error "Failed to set permissions on sudoers file for $target_username"
fi
question "Enter the path to the SSH key to be added to the image (default: none):" && read -r origin_user_rsa_pub || error question "Enter the path to the SSH key to be added to the image (default: none):" && read -r origin_user_rsa_pub || error
if [ -z "$origin_user_rsa_pub" ] if [ -z "$origin_user_rsa_pub" ]
then then
@@ -421,9 +480,9 @@ if [ "$distribution" != "manjaro" ]
cat "$origin_user_rsa_pub" > "$target_authorized_keys" && cat "$origin_user_rsa_pub" > "$target_authorized_keys" &&
target_authorized_keys_content=$(cat "$target_authorized_keys") && target_authorized_keys_content=$(cat "$target_authorized_keys") &&
info "$target_authorized_keys contains the following: $target_authorized_keys_content" && info "$target_authorized_keys contains the following: $target_authorized_keys_content" &&
chown -vR 1000 "$target_user_ssh_folder_path" && info "Set permissions with chmod..." &&
chmod -v 700 "$target_user_ssh_folder_path" && chmod -v 700 "$target_user_ssh_folder_path" &&
chmod -v 600 "$target_authorized_keys" || error chmod -v 600 "$target_authorized_keys" || error "Failed to set ownership and permissions on ssh folder"
else else
error "The ssh key \"$origin_user_rsa_pub\" can't be copied to \"$target_authorized_keys\" because it doesn't exist." error "The ssh key \"$origin_user_rsa_pub\" can't be copied to \"$target_authorized_keys\" because it doesn't exist."
fi fi
@@ -437,7 +496,23 @@ if [ "$distribution" != "manjaro" ]
copy_resolve_conf copy_resolve_conf
question "Type in new password (leave empty to skip): " && read -r password_1 chroot_user_home_path="/home/$target_username/"
chroot_user_ssh_folder_path="$chroot_user_home_path.ssh"
if [ "$rename_decision" == "y" ]; then
info "Delete old user and create new user" &&
(
echo "userdel -r $variable_old_username"
echo "useradd -m -d $chroot_user_home_path -s /bin/bash $target_username"
echo "chown -R $target_username:$target_username $chroot_user_home_path"
) | chroot "$root_mount_path" /bin/bash || error "Failed to delete old user and create new user"
fi
if [ -n "$origin_user_rsa_pub" ]
then
info "Chroot to set ownership..." &&
( echo "chown -vR $target_username:$target_username $chroot_user_ssh_folder_path" ) | chroot "$root_mount_path" /bin/bash || error
fi
question "Type in new password for user root and $target_username (leave empty to skip): " && read -r password_1
if [ -n "$password_1" ]; then if [ -n "$password_1" ]; then
question "Repeat new password for \"$target_username\": " && read -r password_2 question "Repeat new password for \"$target_username\": " && read -r password_2
@@ -535,7 +610,7 @@ if [ "$distribution" != "manjaro" ]
# Concerning which moduls to load # Concerning which moduls to load
# @see https://raspberrypi.stackexchange.com/questions/67051/raspberry-pi-3-with-archarm-and-encrypted-disk-will-not-boot-how-can-be-identif # @see https://raspberrypi.stackexchange.com/questions/67051/raspberry-pi-3-with-archarm-and-encrypted-disk-will-not-boot-how-can-be-identif
case "$version" in case "$raspberry_pi_version" in
"1" | "2") "1" | "2")
mkinitcpio_additional_modules="" mkinitcpio_additional_modules=""
;; ;;
@@ -546,7 +621,7 @@ if [ "$distribution" != "manjaro" ]
mkinitcpio_additional_modules="lan78xx" mkinitcpio_additional_modules="lan78xx"
;; ;;
*) *)
warning "Version $version isn't supported." warning "Version $raspberry_pi_version isn't supported."
;; ;;
esac esac