commit 9313f4fdd38186bcfc130b85672296e080556cb6 Author: Erik Grobecker Date: Sat Apr 5 15:43:28 2025 +0200 feat: added portable luks project diff --git a/luks-portable/README.md b/luks-portable/README.md new file mode 100644 index 0000000..a900ff4 --- /dev/null +++ b/luks-portable/README.md @@ -0,0 +1,76 @@ +# Portable LUKS Volume Manager (using just) + +This `justfile` provides commands to create, manage, mount, and unmount a portable, encrypted LUKS volume stored in a file. It also includes compression and checksum verification for the volume image. + +## Features + +* Create a new LUKS encrypted volume within a file. +* Mount the encrypted volume to a specified mountpoint. +* Unmount the encrypted volume. +* Compress the volume image using `zstd` for portability/storage. +* Decompress the volume image. +* Create and verify checksums for the compressed image. +* Automatically checks for required dependencies. + +## Requirements + +The following dependencies must be installed on your system: +`cryptsetup`, `fallocate`, `mkfs.ext4`, `zstd`, `mount`, `umount`, `chown`, `rmdir`, `mkdir`, `xxhsum`. + +The `check-deps` recipe will verify these before most operations. + +## Configuration + +You can modify these variables at the top of the `justfile`: + +* `MOUNTPOINT`: Directory where the decrypted filesystem will be mounted (default: `./mnt`). +* `VOLUME_NAME`: Internal name used by `cryptsetup` for the mapped device (default: `portable_luks_volume`). +* `IMAGE_PATH`: Path to the LUKS container file (default: `./luks_container.img`). +* `IMAGE_SIZE`: Size for the container file when creating it (default: `1G`). +* `CHECKSUM`: Path to the checksum file (default: `xxh.checksum`). + +## Usage + +**Note:** Most commands require `sudo` privileges for `cryptsetup` and `mount`/`umount` operations. You will likely be prompted for your password. + +1. **Create a new encrypted volume:** + ```bash + just create + ``` + This will: + * Allocate a file (`IMAGE_PATH`) of `IMAGE_SIZE`. + * Format it as a LUKS volume. + * Open the LUKS volume. + * Create an `ext4` filesystem inside it. + * Create the `MOUNTPOINT` directory. + * Mount the filesystem to `MOUNTPOINT`. + * **(Important)** After creation, you should immediately `just unmount` to compress the initial empty image if desired. + +2. **Mount the existing volume:** + * If the image is compressed (`.zst` extension): + ```bash + just mount # or 'just m' or simply 'just' (default) + ``` + This will: check dependencies, verify checksum (if `xxh.checksum` exists), decompress the image, create the mountpoint, open the LUKS container, mount the filesystem, and set user ownership on the mountpoint. + * If the image is *not* compressed: + You might need to manually run the steps after decompression or adapt the `mount` recipe. The default flow assumes starting from a compressed state. + +3. **Unmount the volume:** + ```bash + just unmount # or 'just u' + ``` + This will: unmount the filesystem, close the LUKS container, remove the mountpoint directory, and compress the image file (`IMAGE_PATH` -> `IMAGE_PATH.zst`), removing the original. + +4. **Manual Compression/Decompression:** + * Compress: `just compress` (Compresses `IMAGE_PATH`, removes original) + * Decompress: `just decompress` (Decompresses `IMAGE_PATH.zst`, removes compressed version) + +5. **Checksum Management:** + * Create checksum: `just create-checksum` (Creates `xxh.checksum` from `IMAGE_PATH.zst`) + * Verify checksum: `just verify-checksum` (Verifies `IMAGE_PATH.zst` against `xxh.checksum`) + +6. **Check Dependencies:** + ```bash + just check-deps + ``` + Checks if all required tools are installed and accessible in your `PATH`. diff --git a/luks-portable/justfile b/luks-portable/justfile new file mode 100755 index 0000000..bec4455 --- /dev/null +++ b/luks-portable/justfile @@ -0,0 +1,79 @@ +alias m := mount +alias u := unmount + +MOUNTPOINT := "./mnt" # where the encrypted filesystem can be accessed +VOLUME_NAME := "portable_luks_volume" # how the image should be named +IMAGE_PATH := "./luks_container.img" # path where the image should be +IMAGE_SIZE := "1G" # size how big the image should be +required_deps := 'cryptsetup fallocate mkfs.ext4 zstd mount umount chown rmdir mkdir xxhsum' # required dependencies +CHECKSUM := "xxh.checksum" + +default: mount + +# mounting the encrypted volume +mount: check-deps verify-checksum decompress + @echo "creating mountpoint" + @mkdir -p {{MOUNTPOINT}} # creating mountpoint + sudo cryptsetup luksOpen {{IMAGE_PATH}} {{VOLUME_NAME}} # opening the luks container + sudo mount /dev/mapper/{{VOLUME_NAME}} {{MOUNTPOINT}} # mounting the filesystem + sudo chown $USER {{MOUNTPOINT}} # setting permission for the current user to access the mount + +# unmounting the encrypted volume +unmount: check-deps + sudo umount {{MOUNTPOINT}} # unmounting the filesystem + sudo cryptsetup luksClose {{VOLUME_NAME}} # closing the luks container + rmdir {{MOUNTPOINT}} # removing the mountpoint + just compress # compressing the image + +# creating an encrypted volume and mounting it +create: check-deps + sudo fallocate -l {{IMAGE_SIZE}} {{IMAGE_PATH}} # allocating the file + sudo cryptsetup luksFormat {{IMAGE_PATH}} {{VOLUME_NAME}} # formating the file for luks + sudo cryptsetup luksOpen {{IMAGE_PATH}} {{VOLUME_NAME}} # opening the luks container + sudo mkfs.ext4 /dev/mapper/{{VOLUME_NAME}} # formatting the container with a filesystem + mkdir -p {{MOUNTPOINT}} # creating a mountpoint + sudo mount /dev/mapper/{{VOLUME_NAME}} {{MOUNTPOINT}} # mounting filesystem + + +# compressing the image +compress: + @echo "Compressing the image and removing the original" + zstd --rm --adapt {{IMAGE_PATH}} + +# decompressing the image +decompress: + @echo "Decompressing the image and removing compressed version" + zstd --rm -d {{IMAGE_PATH}}.zst + +create-checksum: + @xxhsum {{IMAGE_PATH}}.zst > {{CHECKSUM}} + +verify-checksum: + @xxhsum -c {{CHECKSUM}} + + +# Check if all required dependencies are installed +check-deps: + #!/usr/bin/env sh + missing_deps="" + # Loop through each dependency in the list + for dep in {{required_deps}}; do + # Check if the command exists in the PATH + if ! command -v "$dep" > /dev/null 2>&1; then + # If not found, add it to the list of missing dependencies (with a space separator) + missing_deps="$missing_deps $dep" + fi + done + + # Check if the missing_deps variable has content (trim whitespace first) + if [ -n "$(echo $missing_deps | xargs)" ]; then + echo "Error: The following required dependencies are missing:" >&2 + # Use xargs to print each missing dependency on a new line, prefixed with ' - ' + echo "$missing_deps" | xargs -n1 printf " - %s\n" >&2 + echo "Please install them and try again." >&2 + # Exit with a non-zero status code to indicate failure + exit 1 + else + # Optional: message indicating success + echo "All dependencies satisfied." + fi