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 bycryptsetup
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.
-
Create a new encrypted volume:
just create
This will:
- Allocate a file (
IMAGE_PATH
) ofIMAGE_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.
- Allocate a file (
-
Mount the existing volume:
- If the image is compressed (
.zst
extension):
This will: check dependencies, verify checksum (ifjust mount # or 'just m' or simply 'just' (default)
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.
- If the image is compressed (
-
Unmount the volume:
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. -
Manual Compression/Decompression:
- Compress:
just compress
(CompressesIMAGE_PATH
, removes original) - Decompress:
just decompress
(DecompressesIMAGE_PATH.zst
, removes compressed version)
- Compress:
-
Checksum Management:
- Create checksum:
just create-checksum
(Createsxxh.checksum
fromIMAGE_PATH.zst
) - Verify checksum:
just verify-checksum
(VerifiesIMAGE_PATH.zst
againstxxh.checksum
)
- Create checksum:
-
Check Dependencies:
just check-deps
Checks if all required tools are installed and accessible in your
PATH
.
1 | alias m := mount |
2 | alias u := unmount |
3 | |
4 | MOUNTPOINT := "./mnt" # where the encrypted filesystem can be accessed |
5 | VOLUME_NAME := "portable_luks_volume" # how the image should be named |
6 | IMAGE_PATH := "./luks_container.img" # path where the image should be |
7 | IMAGE_SIZE := "1G" # size how big the image should be |
8 | required_deps := 'cryptsetup fallocate mkfs.ext4 zstd mount umount chown rmdir mkdir xxhsum' # required dependencies |
9 | CHECKSUM := "xxh.checksum" |
10 | |
11 | default: mount |
12 | |
13 | # mounting the encrypted volume |
14 | mount: check-deps verify-checksum decompress |
15 | @echo "creating mountpoint" |
16 | @mkdir -p {{MOUNTPOINT}} # creating mountpoint |
17 | sudo cryptsetup luksOpen {{IMAGE_PATH}} {{VOLUME_NAME}} # opening the luks container |
18 | sudo mount /dev/mapper/{{VOLUME_NAME}} {{MOUNTPOINT}} # mounting the filesystem |
19 | sudo chown $USER {{MOUNTPOINT}} # setting permission for the current user to access the mount |
20 | |
21 | # unmounting the encrypted volume |
22 | unmount: check-deps |
23 | sudo umount {{MOUNTPOINT}} # unmounting the filesystem |
24 | sudo cryptsetup luksClose {{VOLUME_NAME}} # closing the luks container |
25 | rmdir {{MOUNTPOINT}} # removing the mountpoint |
26 | just compress # compressing the image |
27 | |
28 | # creating an encrypted volume and mounting it |
29 | create: check-deps |
30 | sudo fallocate -l {{IMAGE_SIZE}} {{IMAGE_PATH}} # allocating the file |
31 | sudo cryptsetup luksFormat {{IMAGE_PATH}} {{VOLUME_NAME}} # formating the file for luks |
32 | sudo cryptsetup luksOpen {{IMAGE_PATH}} {{VOLUME_NAME}} # opening the luks container |
33 | sudo mkfs.ext4 /dev/mapper/{{VOLUME_NAME}} # formatting the container with a filesystem |
34 | mkdir -p {{MOUNTPOINT}} # creating a mountpoint |
35 | sudo mount /dev/mapper/{{VOLUME_NAME}} {{MOUNTPOINT}} # mounting filesystem |
36 | |
37 | |
38 | # compressing the image |
39 | compress: |
40 | @echo "Compressing the image and removing the original" |
41 | zstd --rm --adapt {{IMAGE_PATH}} |
42 | |
43 | # decompressing the image |
44 | decompress: |
45 | @echo "Decompressing the image and removing compressed version" |
46 | zstd --rm -d {{IMAGE_PATH}}.zst |
47 | |
48 | create-checksum: |
49 | @xxhsum {{IMAGE_PATH}}.zst > {{CHECKSUM}} |
50 | |
51 | verify-checksum: |
52 | @xxhsum -c {{CHECKSUM}} |
53 | |
54 | |
55 | # Check if all required dependencies are installed |
56 | check-deps: |
57 | #!/usr/bin/env sh |
58 | missing_deps="" |
59 | # Loop through each dependency in the list |
60 | for dep in {{required_deps}}; do |
61 | # Check if the command exists in the PATH |
62 | if ! command -v "$dep" > /dev/null 2>&1; then |
63 | # If not found, add it to the list of missing dependencies (with a space separator) |
64 | missing_deps="$missing_deps $dep" |
65 | fi |
66 | done |
67 | |
68 | # Check if the missing_deps variable has content (trim whitespace first) |
69 | if [ -n "$(echo $missing_deps | xargs)" ]; then |
70 | echo "Error: The following required dependencies are missing:" >&2 |
71 | # Use xargs to print each missing dependency on a new line, prefixed with ' - ' |
72 | echo "$missing_deps" | xargs -n1 printf " - %s\n" >&2 |
73 | echo "Please install them and try again." >&2 |
74 | # Exit with a non-zero status code to indicate failure |
75 | exit 1 |
76 | else |
77 | # Optional: message indicating success |
78 | echo "All dependencies satisfied." |
79 | fi |
80 |