2022-12-31 10:15:08 +00:00
|
|
|
{ config, lib, pkgs, utils, ... }:
|
|
|
|
|
|
|
|
let
|
2022-12-31 12:18:27 +00:00
|
|
|
store = rec {
|
2022-12-31 10:15:08 +00:00
|
|
|
device = "/mnt/impermanence/crypt/clearedonboot";
|
|
|
|
underlying = {
|
|
|
|
path = "/nix/persist/crypt/clearedonboot";
|
|
|
|
# TODO: consider moving this to /tmp, but that requires tmp be mounted first?
|
|
|
|
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
|
2022-12-31 10:45:43 +00:00
|
|
|
umask 266
|
2022-12-31 10:15:08 +00:00
|
|
|
dd if=/dev/random bs=128 count=1 | base64 --wrap=0 > "$passfile"
|
2022-12-31 10:45:43 +00:00
|
|
|
umask 022
|
2022-12-31 10:15:08 +00:00
|
|
|
# initialize the crypt store
|
|
|
|
gocryptfs -quiet -passfile "$passfile" -init "$backing"
|
|
|
|
fi
|
|
|
|
'';
|
|
|
|
};
|
2023-01-03 07:04:49 +00:00
|
|
|
in
|
|
|
|
lib.mkIf config.sane.impermanence.enable
|
2022-12-31 10:15:08 +00:00
|
|
|
{
|
2023-01-03 07:04:49 +00:00
|
|
|
sane.impermanence.stores."cryptClearOnBoot" = {
|
2023-01-04 01:54:13 +00:00
|
|
|
storeDescription = ''
|
|
|
|
stored to disk, but encrypted to an in-memory key and cleared on every boot
|
|
|
|
so that it's unreadable after power-off
|
|
|
|
'';
|
2023-01-03 07:04:49 +00:00
|
|
|
mountpt = "/mnt/impermanence/crypt/clearedonboot";
|
|
|
|
};
|
|
|
|
|
2022-12-31 12:18:27 +00:00
|
|
|
systemd.services."prepareEncryptedClearedOnBoot" = rec {
|
2022-12-31 10:15:08 +00:00
|
|
|
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";
|
|
|
|
};
|
2023-01-04 04:22:17 +00:00
|
|
|
# we need the key directory to be created before we create the key
|
|
|
|
sane.fs."/mnt/impermanence/crypt".dir.reverseDepends = [ "prepareEncryptedClearedOnBoot.service" ];
|
2022-12-31 10:15:08 +00:00
|
|
|
|
|
|
|
fileSystems."${store.device}" = {
|
|
|
|
device = store.underlying.path;
|
|
|
|
fsType = "fuse.gocryptfs";
|
|
|
|
options = [
|
|
|
|
"nodev"
|
|
|
|
"nosuid"
|
|
|
|
"allow_other"
|
|
|
|
"passfile=${store.underlying.key}"
|
2023-01-04 04:22:17 +00:00
|
|
|
# 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"
|
2022-12-31 10:15:08 +00:00
|
|
|
"defaults"
|
|
|
|
];
|
|
|
|
noCheck = true;
|
|
|
|
};
|
2023-01-04 03:57:24 +00:00
|
|
|
# let sane.fs know about our fileSystem and automatically add the appropriate dependencies
|
|
|
|
sane.fs."${store.device}".mount = {};
|
2022-12-31 12:31:49 +00:00
|
|
|
|
2023-01-04 03:57:24 +00:00
|
|
|
# let the fs ensure the underlying path is also created
|
|
|
|
sane.fs."${store.underlying.path}".dir = {};
|
2022-12-31 10:15:08 +00:00
|
|
|
|
|
|
|
# TODO: could add this *specifically* to the .mount file for the encrypted fs?
|
2023-01-03 12:00:49 +00:00
|
|
|
system.fsPackages = [ pkgs.gocryptfs ]; # fuse needs to find gocryptfs
|
2022-12-31 10:15:08 +00:00
|
|
|
}
|