cleanup gocryptfs mounting

there's possibly some latent issues. i think my changes to the gocryptfs
package *might* not be necessary: if you work via the fuse front-door,
it's a lot harder to get it into these weird places.
This commit is contained in:
2022-12-28 09:30:29 +00:00
parent 121936620a
commit 8e5ca11259
5 changed files with 74 additions and 38 deletions

View File

@@ -58,19 +58,8 @@
}; };
# enable zsh completions # enable zsh completions
environment.pathsToLink = [ "/share/zsh" ]; environment.pathsToLink = [ "/share/zsh" ];
environment.systemPackages = with pkgs; [
# required for pam_mount
gocryptfs
];
# link debug symbols into /run/current-system/sw/lib/debug # link debug symbols into /run/current-system/sw/lib/debug
# hopefully picked up by gdb automatically? # hopefully picked up by gdb automatically?
environment.enableDebugInfo = true; environment.enableDebugInfo = true;
security.pam.mount.enable = true;
# security.pam.mount.debugLevel = 1;
# security.pam.enableSSHAgentAuth = true; # ??
# needed for `allow_other` in e.g. gocryptfs mounts
# or i guess going through mount.fuse sets suid so that's not necessary?
# programs.fuse.userAllowOther = true;
} }

View File

@@ -54,24 +54,41 @@ in
shell = pkgs.zsh; shell = pkgs.zsh;
openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users; openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users;
# some other nix pam users:
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.nix>
# - <https://github.com/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
pamMount = { pamMount = {
# mount encrypted stuff at login # mount encrypted stuff at login
# requires that login password == fs encryption password # requires that login password == fs encryption password
# fstype = "fuse"; fstype = "fuse";
path = "gocryptfs#/nix/persist/home/colin/private";
# path = "${pkgs.gocryptfs}/bin/gocryptfs#/nix/persist/home/colin/private"; # path = "${pkgs.gocryptfs}/bin/gocryptfs#/nix/persist/home/colin/private";
fstype = "fuse.gocryptfs"; # fstype = "fuse.gocryptfs";
path = "/nix/persist/home/colin/private"; # path = "/nix/persist/home/colin/private";
mountpoint = "/home/colin/private"; mountpoint = "/home/colin/private";
options="nodev,nosuid,quiet,allow_other"; # without allow_other, *root* isn't allowed to list anything in ~/private.
# which is weird (root can just `su colin`), but probably doesn't *hurt* anything -- right?
options="nodev,nosuid,quiet"; # allow_other
}; };
}; };
# required for PAM to find gocryptfs
security.pam.mount.additionalSearchPaths = [ pkgs.gocryptfs ];
security.pam.mount.enable = true;
# security.pam.mount.debugLevel = 1;
# security.pam.enableSSHAgentAuth = true; # ??
# needed for `allow_other` in e.g. gocryptfs mounts
# or i guess going through mount.fuse sets suid so that's not necessary?
# programs.fuse.userAllowOther = true;
sane.impermanence.home-dirs = [ sane.impermanence.home-dirs = [
# cache is probably too big to fit on the tmpfs # cache is probably too big to fit on the tmpfs
# TODO: we could bind-mount it to something which gets cleared per boot, though. # TODO: we could bind-mount it to something which gets cleared per boot, though.
".cache" ".cache"
".cargo" ".cargo"
".rustup" ".rustup"
# TODO: move this to ~/private!
".local/share/keyrings" ".local/share/keyrings"
]; ];

View File

@@ -2,9 +2,14 @@
lib.mkIf config.sane.home-manager.enable lib.mkIf config.sane.home-manager.enable
{ {
# we don't need to full zsh dir -- just the history file -- sane.impermanence.home-dirs = [
# but zsh will sometimes backup the history file and we get fewer errors if we do proper mounts instead of symlinks. # we don't need to full zsh dir -- just the history file --
sane.impermanence.home-dirs = [ ".local/share/zsh" ]; # but zsh will sometimes backup the history file and we get fewer errors if we do proper mounts instead of symlinks.
# TODO: should be private?
".local/share/zsh"
# cache gitstatus otherwise p10k fetched it from the net EVERY BOOT
".cache/gitstatus"
];
home-manager.users.colin.programs.zsh = { home-manager.users.colin.programs.zsh = {
enable = true; enable = true;

View File

@@ -114,26 +114,46 @@ in
}) })
(lib.mkIf cfg.encrypted-clear-on-boot { (lib.mkIf cfg.encrypted-clear-on-boot {
system.activationScripts.mountEncryptedClearedOnBoot.text = let # without this, we get `fusermount: fuse device not found, try 'modprobe fuse' first`.
gocryptfs = "${pkgs.gocryptfs}/bin/gocryptfs"; # - that only happens after a activation-via-boot -- not activation-after-rebuild-switch.
backing = "/nix/persist/crypt/cleared-on-boot"; # it seems likely that systemd loads `fuse` by default. see:
mountpt = encrypted-clear-on-boot-base; # - </etc/systemd/system/sysinit.target.wants/sys-fs-fuse-connections.mount>
# - triggers: /etc/systemd/system/modprobe@.service
# - calls `modprobe`
# note: even `boot.kernelModules = ...` isn't enough: that option creates /etc/modules-load.d/, which is ingested only by systemd.
# note: `boot.initrd.availableKernelModules` ALSO isn't enough: idk why.
boot.initrd.kernelModules = [ "fuse" ];
system.activationScripts.mountEncryptedClearedOnBoot =
let
pass-template = "/tmp/encrypted-clear-on-boot.XXXXXXXX"; pass-template = "/tmp/encrypted-clear-on-boot.XXXXXXXX";
tmpdir = "/tmp/impermanence"; tmpdir = "/tmp/impermanence";
in '' script = pkgs.writeShellApplication {
if !(test -e ${mountpt}/init) name = "mountEncryptedClearedOnBoot";
then runtimeInputs = with pkgs; [ fuse gocryptfs ];
mkdir -p ${backing} ${mountpt} ${tmpdir} text = ''
rm -rf ${backing}/* backing="$1"
passfile=$(mktemp ${pass-template}) mountpt="$2"
dd if=/dev/random bs=128 count=1 | base64 --wrap=0 > $passfile if ! test -e "$mountpt"/init
${gocryptfs} -quiet -passfile $passfile -init ${backing} then
${gocryptfs} -quiet -passfile $passfile ${backing} ${mountpt} mkdir -p "$backing" "$mountpt" ${tmpdir}
rm $passfile rm -rf "''${backing:?}"/*
unset passfile passfile=$(mktemp ${pass-template})
touch ${mountpt}/init dd if=/dev/random bs=128 count=1 | base64 --wrap=0 > "$passfile"
fi gocryptfs -quiet -passfile "$passfile" -init "$backing"
''; mount.fuse "gocryptfs#$backing" "$mountpt" -o nodev,nosuid,allow_other,passfile="$passfile"
# mount -t fuse.gocryptfs -o passfile="$passfile" "$backing" "$mountpt"
# gocryptfs -quiet -passfile "$passfile" "$backing" "$mountpt"
rm "$passfile"
unset passfile
touch "$mountpt"/init
fi
'';
};
in {
deps = [ "modprobe" ];
text = ''${script}/bin/mountEncryptedClearedOnBoot /nix/persist/crypt/cleared-on-boot "${encrypted-clear-on-boot-base}"'';
};
system.activationScripts.createPersistentStorageDirs.deps = [ "mountEncryptedClearedOnBoot" ]; system.activationScripts.createPersistentStorageDirs.deps = [ "mountEncryptedClearedOnBoot" ];
}) })

View File

@@ -1,4 +1,4 @@
{ gocryptfs, fuse, util-linux, lib }: { fuse, gocryptfs, util-linux, lib }:
(gocryptfs.overrideAttrs (upstream: { (gocryptfs.overrideAttrs (upstream: {
# XXX `su colin` hangs when pam_mount tries to mount a gocryptfs system # XXX `su colin` hangs when pam_mount tries to mount a gocryptfs system
@@ -7,9 +7,14 @@
# propagating util-linux through either `environment.systemPackages` or `security.pam.mount.additionalSearchPaths` DOES NOT WORK. # propagating util-linux through either `environment.systemPackages` or `security.pam.mount.additionalSearchPaths` DOES NOT WORK.
# #
# TODO: see about upstreaming this # TODO: see about upstreaming this
#
# additionally, we need /run/wrappers/bin EXPLICITLY in PATH, for when we run not as root.
# but we want to keep `fuse` for when we ARE running as root -- particularly during an activation script BEFORE the wrappers exist.
postInstall = '' postInstall = ''
wrapProgram $out/bin/gocryptfs \ wrapProgram $out/bin/gocryptfs \
--suffix PATH : ${lib.makeBinPath [ fuse util-linux ]} --suffix PATH : ${lib.makeBinPath [ util-linux ]} \
--suffix PATH : /run/wrappers/bin \
--suffix PATH : ${lib.makeBinPath [ fuse ]}
ln -s $out/bin/gocryptfs $out/bin/mount.fuse.gocryptfs ln -s $out/bin/gocryptfs $out/bin/mount.fuse.gocryptfs
''; '';
})) }))