ossuary
Ive created a script called ossuary which will mount and unmount geli encryped containers with geli keys
you create a file which you use as a geli encrypted container with a key file and format the container as zfs,
and set the zfs mount point which the script uses to mount the device which is described below
Script usage
* mount device
* umount device
-f and the path to the geli container
-k and the path to the geli key file
ossuary script - sh version
ossuary - sh version github
ossuary script - bash version
ossuary bash version on githib
Install ossuary script
* create a bin directory in your home directory
* change permissions
* copy the ossuary script to your ~/bin directory
make the ossuary script executable
* edit your bashrc and add your bin directory to your bash path
add the code below to your bashrc
* source your bashrc file
What the script outputs in the terminal when you mount a geli encrypted container
* first you are prompted for your sudo passsword
the script then shows that it is creating a vnode for your geli container, it will display your username and not the actual word username
then the script shows the path for the geli key and the path to the geli container
you are then prompted for the geli key password
the script then shows it is importing the zfs pool name
and the pool is then mounted to the location of the zfs mount point you set on the geli container
What the script outputs in the terminal when you umount a geli encrypted container
The script prompts you for your sudo password and then provides feedback on umounting the zfs pool,
exporting the zfs pool, detatching the geli file and using mdconfig to clear the md0 file
If you enter the wrong geli password the script will exit and automatically use mdconfig to clear the md0 file
Next you need to create the geli encrypted container as outlined below before you can use the script
Set up geli encrypted conatiner
Create geli encrypted container
Load geli Support
Support for geli is available as a loadable kernel module. To configure the system to automatically load the module at boot time, add the following line to /boot/loader.conf:
create virtual container with dd
create a 2 gig container with dd on the Desktop called disk.img
* change directory to the Desktop
switch to root
* use dd to create a 2 gig disk image
* mount the image with mdconfig
Here, the -a option forces the disk mounting, -t vnode is used for opening a regular file, and the path of this file is specified after -f. The -u 0 option set the virtual disk identifier to use, in this case /dev/md0.
* Generate the Master Key
create directory to store geli key
Now we want to create a key for GELI to encrypt with, and attach it to our disk image device:
replace username with your username
Add the location of your geli key
Enter passphrase:
Create the ZFS File System
* use dd to write random data to geli container before adding file system
* To create a simple, non-redundant pool using a single disk device:
* add compression and duplication to the zfs pool
* zfs set mount point
create the mount point for zfs
change the permissions on the mount point
set the zfs mount point
replace username with your username
* change the permission on the container
replace username with your username
Finally, when you want to unmount, we also want to detach from GELI and detach from md:
zfs unmount
* geli detach
* mdconfig free loop device
manual mounting and unmounting
* mount
use mdconfig to mount the encrypted container to /dev/md0
* use geli with the path to the key and device
replace username with your username
* we need to import the zpool which will also mount the container
* umount
unmount the zfs pool
* we need to export the zfs pool before we use geli detach, otherwise geli thinks the device is busy
* use geli to detach the encrypted device
* free the loop device
Ive created a script called ossuary which will mount and unmount geli encryped containers with geli keys
you create a file which you use as a geli encrypted container with a key file and format the container as zfs,
and set the zfs mount point which the script uses to mount the device which is described below
Script usage
* mount device
Bash:
sudo ossuary mount -f ~/documents/disk.img -k ~/.ossuary/ossuary.key
* umount device
Bash:
sudo ossuary umount -f ~/documents/disk.img
-f and the path to the geli container
-k and the path to the geli key file
ossuary script - sh version
Bash:
#!/bin/sh
# script usage
script_usage=$(printf "%s\n" \
"mount: sudo $(basename "$0") mount -f container -k gelikey" \
"umount: sudo $(basename "$0") umount -f container")
# check to see if script was run as root
if [ "$(id -u)" != "0" ]; then
printf "%s\n" "$0 must be run as root using sudo" "$script_usage"
exit 1
fi
# mount function
mount () {
# group commands
{
# container
container="$1" && \
# gelikey
gelikey="$2" && \
# mdconfig loopname from container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//')
# eli filepath
loopcrypt="/dev/${loopdevice}.eli"
# mdconfig create vnode from container
printf "%s\n" "+ mdconfig creating vnode for '$container'" && \
loop=$(mdconfig -a -t vnode -f "$container") && \
# geli attach key to vnode
printf "%s\n" "+ geli attaching '$gelikey' key to '$container' file" && \
geli attach -k "$gelikey" "$loop" && \
# mdconfig loop device for container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//') && \
# path to mdconfig eli file
loopcrypt="/dev/${loopdevice}.eli" && \
# zpool name from mdconfig eli file
poolname=$(zdb -l "$loopcrypt" | awk -F\' '/[[:blank:]]name/ {print $2; exit;}') && \
# zpool import pool
printf "%s\n" "+ zpool importing '$poolname'" && \
zpool import "$poolname" && \
# mount point from zpool
mountpoint=$(zfs get -H -o value mountpoint "$poolname") && \
printf "%s\n" "+ '$poolname' mounted to '$mountpoint'";
} || { mdconfig -du "$loopdevice" && exit; }
}
# umount function
umount () {
# group commands
{
# container
container="$1" && \
# mdconfig loopname from container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//') && \
# eli filepath
loopcrypt="/dev/${loopdevice}.eli" && \
# zpool name from eli file
poolname=$(zdb -l "$loopcrypt" | awk -F\' '/[[:blank:]]name/ {print $2; exit;}') && \
# zfs umount poolname
printf "%s\n" "- zfs unmounting '$poolname'" && \
zfs umount "$poolname" && \
# zpool export poolname
printf "%s\n" "- zpool exporting '$poolname'" && \
zpool export "$poolname" && \
sleep 1 && \
# geli detach
printf "%s\n" "- geli detaching '$loopcrypt'" && \
geli detach "$loopcrypt" && \
# mdconfig remove md file
printf "%s\n" "- mdconfig clearing '$loopdevice'" && \
mdconfig -du "$loopdevice" && \
printf "%s\n" "- unmounted device";
} || { printf "%s\n" 'container not mounted' && exit; }
}
# check if mount is first argument
# + 2nd argument shuld be -f for the file to mount
# + 3rd argument should be the path to the file to mount
# + 4th argunent should be -k for key
# + 5th argument should be the path to the keyfile
# check if umount is first argument
# + 2nd argument shuld be -f for the file to unmount
# + 3rd argument should be the path to the file to unmount
# check arguments
if [ "$1" = mount ] && [ $# -eq 5 ]; then
# group commands
{
[ "$2" = '-f' ] && \
[ -f "$3" ] && \
[ "$4" = '-k' ] && \
[ -f "$5" ];
} || { printf "%s\n" "$script_usage" && exit; }
# mount function pass conatainer and key to function
mount "$3" "$5"
elif [ "$1" = umount ] && [ $# -eq 3 ]; then
# group commands
{
[ "$2" = '-f' ] && \
[ -f "$3" ];
} || { printf "%s\n" "$script_usage" && exit; }
# umount function pass container to function
umount "$3"
else
printf "%s\n" "$script_usage"
fi
ossuary - sh version github
ossuary script - bash version
Bash:
#!/usr/local/bin/bash
# geli container mount and umount script
#=======================================
# script usage
script_usage=$(printf "%s\n%s\n" \
"mount: sudo $(basename "$0") mount -f container -k gelikey" \
"umount: sudo $(basename "$0") umount -f container")
# check to see if script was run as root
if [[ $UID -ne 0 ]]; then
printf "%s\n" "$0 must be run as root using sudo" &&
printf "%s\n" "$script_usage"
exit 1
fi
# mount function
mount () {
# group commands
{
# container
container="$1" && \
# gelikey
gelikey="$2" && \
# mdconfig loopname from container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//')
# eli filepath
loopcrypt="/dev/${loopdevice}.eli"
# mdconfig create vnode from container
printf "%s\n" "+ mdconfig creating vnode for '$container'" && \
loop=$(mdconfig -a -t vnode -f "$container") && \
# geli attach key to vnode
printf "%s\n" "+ geli attaching '$gelikey' key to '$container' file" && \
geli attach -k "$gelikey" "$loop" && \
# mdconfig loop device for container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//') && \
# path to mdconfig eli file
loopcrypt="/dev/${loopdevice}.eli" && \
# zpool name from mdconfig eli file
poolname=$(zdb -l "$loopcrypt" | awk -F\' '/[[:blank:]]name/ {print $2; exit;}') && \
# zpool import pool
printf "%s\n" "+ zpool importing '$poolname'" && \
zpool import "$poolname" && \
# mount point from zpool
mountpoint=$(zfs get -H -o value mountpoint "$poolname") && \
printf "%s\n" "+ '$poolname' mounted to '$mountpoint'";
} || { mdconfig -du "$loopdevice" && exit; }
}
# umount function
umount () {
# group commands
{
# container
container="$1" && \
# mdconfig loopname from container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//') && \
# eli filepath
loopcrypt="/dev/${loopdevice}.eli" && \
# zpool name from eli file
poolname=$(zdb -l "$loopcrypt" | awk -F\' '/[[:blank:]]name/ {print $2; exit;}') && \
# zfs umount poolname
printf "%s\n" "- zfs unmounting '$poolname'" && \
zfs umount "$poolname" && \
# zpool export poolname
printf "%s\n" "- zpool exporting '$poolname'" && \
zpool export "$poolname" && \
sleep 1 && \
# geli detach
printf "%s\n" "- geli detaching '$loopcrypt'" && \
geli detach "$loopcrypt" && \
# mdconfig remove md file
printf "%s\n" "- mdconfig clearing '$loopdevice'" && \
mdconfig -du "$loopdevice" && \
printf "%s\n" "- unmounted device";
} || { printf "%s\n" 'container not mounted' && exit; }
}
# check if mount is first argument
# + 2nd argument shuld be -f for the file to mount
# + 3rd argument should be the path to the file to mount
# + 4th argunent should be -k for key
# + 5th argument should be the path to the keyfile
# check if umount is first argument
# + 2nd argument shuld be -f for the file to unmount
# + 3rd argument should be the path to the file to unmount
# check arguments
if [[ "$1" =~ ^mount$ && $# -eq 5 ]]; then
# group commands
{
[[ "$2" =~ '-f' ]] && \
[[ -f "$3" ]] && \
[[ "$4" =~ '-k' ]] && \
[[ -f "$5" ]];
} || { printf "%s\n" "$script_usage" && exit; }
# mount function pass conatainer and key to function
mount "$3" "$5"
elif [[ "$1" =~ ^umount$ && $# -eq 3 ]]; then
# group commands
{
[[ "$2" =~ '-f' ]] && \
[[ -f "$3" ]];
} || { printf "%s\n" "$script_usage" && exit; }
# umount function pass container to function
umount "$3"
else
printf "%s\n" "$script_usage"
fi
ossuary bash version on githib
Install ossuary script
* create a bin directory in your home directory
Bash:
mkdir -p ~/bin
* change permissions
Bash:
chmod 700 ~/bin
* copy the ossuary script to your ~/bin directory
make the ossuary script executable
Bash:
chmod u+x ~/bin/ossuary
* edit your bashrc and add your bin directory to your bash path
Bash:
vim ~/.bashrc
add the code below to your bashrc
Bash:
# home bin
if [ -d "$HOME/bin" ]; then
PATH="$HOME/bin:$PATH"
fi
* source your bashrc file
Bash:
source ~/.bashrc
What the script outputs in the terminal when you mount a geli encrypted container
Bash:
sudo ossuary mount -f ~/documents/disk.img -k ~/.ossuary/ossuary.key
Password:
+ mdconfig creating vnode for '/home/username/documents/disk.img'
+ geli attaching '/home/username/.ossuary/ossuary.key' key to '/home/username/documents/disk.img' file
Enter passphrase:
+ zpool importing 'crypt'
+ 'crypt' mounted to '/usr/home/username/mnt'
* first you are prompted for your sudo passsword
the script then shows that it is creating a vnode for your geli container, it will display your username and not the actual word username
then the script shows the path for the geli key and the path to the geli container
you are then prompted for the geli key password
the script then shows it is importing the zfs pool name
and the pool is then mounted to the location of the zfs mount point you set on the geli container
What the script outputs in the terminal when you umount a geli encrypted container
Bash:
sudo ossuary umount -f ~/documents/disk.img
Password:
- zfs unmounting 'crypt'
- zpool exporting 'crypt'
- geli detaching '/dev/md0.eli'
- mdconfig clearing 'md0'
- unmounted device
The script prompts you for your sudo password and then provides feedback on umounting the zfs pool,
exporting the zfs pool, detatching the geli file and using mdconfig to clear the md0 file
If you enter the wrong geli password the script will exit and automatically use mdconfig to clear the md0 file
Next you need to create the geli encrypted container as outlined below before you can use the script
Set up geli encrypted conatiner
Create geli encrypted container
Load geli Support
Support for geli is available as a loadable kernel module. To configure the system to automatically load the module at boot time, add the following line to /boot/loader.conf:
Bash:
geom_eli_load="YES"
create virtual container with dd
create a 2 gig container with dd on the Desktop called disk.img
* change directory to the Desktop
Bash:
cd ~/Desktop
switch to root
Bash:
sudo su
* use dd to create a 2 gig disk image
Bash:
dd if=/dev/zero of=disk.img bs=1M count=2048
* mount the image with mdconfig
Bash:
mdconfig -a -t vnode -f disk.img -u 0
Here, the -a option forces the disk mounting, -t vnode is used for opening a regular file, and the path of this file is specified after -f. The -u 0 option set the virtual disk identifier to use, in this case /dev/md0.
* Generate the Master Key
create directory to store geli key
Bash:
mkdir ~/.ossuary
Now we want to create a key for GELI to encrypt with, and attach it to our disk image device:
replace username with your username
Bash:
cd ~/Desktop
Add the location of your geli key
Bash:
dd if=/dev/zero of=/usr/home/username/.ossuary/ossuary.key bs=256 count=1
geli init -e aes -l 256 -s 4096 -K /usr/home/username/.ossuary/ossuary.key /dev/md0
geli attach -k /usr/home/username/.ossuary/ossuary.key /dev/md0
Enter passphrase:
Create the ZFS File System
* use dd to write random data to geli container before adding file system
Bash:
dd if=/dev/random of=/dev/md0.eli bs=1M
* To create a simple, non-redundant pool using a single disk device:
Bash:
zpool create crypt /dev/md0.eli
* add compression and duplication to the zfs pool
Bash:
zfs set compression=lz4 crypt
* zfs set mount point
create the mount point for zfs
Bash:
mkdir -p ~/mnt
change the permissions on the mount point
Bash:
chmod 700 ~/mnt
set the zfs mount point
replace username with your username
Bash:
zfs set mountpoint=/usr/home/username/mnt crypt
* change the permission on the container
replace username with your username
Bash:
chmod -R username:username ~/mnt
Finally, when you want to unmount, we also want to detach from GELI and detach from md:
zfs unmount
Bash:
zfs umount crypt
* geli detach
Bash:
geli detach md0.eli
* mdconfig free loop device
Bash:
mdconfig -d -u 0
manual mounting and unmounting
* mount
use mdconfig to mount the encrypted container to /dev/md0
Bash:
mdconfig -a -t vnode -f disk.img -u 0
* use geli with the path to the key and device
replace username with your username
Bash:
geli attach -k /usr/home/username/.ossuary/ossuary.key /dev/md0
* we need to import the zpool which will also mount the container
Bash:
zpool import crypt
* umount
unmount the zfs pool
Bash:
zfs umount crypt
* we need to export the zfs pool before we use geli detach, otherwise geli thinks the device is busy
Bash:
zpool export crypt
* use geli to detach the encrypted device
Bash:
geli detach md0.eli
* free the loop device
Bash:
mdconfig -d -u 0
Last edited: