48 lines
1.5 KiB
Plaintext
Executable File
48 lines
1.5 KiB
Plaintext
Executable File
#!/usr/bin/env nix-shell
|
|
#!nix-shell -i bash -p bash -p coreutils-full -p gocryptfs -p inotify-tools
|
|
|
|
passfile="$1" # e.g. /run/gocryptfs/private.key
|
|
conffile="$2" # e.g. /nix/persist/private/gocryptfs.conf
|
|
passdir=$(dirname "$passfile")
|
|
|
|
waitForPassfileOnce() {
|
|
local timeout=$1
|
|
if [ -f "$passfile" ]; then
|
|
return 0
|
|
else
|
|
# wait for some file to be created inside the directory.
|
|
# inotifywait returns 0 if the file was created. 1 or 2 if timeout was hit or it was interrupted by a different event.
|
|
inotifywait --timeout "$timeout" --event create "$passdir"
|
|
return 1 #< maybe it was created; we'll pick that up immediately, on next check
|
|
fi
|
|
}
|
|
waitForPassfile() {
|
|
# there's a race condition between testing the path and starting `inotifywait`.
|
|
# therefore, use a retry loop. exponential backoff to decrease the impact of the race condition,
|
|
# especially near the start of boot to allow for quick reboots even if/when i hit the race.
|
|
for timeout in 4 4 8 8 8 8 16 16 16 16 16 16 16 16; do
|
|
if waitForPassfileOnce "$timeout"; then
|
|
return 0
|
|
fi
|
|
done
|
|
while true; do
|
|
if waitForPassfileOnce 30; then
|
|
return 0
|
|
fi
|
|
done
|
|
}
|
|
validatePassword() {
|
|
echo "validating password ..."
|
|
if ! cat "$passfile" | gocryptfs-xray -dumpmasterkey "$conffile" > /dev/null; then
|
|
echo "failed key validation"
|
|
rm -f "$passfile"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
waitForPassfile
|
|
while ! validatePassword; do
|
|
waitForPassfile
|
|
done
|
|
echo "key provisioned"
|