impermanence: crypt: simplify setup (experimental)

This commit is contained in:
colin 2023-01-04 09:28:59 +00:00
parent 4d9c15f9b8
commit 592d17b725

View File

@ -9,25 +9,6 @@ let
key = "/mnt/impermanence/crypt/clearedonboot.key"; key = "/mnt/impermanence/crypt/clearedonboot.key";
}; };
}; };
prepareEncryptedClearedOnBoot = pkgs.writeShellApplication {
name = "prepareEncryptedClearedOnBoot";
runtimeInputs = with pkgs; [ gocryptfs ];
text = ''
backing="$1"
passfile="$2"
if ! test -e "$passfile"
then
# if the key doesn't exist, it's probably not mounted => delete the backing dir
rm -rf "''${backing:?}"/*
# generate key. we can "safely" keep it around for the lifetime of this boot
umask 266
dd if=/dev/random bs=128 count=1 | base64 --wrap=0 > "$passfile"
umask 022
# initialize the crypt store
gocryptfs -quiet -passfile "$passfile" -init "$backing"
fi
'';
};
in in
lib.mkIf config.sane.impermanence.enable lib.mkIf config.sane.impermanence.enable
{ {
@ -36,20 +17,9 @@ lib.mkIf config.sane.impermanence.enable
stored to disk, but encrypted to an in-memory key and cleared on every boot stored to disk, but encrypted to an in-memory key and cleared on every boot
so that it's unreadable after power-off so that it's unreadable after power-off
''; '';
mountpt = "/mnt/impermanence/crypt/clearedonboot"; mountpt = store.device;
}; };
systemd.services."prepareEncryptedClearedOnBoot" = rec {
description = "prepare keys for ${store.device}";
serviceConfig.ExecStart = ''
${prepareEncryptedClearedOnBoot}/bin/prepareEncryptedClearedOnBoot ${store.underlying.path} ${store.underlying.key}
'';
serviceConfig.Type = "oneshot";
# remove implicit dep on sysinit.target
unitConfig.DefaultDependencies = "no";
};
# we need the key directory to be created before we create the key
sane.fs."/mnt/impermanence/crypt".dir.reverseDepends = [ "prepareEncryptedClearedOnBoot.service" ];
fileSystems."${store.device}" = { fileSystems."${store.device}" = {
device = store.underlying.path; device = store.underlying.path;
@ -59,9 +29,6 @@ lib.mkIf config.sane.impermanence.enable
"nosuid" "nosuid"
"allow_other" "allow_other"
"passfile=${store.underlying.key}" "passfile=${store.underlying.key}"
# this is really a 'wants' + 'after'... gocryptfs loads the key
# into ram and then doesn't need it again. but this is easy
"x-systemd.requires=prepareEncryptedClearedOnBoot.service"
"defaults" "defaults"
]; ];
noCheck = true; noCheck = true;
@ -69,8 +36,33 @@ lib.mkIf config.sane.impermanence.enable
# let sane.fs know about our fileSystem and automatically add the appropriate dependencies # let sane.fs know about our fileSystem and automatically add the appropriate dependencies
sane.fs."${store.device}".mount = {}; sane.fs."${store.device}".mount = {};
# let the fs ensure the underlying path is also created # let sane.fs know how to initialize the gocryptfs store,
sane.fs."${store.underlying.path}".dir = {}; # and that it MUST do so
sane.fs."${store.underlying.path}/gocryptfs.conf".generated = {
script.script = ''
backing="$1"
passfile="$2"
# clear the backing store
# TODO: we should verify that it's not mounted anywhere...
rm -rf "''${backing:?}"/*
${pkgs.gocryptfs}/bin/gocryptfs -quiet -passfile "$passfile" -init "$backing"
'';
script.scriptArgs = [ store.underlying.path store.underlying.key ];
# we need the key in order to initialize the store
depends = [ config.sane.fs."${store.underlying.key}".unit ];
# the store must be initialized before we can mount it
reverseDepends = [ config.sane.fs."${store.device}".unit ];
};
# let sane.fs know how to generate the key for gocryptfs
sane.fs."${store.underlying.key}".generated = {
script.script = ''
dd if=/dev/random bs=128 count=1 | base64 --wrap=0 > "$1"
'';
script.scriptArgs = [ store.underlying.key ];
# no need for anyone else to be able to read the key
acl.mode = "0400";
};
# TODO: could add this *specifically* to the .mount file for the encrypted fs? # TODO: could add this *specifically* to the .mount file for the encrypted fs?
system.fsPackages = [ pkgs.gocryptfs ]; # fuse needs to find gocryptfs system.fsPackages = [ pkgs.gocryptfs ]; # fuse needs to find gocryptfs