Skip to content

Instantly share code, notes, and snippets.

@fortes
Last active January 27, 2023 16:03
Show Gist options
  • Save fortes/03846f4e896e5d86562c527387e82ec3 to your computer and use it in GitHub Desktop.
Save fortes/03846f4e896e5d86562c527387e82ec3 to your computer and use it in GitHub Desktop.
Mounting a pool of encrypted disks with rclone and mergerfs. See http://fortes.com/2018/rclone-and-mergerfs for details.
#!/usr/bin/env bash
set -euf -o pipefail
# Removable drive names go here, separated by spaces
DRIVE_NAMES=(drive1 drive2 drive3)
# Removable and cloud drives are mounted in this local directory
DRIVE_MOUNT_ROOT="/media"
# Name of folder for root of encrypted storage on drives
ENCRYPTED_DIR_NAME="encrypted"
# Rclone remote name for pooled drives
RCLONE_POOL_NAME="encrypted_pool"
# Local path for mounting decrypted drive pool
DECRYPTED_MOUNT_PATH="/media/decrypted_pool"
# Helper for joining array items with `:`
function semicolon_join { local IFS=':'; echo "$*"; }
# Helper for unmounting on exit
function finish {
echo "Cleaning up and unmounting ..."
if mount | grep -q "$DECRYPTED_MOUNT_PATH"; then
echo "Unmounting merged rclone at $DECRYPTED_MOUNT_PATH"
fusermount -u "$DECRYPTED_MOUNT_PATH" > /dev/null 2>&1
fi
if mount | grep -q "$DRIVE_MOUNT_ROOT/merged"; then
echo "Unmounting mergerfs at $DRIVE_MOUNT_ROOT/merged"
fusermount -u "$DRIVE_MOUNT_ROOT/merged" > /dev/null 2>&1
fi
for name in "${CLOUD_DRIVE_NAMES[@]}"; do
mount_path="$DRIVE_MOUNT_ROOT/$name"
if mount | grep -q "$mount_path"; then
echo "Unmounting cloud remote $name"
fusermount -u "$mount_path" > /dev/null 2>&1
fi
done
}
trap finish EXIT
VALID_MOUNTS=()
echo "Checking removable drives"
for name in "${DRIVE_NAMES[@]}"; do
mount_path="$DRIVE_MOUNT_ROOT/$name/$ENCRYPTED_DIR_NAME"
if [ -d "$mount_path" ]; then
VALID_MOUNTS+=("$mount_path")
fi
done
# Mount cloud drives, if any
CLOUD_DRIVE_NAMES=(gdrive)
echo "Checking cloud drives"
for name in "${CLOUD_DRIVE_NAMES[@]}"; do
mount_path="$DRIVE_MOUNT_ROOT/$name"
if ! mount | grep -q "rclone_$name"; then
echo "Mounting rclone remote $name ..."
rclone mount "$name:/$ENCRYPTED_DIR_NAME" "$mount_path" \
--allow-other --read-only &
fi
VALID_MOUNTS+=("$mount_path")
done
echo "Found drives: ${VALID_MOUNTS[*]}"
echo "Mounting pool via mergerfs"
mergerfs "$(semicolon_join "${VALID_MOUNTS[@]}")" "$DRIVE_MOUNT_ROOT/merged" \
-o defaults,allow_other,moveonenospc=true \
-o fsname=encrypted_merged,category.create=epmfs,func.getattr=newest
echo "Mounting decrypted pool"
rclone mount "$RCLONE_POOL_NAME:/" "$DECRYPTED_MOUNT_PATH" \
--allow-other --no-modtime &
echo "Mounting complete, hit Control-C to unmount and exit"
wait
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment