mirror of
https://github.com/kevinveenbirkenbach/linux-image-manager.git
synced 2025-09-09 19:57:11 +02:00
Compare commits
35 Commits
5aae1f8a50
...
master
Author | SHA1 | Date | |
---|---|---|---|
e60b3cf2a7 | |||
94fdcf5758 | |||
b4a0b50e1f | |||
d613fbf262 | |||
bf95ba6090 | |||
7f82c6fcb9 | |||
13454c7e87 | |||
72c4d95606 | |||
3f272790d6 | |||
bac3edc404 | |||
b2881c1319 | |||
3daed9447b | |||
bd05fd4c2d | |||
bbb54a4237 | |||
9519b314e9 | |||
826aa42565 | |||
19f5dc7178 | |||
5aa8f65584 | |||
e37d57d569 | |||
c05e804fb5 | |||
e40974f56d | |||
e8581cb448 | |||
38a289083d | |||
796028670f | |||
265e5c6f20 | |||
de0090b60c | |||
ab8b8b6e3a | |||
59f38c4089 | |||
93beadb519 | |||
c5b091e3b3 | |||
ca6951d1fe | |||
42e9b6bd7f | |||
2d8a7fb3cb | |||
cd7b58d4fe | |||
4ed8a3468d |
7
.github/FUNDING.yml
vendored
Normal file
7
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
github: kevinveenbirkenbach
|
||||||
|
|
||||||
|
patreon: kevinveenbirkenbach
|
||||||
|
|
||||||
|
buy_me_a_coffee: kevinveenbirkenbach
|
||||||
|
|
||||||
|
custom: https://s.veen.world/paypaldonate
|
142
README.md
142
README.md
@@ -1,40 +1,136 @@
|
|||||||
# Linux Image Manager
|
# Linux Image Manager 🖥️🛠️
|
||||||
[](./LICENSE.txt)
|
|
||||||
|
|
||||||
This repository contains some shell scripts to download and configure linux images and to transfer them to a storage.
|
[](https://github.com/sponsors/kevinveenbirkenbach) [](https://www.patreon.com/c/kevinveenbirkenbach) [](https://buymeacoffee.com/kevinveenbirkenbach) [](https://s.veen.world/paypaldonate)
|
||||||
|
|
||||||
## Virtual Btrfs RAID1 Setup
|
[](./LICENSE.txt) [](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
|
|
||||||
```
|
|
||||||
|
|
||||||
## Chroot
|
### Available Script Types
|
||||||
|
|
||||||
To chroot into a Linux distribution on a storage execute:
|
- **Image Setup (`--type image`):**
|
||||||
|
Executes the Linux image setup located at `scripts/image/setup.sh`. This setup:
|
||||||
|
- Creates partitions and formats them.
|
||||||
|
- Transfers the Linux image file to the device.
|
||||||
|
- Configures boot and root partitions.
|
||||||
|
|
||||||
```bash
|
- **Single Drive Encryption Setup (`--type single`):**
|
||||||
sudo bash ./scripts/image/chroot.sh
|
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.
|
||||||
|
|
||||||
## Backup
|
- **RAID1 Encryption Setup (`--type raid1`):**
|
||||||
|
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.
|
||||||
|
|
||||||
To backup a image execute:
|
- **Backup Image Setup (`--type backup`):**
|
||||||
|
Executes the backup image setup located at `scripts/image/backup.sh`. This setup:
|
||||||
|
- Creates an image backup from a memory device to a file.
|
||||||
|
- Uses `dd` to transfer the image from the specified device to an image file.
|
||||||
|
|
||||||
```bash
|
- **Chroot Environment Setup (`--type chroot`):**
|
||||||
sudo bash ./scripts/image/backup.sh
|
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.
|
||||||
|
|
||||||
## License
|
### Command-Line Options
|
||||||
|
|
||||||
The ["GNU GENERAL PUBLIC LICENSE Version 3"](./LICENSE.txt) applies to this project.
|
- **`--type`**
|
||||||
|
**(Required)** Choose the type of script to execute. Options include: `image`, `single`, `raid1`, `backup`, and `chroot`.
|
||||||
|
|
||||||
|
- **`--extra`**
|
||||||
|
**(Optional)** Pass any extra parameters directly to the selected shell script.
|
||||||
|
|
||||||
|
- **`--auto-confirm`**
|
||||||
|
**(Optional)** Automatically bypass the confirmation prompt before executing the selected script.
|
||||||
|
|
||||||
|
- **`--help`**
|
||||||
|
**(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.
|
||||||
|
|
||||||
|
### Example Commands
|
||||||
|
|
||||||
|
- **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
118
main.py
Executable 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
2
requirements.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pacman:
|
||||||
|
- pv
|
@@ -81,25 +81,62 @@ set_device_path(){
|
|||||||
info "Device path set to: $device_path"
|
info "Device path set to: $device_path"
|
||||||
# @see https://www.heise.de/ct/hotline/Optimale-Blockgroesse-fuer-dd-2056768.html
|
# @see https://www.heise.de/ct/hotline/Optimale-Blockgroesse-fuer-dd-2056768.html
|
||||||
PHYSICAL_BLOCK_SIZE_PATH="/sys/block/$device/queue/physical_block_size"
|
PHYSICAL_BLOCK_SIZE_PATH="/sys/block/$device/queue/physical_block_size"
|
||||||
if [ -f "$device_path" ]
|
if [ -f "$PHYSICAL_BLOCK_SIZE_PATH" ]; then
|
||||||
then
|
PHYSICAL_BLOCK_SIZE=$(sudo cat $PHYSICAL_BLOCK_SIZE_PATH)
|
||||||
OPTIMAL_BLOCKSIZE=$(expr 64 \* "$(sudo cat $PHYSICAL_BLOCK_SIZE_PATH)") || error
|
if [ $? -eq 0 ]; then
|
||||||
else
|
OPTIMAL_BLOCKSIZE=$((64 * PHYSICAL_BLOCK_SIZE)) || error
|
||||||
OPTIMAL_BLOCKSIZE="1KB"
|
else
|
||||||
|
echo "Unable to read $PHYSICAL_BLOCK_SIZE_PATH"
|
||||||
|
OPTIMAL_BLOCKSIZE="4K"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
OPTIMAL_BLOCKSIZE="4K"
|
||||||
fi
|
fi
|
||||||
info "Optimal blocksize set to: $OPTIMAL_BLOCKSIZE" ||
|
info "Optimal blocksize set to: $OPTIMAL_BLOCKSIZE" || error
|
||||||
error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
overwritte_device_with_zeros(){
|
print_partition_table_info() {
|
||||||
question "Should $device_path be overwritten with zeros before copying?(y/N)" && read -r copy_zeros_to_device
|
echo "##########################################################################################"
|
||||||
if [ "$copy_zeros_to_device" = "y" ]
|
echo "Note on Partition Table Deletion:"
|
||||||
then
|
echo "---------------------------------------------"
|
||||||
info "Overwritting..." &&
|
echo "• MBR (Master Boot Record):"
|
||||||
dd if=/dev/zero of="$device_path" bs="$OPTIMAL_BLOCKSIZE" status=progress || error "Overwritting $device_path failed."
|
echo " - Typically occupies the first sector (512 bytes), i.e., 1 block."
|
||||||
else
|
echo ""
|
||||||
info "Skipping Overwritting..."
|
echo "• GPT (GUID Partition Table):"
|
||||||
fi
|
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() {
|
||||||
|
# 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
|
||||||
|
case "$copy_zeros_to_device" in
|
||||||
|
y)
|
||||||
|
info "Overwriting entire device..." &&
|
||||||
|
dd if=/dev/zero of="$device_path" bs="$OPTIMAL_BLOCKSIZE" status=progress && sync || error "Overwriting $device_path failed."
|
||||||
|
;;
|
||||||
|
N|'')
|
||||||
|
info "Skipping Overwriting..."
|
||||||
|
;;
|
||||||
|
''|*[!0-9]*)
|
||||||
|
error "Invalid input."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ "$copy_zeros_to_device" =~ ^[0-9]+$ ]]; then
|
||||||
|
info "Overwriting $copy_zeros_to_device blocks..." &&
|
||||||
|
dd if=/dev/zero of="$device_path" bs="$OPTIMAL_BLOCKSIZE" count="$copy_zeros_to_device" status=progress && sync || error "Overwriting $device_path failed."
|
||||||
|
else
|
||||||
|
error "Invalid input. Block count must be a number."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
get_packages(){
|
get_packages(){
|
||||||
|
@@ -29,12 +29,13 @@ create_luks_key_and_update_cryptab(){
|
|||||||
info "Generate secret key under: $secret_key_path" || error
|
info "Generate secret key under: $secret_key_path" || error
|
||||||
if [ -f "$secret_key_path" ]
|
if [ -f "$secret_key_path" ]
|
||||||
then
|
then
|
||||||
warning "File allready exist. Overwritting!"
|
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 &&
|
||||||
sudo cryptsetup -v luksAddKey "$2" "$secret_key_path" &&
|
|
||||||
info "Opening and closing device to verify that that everything works fine..." || error
|
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..." &&
|
||||||
@@ -45,7 +46,7 @@ create_luks_key_and_update_cryptab(){
|
|||||||
info "Adding crypttab entry..." || error
|
info "Adding crypttab entry..." || error
|
||||||
if sudo grep -q "$crypttab_entry" "$crypttab_path";
|
if sudo grep -q "$crypttab_entry" "$crypttab_path";
|
||||||
then
|
then
|
||||||
warning "File $crypttab_path contains allready the following entry:" &&
|
warning "File $crypttab_path already contains the following entry:" &&
|
||||||
echo "$crypttab_entry" &&
|
echo "$crypttab_entry" &&
|
||||||
info "Skipped." ||
|
info "Skipped." ||
|
||||||
error
|
error
|
||||||
@@ -59,6 +60,7 @@ create_luks_key_and_update_cryptab(){
|
|||||||
error
|
error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# @var $1 mapper_name
|
# @var $1 mapper_name
|
||||||
# @var $2 mount_path
|
# @var $2 mount_path
|
||||||
#
|
#
|
||||||
|
@@ -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\"..." &&
|
||||||
|
@@ -7,7 +7,7 @@ echo "Setups disk encryption"
|
|||||||
|
|
||||||
set_device_mount_partition_and_mapper_paths
|
set_device_mount_partition_and_mapper_paths
|
||||||
|
|
||||||
overwritte_device_with_zeros
|
overwrite_device
|
||||||
|
|
||||||
info "Creating new GPT partition table..."
|
info "Creating new GPT partition table..."
|
||||||
( echo "g" # create a new empty GPT partition table
|
( echo "g" # create a new empty GPT partition table
|
||||||
|
@@ -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;
|
||||||
|
@@ -38,7 +38,7 @@ make_mount_folders(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
make_working_folder(){
|
make_working_folder(){
|
||||||
working_folder_path="/tmp/raspberry-pi-tools-$(date +%s)/" &&
|
working_folder_path="/tmp/linux-image-manager-$(date +%s)/" &&
|
||||||
info "Create temporary working folder in $working_folder_path" &&
|
info "Create temporary working folder in $working_folder_path" &&
|
||||||
mkdir -v "$working_folder_path" ||
|
mkdir -v "$working_folder_path" ||
|
||||||
error
|
error
|
||||||
@@ -48,7 +48,7 @@ decrypt_root(){
|
|||||||
if [ "$(blkid "$root_partition_path" -s TYPE -o value)" == "crypto_LUKS" ]
|
if [ "$(blkid "$root_partition_path" -s TYPE -o value)" == "crypto_LUKS" ]
|
||||||
then
|
then
|
||||||
root_partition_uuid=$(blkid "$root_partition_path" -s UUID -o value) &&
|
root_partition_uuid=$(blkid "$root_partition_path" -s UUID -o value) &&
|
||||||
root_mapper_name="arch-root-$root_partition_uuid" &&
|
root_mapper_name="linux-image-manager-$root_partition_uuid" &&
|
||||||
root_mapper_path="/dev/mapper/$root_mapper_name" &&
|
root_mapper_path="/dev/mapper/$root_mapper_name" &&
|
||||||
info "Decrypting of $root_partition_path is neccessary..." &&
|
info "Decrypting of $root_partition_path is neccessary..." &&
|
||||||
sudo cryptsetup -v luksOpen "$root_partition_path" "$root_mapper_name" || error
|
sudo cryptsetup -v luksOpen "$root_partition_path" "$root_mapper_name" || error
|
||||||
|
@@ -21,6 +21,32 @@ install(){
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
replace_in_file() {
|
||||||
|
# Assign the first function argument to the local variable search_string
|
||||||
|
local search_string=$1
|
||||||
|
# Assign the second function argument to the local variable replace_string
|
||||||
|
local replace_string=$2
|
||||||
|
# Assign the third function argument to the local variable file_path
|
||||||
|
local file_path=$3
|
||||||
|
|
||||||
|
# Create a temporary file and store its path in temp_file
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
|
||||||
|
# Use sed to replace the search_string with replace_string in the file at file_path
|
||||||
|
# Write the output to the temporary file
|
||||||
|
sed "s/$search_string/$replace_string/g" "$file_path" > "$temp_file"
|
||||||
|
|
||||||
|
# Compare the original file with the temporary file
|
||||||
|
if cmp -s "$file_path" "$temp_file"; then
|
||||||
|
# If files are identical, remove the temporary file and signal an error
|
||||||
|
rm -f "$temp_file"
|
||||||
|
error "Error: Search string '$search_string' not found in $file_path."
|
||||||
|
else
|
||||||
|
# If files are different, move the temporary file to overwrite the original file
|
||||||
|
mv "$temp_file" "$file_path"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
info "Setupscript for images started..."
|
info "Setupscript for images started..."
|
||||||
|
|
||||||
info "Checking if root..."
|
info "Checking if root..."
|
||||||
@@ -58,31 +84,55 @@ case "$operation_system" in
|
|||||||
question "Which distribution should be used [arch,moode,retropie,manjaro,torbox...]?" && read -r distribution || error
|
question "Which distribution should be used [arch,moode,retropie,manjaro,torbox...]?" && read -r distribution || error
|
||||||
|
|
||||||
case "$distribution" in
|
case "$distribution" in
|
||||||
|
"android-x86")
|
||||||
|
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_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,3,4,aarch64):" && 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/";
|
||||||
if [ "$version" == "1" ]
|
case "$raspberry_pi_version" in
|
||||||
then
|
"1")
|
||||||
image_name="ArchLinuxARM-rpi-latest.tar.gz"
|
image_name="ArchLinuxARM-rpi-armv7-latest.tar.gz"
|
||||||
else
|
luks_memory_cost="64000"
|
||||||
image_name="ArchLinuxARM-rpi-$version-latest.tar.gz"
|
;;
|
||||||
fi
|
"2")
|
||||||
|
image_name="ArchLinuxARM-rpi-armv7-latest.tar.gz"
|
||||||
|
luks_memory_cost="128000"
|
||||||
|
;;
|
||||||
|
"3b" | "3b+")
|
||||||
|
image_name="ArchLinuxARM-rpi-aarch64-latest.tar.gz"
|
||||||
|
luks_memory_cost="128000"
|
||||||
|
;;
|
||||||
|
"4" )
|
||||||
|
image_name="ArchLinuxARM-rpi-aarch64-latest.tar.gz"
|
||||||
|
luks_memory_cost="256000"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Version $raspberry_pi_version isn't supported."
|
||||||
|
;;
|
||||||
|
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";
|
||||||
image_name="manjaro-architect-20.0-200426-linux56.iso"
|
image_name="manjaro-architect-20.0-200426-linux56.iso"
|
||||||
;;
|
;;
|
||||||
"gnome")
|
"gnome")
|
||||||
question "Which release(e.g.:20,21) should be used:" && read -r release
|
question "Which release(e.g.:20,21,raspberrypi) should be used:" && read -r release
|
||||||
case "$release" in
|
case "$release" in
|
||||||
"20")
|
"20")
|
||||||
image_checksum="2df3697908483550d4a473815b08c1377e6b6892"
|
image_checksum="2df3697908483550d4a473815b08c1377e6b6892"
|
||||||
@@ -93,19 +143,39 @@ case "$operation_system" in
|
|||||||
base_download_url="https://download.manjaro.org/gnome/21.3.7/"
|
base_download_url="https://download.manjaro.org/gnome/21.3.7/"
|
||||||
image_name="manjaro-gnome-21.3.7-220816-linux515.iso"
|
image_name="manjaro-gnome-21.3.7-220816-linux515.iso"
|
||||||
;;
|
;;
|
||||||
|
"22")
|
||||||
|
base_download_url="https://download.manjaro.org/gnome/22.1.3/"
|
||||||
|
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")
|
||||||
|
# at the moment just optimized for raspberry pi 4
|
||||||
|
base_download_url="https://github.com/manjaro-arm/rpi4-images/releases/download/23.02/"
|
||||||
|
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"
|
||||||
@@ -159,30 +229,81 @@ case "$operation_system" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ -z "$image_checksum" ]
|
info "Verifying image..."
|
||||||
then
|
info "Verifying checksum..."
|
||||||
sha1_download_url="$download_url.sha1"
|
if [ -z "$image_checksum" ]; then
|
||||||
info "Image Chechsum is not defined. Try to download image signature from $sha1_download_url."
|
for ext in sha1 sha512 md5; do
|
||||||
if wget -q --method=HEAD "$sha1_download_url";
|
sha_download_url="$download_url.$ext"
|
||||||
then
|
info "Image Checksum is not defined. Try to download image signature from $sha_download_url."
|
||||||
image_checksum="$(wget $sha1_download_url -q -O - | cut -d ' ' -f1 )"
|
if wget -q --method=HEAD "$sha_download_url"; then
|
||||||
info "Defined image_checksum as $image_checksum"
|
image_checksum="$(wget $sha_download_url -q -O - | cut -d ' ' -f1)"
|
||||||
else
|
info "Defined image_checksum as $image_checksum"
|
||||||
warning "No checksum found under $sha1_download_url."
|
break
|
||||||
fi
|
else
|
||||||
|
warning "No checksum found under $sha_download_url."
|
||||||
|
fi
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Verifying image..."
|
if [[ -v image_checksum ]]; then
|
||||||
if [[ -v image_checksum ]]
|
info "A checksum is defined for the image."
|
||||||
then
|
info "Checksums verify file integrity to ensure that the file was not corrupted during download."
|
||||||
(info "Checking md5 checksum..." && echo "$image_checksum $image_path"| md5sum -c -) ||
|
info "The script will try verifying the integrity using MD5, then SHA1, and finally SHA256 if needed."
|
||||||
(info "Checking sha1 checksum..." && echo "$image_checksum $image_path"| sha1sum -c -) ||
|
|
||||||
(info "Checking sha256 checksum..." && echo "$image_checksum $image_path"| sha256sum -c -) ||
|
info "Trying MD5 checksum verification..."
|
||||||
error "Verification failed. HINT: Force the download of the image."
|
(info "Checking md5 checksum..." && echo "$image_checksum $image_path" | md5sum -c -) ||
|
||||||
else
|
(warning "MD5 verification failed. This may indicate data corruption." &&
|
||||||
warning "Verification is not possible. No checksum is defined."
|
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 "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"
|
||||||
|
info "Attempting to download the 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
|
||||||
|
signature_name="${image_name}.sig"
|
||||||
|
signature_path="${image_folder}${signature_name}"
|
||||||
|
|
||||||
|
info "Download the signature file"
|
||||||
|
if wget -q -O "$signature_path" "$signature_download_url"; then
|
||||||
|
info "Extract the key ID from the signature file"
|
||||||
|
key_id=$(gpg --status-fd 1 --verify "$signature_path" "$image_path" 2>&1 | grep 'NO_PUBKEY' | awk '{print $NF}')
|
||||||
|
|
||||||
|
if [ -n "$key_id" ]; then
|
||||||
|
info "Check if the key is already in the keyring"
|
||||||
|
if gpg --list-keys "$key_id" > /dev/null 2>&1; then
|
||||||
|
info "Key $key_id already in keyring."
|
||||||
|
else
|
||||||
|
info "Import the public key"
|
||||||
|
gpg --keyserver keyserver.ubuntu.com --recv-keys "$key_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Verify the signature again after importing the key"
|
||||||
|
if gpg --verify "$signature_path" "$image_path"; then
|
||||||
|
info "Signature verification succeeded."
|
||||||
|
else
|
||||||
|
warning "Signature verification failed."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warning "No public key found in the signature file."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warning "Failed to download the signature file."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warning "No signature found under $signature_download_url."
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
make_mount_folders
|
make_mount_folders
|
||||||
|
|
||||||
set_partition_paths
|
set_partition_paths
|
||||||
@@ -202,36 +323,51 @@ if [ "$transfer_image" = "y" ]
|
|||||||
info "Skipping partition table deletion..."
|
info "Skipping partition table deletion..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
overwritte_device_with_zeros
|
overwrite_device
|
||||||
|
|
||||||
info "Starting image transfer..."
|
info "Starting image transfer..."
|
||||||
if [ "$distribution" = "arch" ]
|
if [ "$distribution" = "arch" ]
|
||||||
then
|
then
|
||||||
|
# Set default size of the boot partition
|
||||||
|
boot_size=${boot_size:-"+500M"}
|
||||||
|
|
||||||
|
# Use the provided size or the default size
|
||||||
|
info "The boot partition will be set to $boot_size."
|
||||||
|
|
||||||
|
# Partitioning with the specified size
|
||||||
info "Creating partitions..." &&
|
info "Creating partitions..." &&
|
||||||
( echo "o" #Type o. This will clear out any partitions on the drive.
|
(
|
||||||
echo "p" #Type p to list partitions. There should be no partitions left
|
echo "o" # Type o. This will clear out any partitions on the drive.
|
||||||
echo "n" #Type n,
|
echo "p" # Type p to list partitions. There should be no partitions left
|
||||||
echo "p" #then p for primary,
|
echo "n" # Type n,
|
||||||
echo "1" #1 for the first partition on the drive,
|
echo "p" # then p for primary,
|
||||||
echo "" #Default start sector
|
echo "1" # 1 for the first partition on the drive,
|
||||||
echo "+300M" #then type +300M for the last sector.
|
echo "" # Default start sector
|
||||||
echo "t" #Type t,
|
echo "$boot_size" # Size of the boot partition
|
||||||
echo "c" #then c to set the first partition to type W95 FAT32 (LBA).
|
echo "t" # Type t,
|
||||||
echo "n" #Type n,
|
echo "c" # then c to set the first partition to type W95 FAT32 (LBA).
|
||||||
echo "p" #then p for primary,
|
echo "n" # Type n,
|
||||||
echo "2" #2 for the second partition on the drive,
|
echo "p" # then p for primary,
|
||||||
echo "" #Default start sector
|
echo "2" # 2 for the second partition on the drive,
|
||||||
echo "" #Default end sector
|
echo "" # Default start sector
|
||||||
echo "w" #Write the partition table and exit by typing w.
|
echo "" # Default end sector
|
||||||
)| fdisk "$device_path" || error
|
echo "w" # Write the partition table and exit by typing w.
|
||||||
|
) | fdisk "$device_path" || error
|
||||||
|
|
||||||
info "Format boot partition..." &&
|
info "Format boot partition..." &&
|
||||||
mkfs.vfat "$boot_partition_path" || error
|
mkfs.vfat "$boot_partition_path" || error
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -262,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
|
||||||
@@ -272,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"
|
||||||
@@ -296,35 +439,53 @@ 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" &&
|
||||||
question "Should the ssh-key be copied to the image?(y/N)" && read -r copy_ssh_key || error
|
|
||||||
if [ "$copy_ssh_key" == "y" ]
|
# 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
|
||||||
|
if [ -z "$origin_user_rsa_pub" ]
|
||||||
then
|
then
|
||||||
correct_ssh_key_path=false;
|
|
||||||
while [ "$correct_ssh_key_path" != true ]
|
|
||||||
do
|
|
||||||
question "Whats the absolut path to the ssh key:" && read -r origin_user_rsa_pub || error
|
|
||||||
if [ -f "$origin_user_rsa_pub" ]
|
|
||||||
then
|
|
||||||
correct_ssh_key_path=true;
|
|
||||||
else
|
|
||||||
warning "The ssh key \"$origin_user_rsa_pub\" can't be copied to \"$target_authorized_keys\" because it doesn't exist."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
info "Copy ssh key to target..."
|
|
||||||
mkdir -v "$target_user_ssh_folder_path" || warning "Folder \"$target_user_ssh_folder_path\" exists. Can't be created."
|
|
||||||
cat "$origin_user_rsa_pub" > "$target_authorized_keys" &&
|
|
||||||
target_authorized_keys_content=$(cat "$target_authorized_keys") &&
|
|
||||||
info "$target_authorized_keys contains the following: $target_authorized_keys_content" &&
|
|
||||||
chown -vR 1000 "$target_user_ssh_folder_path" &&
|
|
||||||
chmod -v 700 "$target_user_ssh_folder_path" &&
|
|
||||||
chmod -v 600 "$target_authorized_keys" || error
|
|
||||||
else
|
|
||||||
info "Skipped SSH-key copying.."
|
info "Skipped SSH-key copying.."
|
||||||
|
else
|
||||||
|
if [ -f "$origin_user_rsa_pub" ]
|
||||||
|
then
|
||||||
|
info "Copy ssh key to target..."
|
||||||
|
mkdir -v "$target_user_ssh_folder_path" || warning "Folder \"$target_user_ssh_folder_path\" exists. Can't be created."
|
||||||
|
cat "$origin_user_rsa_pub" > "$target_authorized_keys" &&
|
||||||
|
target_authorized_keys_content=$(cat "$target_authorized_keys") &&
|
||||||
|
info "$target_authorized_keys contains the following: $target_authorized_keys_content" &&
|
||||||
|
info "Set permissions with chmod..." &&
|
||||||
|
chmod -v 700 "$target_user_ssh_folder_path" &&
|
||||||
|
chmod -v 600 "$target_authorized_keys" || error "Failed to set ownership and permissions on ssh folder"
|
||||||
|
else
|
||||||
|
error "The ssh key \"$origin_user_rsa_pub\" can't be copied to \"$target_authorized_keys\" because it doesn't exist."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Start chroot procedures..."
|
info "Start chroot procedures..."
|
||||||
@@ -335,41 +496,57 @@ if [ "$distribution" != "manjaro" ]
|
|||||||
|
|
||||||
copy_resolve_conf
|
copy_resolve_conf
|
||||||
|
|
||||||
question "Should the password of the standart user \"$target_username\" be changed?(y/N)" && read -r change_password
|
chroot_user_home_path="/home/$target_username/"
|
||||||
if [ "$change_password" == "y" ]
|
chroot_user_ssh_folder_path="$chroot_user_home_path.ssh"
|
||||||
then
|
if [ "$rename_decision" == "y" ]; then
|
||||||
info "Changing passwords on target system..."
|
info "Delete old user and create new user" &&
|
||||||
question "Type in new password: " && read -r password_1
|
(
|
||||||
question "Repeat new password\"$target_username\"" && read -r password_2
|
echo "userdel -r $variable_old_username"
|
||||||
if [ "$password_1" = "$password_2" ]
|
echo "useradd -m -d $chroot_user_home_path -s /bin/bash $target_username"
|
||||||
then
|
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"
|
||||||
echo "(
|
|
||||||
echo '$password_1'
|
|
||||||
echo '$password_1'
|
|
||||||
) | passwd $target_username"
|
|
||||||
echo "(
|
|
||||||
echo '$password_1'
|
|
||||||
echo '$password_1'
|
|
||||||
) | passwd"
|
|
||||||
) | chroot "$root_mount_path" /bin/bash || error
|
|
||||||
else
|
|
||||||
error "Passwords didn't match."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
info "Skipped password change..."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
hostname_path="$root_mount_path""etc/hostname"
|
if [ -n "$origin_user_rsa_pub" ]
|
||||||
question "Should the hostname be changed?(y/N)" && read -r change_hostname
|
|
||||||
if [ "$change_hostname" == "y" ]
|
|
||||||
then
|
then
|
||||||
question "Type in the hostname:" && read -r target_hostname;
|
info "Chroot to set ownership..." &&
|
||||||
echo "$target_hostname" > "$hostname_path" || error
|
( 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
|
||||||
|
question "Repeat new password for \"$target_username\": " && read -r password_2
|
||||||
|
if [ "$password_1" = "$password_2" ]; then
|
||||||
|
info "Changing passwords on target system..."
|
||||||
|
(
|
||||||
|
echo "(
|
||||||
|
echo '$password_1'
|
||||||
|
echo '$password_1'
|
||||||
|
) | passwd $target_username"
|
||||||
|
echo "(
|
||||||
|
echo '$password_1'
|
||||||
|
echo '$password_1'
|
||||||
|
) | passwd"
|
||||||
|
) | chroot "$root_mount_path" /bin/bash || error "Failed to change password."
|
||||||
else
|
else
|
||||||
target_hostname=$(cat "$hostname_path")
|
error "Passwords didn't match."
|
||||||
info "Skipped hostname change..."
|
fi
|
||||||
|
else
|
||||||
|
info "No password change requested, skipped password change..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
hostname_path="$root_mount_path/etc/hostname"
|
||||||
|
|
||||||
|
question "Type in the hostname (leave empty to skip): " && read -r target_hostname
|
||||||
|
|
||||||
|
if [ -n "$target_hostname" ]; then
|
||||||
|
echo "$target_hostname" > "$hostname_path" || error "Failed to set hostname."
|
||||||
|
else
|
||||||
|
target_hostname=$(cat "$hostname_path")
|
||||||
|
info "No hostname change requested, skipped hostname change..."
|
||||||
|
fi
|
||||||
|
|
||||||
info "Used hostname is: $target_hostname"
|
info "Used hostname is: $target_hostname"
|
||||||
|
|
||||||
case "$distribution" in
|
case "$distribution" in
|
||||||
@@ -412,7 +589,9 @@ if [ "$distribution" != "manjaro" ]
|
|||||||
|
|
||||||
if [ "$encrypt_system" == "y" ]
|
if [ "$encrypt_system" == "y" ]
|
||||||
then
|
then
|
||||||
# Adapted this instruction for setting up encrypted systems @see https://gist.github.com/gea0/4fc2be0cb7a74d0e7cc4322aed710d38
|
# Adapted this instruction for setting up encrypted systems
|
||||||
|
# @see https://gist.github.com/gea0/4fc2be0cb7a74d0e7cc4322aed710d38
|
||||||
|
# @see https://gist.github.com/EnigmaCurry/2f9bed46073da8e38057fe78a61e7994
|
||||||
info "Setup encryption..." &&
|
info "Setup encryption..." &&
|
||||||
|
|
||||||
info "Installing neccessary software..." &&
|
info "Installing neccessary software..." &&
|
||||||
@@ -422,19 +601,43 @@ if [ "$distribution" != "manjaro" ]
|
|||||||
info "Adding $target_authorized_keys to dropbear..." &&
|
info "Adding $target_authorized_keys to dropbear..." &&
|
||||||
cp -v "$target_authorized_keys" "$dropbear_root_key_path" &&
|
cp -v "$target_authorized_keys" "$dropbear_root_key_path" &&
|
||||||
|
|
||||||
#Concerning mkinitcpio warning @see https://gist.github.com/imrvelj/c65cd5ca7f5505a65e59204f5a3f7a6d
|
# Concerning mkinitcpio warning
|
||||||
|
# @see https://gist.github.com/imrvelj/c65cd5ca7f5505a65e59204f5a3f7a6d
|
||||||
mkinitcpio_path="$root_mount_path""etc/mkinitcpio.conf" &&
|
mkinitcpio_path="$root_mount_path""etc/mkinitcpio.conf" &&
|
||||||
info "Configuring $mkinitcpio_path..." &&
|
info "Configuring $mkinitcpio_path..." &&
|
||||||
mkinitcpio_search_modules="MODULES=()" &&
|
mkinitcpio_search_modules="MODULES=()" || error
|
||||||
mkinitcpio_replace_modules="MODULES=(g_cdc usb_f_acm usb_f_ecm smsc95xx g_ether)" &&
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
case "$raspberry_pi_version" in
|
||||||
|
"1" | "2")
|
||||||
|
mkinitcpio_additional_modules=""
|
||||||
|
;;
|
||||||
|
"3b")
|
||||||
|
mkinitcpio_additional_modules="smsc95xx"
|
||||||
|
;;
|
||||||
|
"3b+" | "4")
|
||||||
|
mkinitcpio_additional_modules="lan78xx"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
warning "Version $raspberry_pi_version isn't supported."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mkinitcpio_replace_modules="MODULES=(g_cdc usb_f_acm usb_f_ecm $mkinitcpio_additional_modules g_ether)" || error
|
||||||
|
|
||||||
|
|
||||||
mkinitcpio_search_binaries="BINARIES=()" &&
|
mkinitcpio_search_binaries="BINARIES=()" &&
|
||||||
mkinitcpio_replace_binaries=$(echo "BINARIES=(/usr/lib/libgcc_s.so.1)"| sed -e 's/[\/&]/\\&/g') &&
|
mkinitcpio_replace_binaries=$(echo "BINARIES=(/usr/lib/libgcc_s.so.1)"| sed -e 's/[\/&]/\\&/g') &&
|
||||||
mkinitcpio_encrypt_hooks="sleep netconf dropbear encryptssh" &&
|
mkinitcpio_encrypt_hooks="sleep netconf dropbear encryptssh" &&
|
||||||
mkinitcpio_search_hooks="HOOKS=(base udev autodetect modconf block filesystems keyboard fsck)" &&
|
mkinitcpio_hooks_prefix="base udev autodetect microcode modconf kms keyboard keymap consolefont block"
|
||||||
mkinitcpio_replace_hooks="HOOKS=(base udev autodetect modconf block $mkinitcpio_encrypt_hooks filesystems keyboard fsck)" &&
|
mkinitcpio_hooks_suffix="filesystems fsck"
|
||||||
sed -i "s/$mkinitcpio_search_modules/$mkinitcpio_replace_modules/g" "$mkinitcpio_path" &&
|
mkinitcpio_search_hooks="HOOKS=($mkinitcpio_hooks_prefix $mkinitcpio_hooks_suffix)" &&
|
||||||
sed -i "s/$mkinitcpio_search_binaries/$mkinitcpio_replace_binaries/g" "$mkinitcpio_path" &&
|
mkinitcpio_replace_hooks="HOOKS=($mkinitcpio_hooks_prefix $mkinitcpio_encrypt_hooks $mkinitcpio_hooks_suffix)" &&
|
||||||
sed -i "s/$mkinitcpio_search_hooks/$mkinitcpio_replace_hooks/g" "$mkinitcpio_path" &&
|
replace_in_file "$mkinitcpio_search_modules" "$mkinitcpio_replace_modules" "$mkinitcpio_path" &&
|
||||||
|
replace_in_file "$mkinitcpio_search_binaries" "$mkinitcpio_replace_binaries" "$mkinitcpio_path" &&
|
||||||
|
replace_in_file "$mkinitcpio_search_hooks" "$mkinitcpio_replace_hooks" "$mkinitcpio_path" &&
|
||||||
info "Content of $mkinitcpio_path:$(cat "$mkinitcpio_path")" &&
|
info "Content of $mkinitcpio_path:$(cat "$mkinitcpio_path")" &&
|
||||||
info "Generating mkinitcpio..." &&
|
info "Generating mkinitcpio..." &&
|
||||||
echo "mkinitcpio -vP" | chroot "$root_mount_path" /bin/bash &&
|
echo "mkinitcpio -vP" | chroot "$root_mount_path" /bin/bash &&
|
||||||
@@ -467,9 +670,11 @@ if [ "$distribution" != "manjaro" ]
|
|||||||
info "Configuring $boot_txt_path..." &&
|
info "Configuring $boot_txt_path..." &&
|
||||||
boot_txt_delete_line=$(echo "part uuid \${devtype} \${devnum}:2 uuid" | sed -e 's/[]\/$*.^[]/\\&/g') &&
|
boot_txt_delete_line=$(echo "part uuid \${devtype} \${devnum}:2 uuid" | sed -e 's/[]\/$*.^[]/\\&/g') &&
|
||||||
boot_txt_setenv_origin=$(echo "setenv bootargs console=ttyS1,115200 console=tty0 root=PARTUUID=\${uuid} rw rootwait smsc95xx.macaddr=\"\${usbethaddr}\"" | sed -e 's/[]\/$*.^[]/\\&/g') &&
|
boot_txt_setenv_origin=$(echo "setenv bootargs console=ttyS1,115200 console=tty0 root=PARTUUID=\${uuid} rw rootwait smsc95xx.macaddr=\"\${usbethaddr}\"" | sed -e 's/[]\/$*.^[]/\\&/g') &&
|
||||||
boot_txt_setenv_replace=$(echo "setenv bootargs console=ttyS1,115200 console=tty0 ip=::::$target_hostname:eth0:dhcp $cryptdevice_configuration rw rootwait smsc95xx.macaddr=\"\${usbethaddr}\""| sed -e 's/[\/&]/\\&/g') &&
|
# Concerning issues with network adapter names;
|
||||||
sed -i "s/$boot_txt_delete_line//g" "$boot_txt_path" &&
|
# @see https://forum.iobroker.net/topic/40542/raspberry-pi4-kein-eth0-mehr/16
|
||||||
sed -i "s/$boot_txt_setenv_origin/$boot_txt_setenv_replace/g" "$boot_txt_path" &&
|
boot_txt_setenv_replace=$(echo "setenv bootargs console=ttyS1,115200 console=tty0 ip=::::$target_hostname:eth0:dhcp $cryptdevice_configuration rw rootwait smsc95xx.macaddr=\"\${usbethaddr}\" net.ifnames=0 biosdevname=0"| sed -e 's/[\/&]/\\&/g') &&
|
||||||
|
replace_in_file "$boot_txt_delete_line" "" "$boot_txt_path" &&
|
||||||
|
replace_in_file "$boot_txt_setenv_origin" "$boot_txt_setenv_replace" "$boot_txt_path" &&
|
||||||
info "Content of $boot_txt_path:$(cat "$boot_txt_path")" &&
|
info "Content of $boot_txt_path:$(cat "$boot_txt_path")" &&
|
||||||
info "Generating..." &&
|
info "Generating..." &&
|
||||||
echo "cd /boot/ && ./mkscr || exit 1" | chroot "$root_mount_path" /bin/bash || error
|
echo "cd /boot/ && ./mkscr || exit 1" | chroot "$root_mount_path" /bin/bash || error
|
||||||
@@ -478,7 +683,7 @@ if [ "$distribution" != "manjaro" ]
|
|||||||
info "Configuring $cmdline_txt_path..." &&
|
info "Configuring $cmdline_txt_path..." &&
|
||||||
cmdline_search_string=$(echo "root=/dev/mmcblk0p2" | sed -e 's/[\/&]/\\&/g') &&
|
cmdline_search_string=$(echo "root=/dev/mmcblk0p2" | sed -e 's/[\/&]/\\&/g') &&
|
||||||
cmdline_replace_string=$(echo "$cryptdevice_configuration rootfstype=$root_filesystem"| sed -e 's/[\/&]/\\&/g') &&
|
cmdline_replace_string=$(echo "$cryptdevice_configuration rootfstype=$root_filesystem"| sed -e 's/[\/&]/\\&/g') &&
|
||||||
sed -i "s/$cmdline_search_string/$cmdline_replace_string/g" "$cmdline_txt_path" &&
|
replace_in_file "$cmdline_search_string" "$cmdline_replace_string" "$cmdline_txt_path" &&
|
||||||
info "Content of $cmdline_txt_path:$(cat "$cmdline_txt_path")" || error
|
info "Content of $cmdline_txt_path:$(cat "$cmdline_txt_path")" || error
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -486,7 +691,7 @@ if [ "$distribution" != "manjaro" ]
|
|||||||
info "Running system specific procedures..."
|
info "Running system specific procedures..."
|
||||||
if [ "$distribution" = "retropie" ]
|
if [ "$distribution" = "retropie" ]
|
||||||
then
|
then
|
||||||
if [ "$copy_ssh_key" == "y" ]
|
if [ -n "$origin_user_rsa_pub" ]
|
||||||
then
|
then
|
||||||
ssh_file="$boot_mount_path""ssh" &&
|
ssh_file="$boot_mount_path""ssh" &&
|
||||||
echo "" > "$ssh_file"
|
echo "" > "$ssh_file"
|
||||||
|
Reference in New Issue
Block a user