fix s6 service ordering: unl0kr -> (wait for mount) -> sway
note that the systemd-aware mount never completes -- it's stuck in 'activating' forever. that's the next challenge
This commit is contained in:
@@ -32,8 +32,6 @@ in
|
|||||||
wheelNeedsPassword = false;
|
wheelNeedsPassword = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
security.pam.mount.enable = true;
|
|
||||||
|
|
||||||
system.activationScripts.makeEtcShadowSandboxable = {
|
system.activationScripts.makeEtcShadowSandboxable = {
|
||||||
deps = [ "users" ];
|
deps = [ "users" ];
|
||||||
text = ''
|
text = ''
|
||||||
|
@@ -5,6 +5,61 @@ let
|
|||||||
persist-base = "/nix/persist";
|
persist-base = "/nix/persist";
|
||||||
origin = config.sane.persist.stores."private".origin;
|
origin = config.sane.persist.stores."private".origin;
|
||||||
backing = sane-lib.path.concat [ persist-base "private" ];
|
backing = sane-lib.path.concat [ persist-base "private" ];
|
||||||
|
|
||||||
|
gocryptfs-private = pkgs.writeShellApplication {
|
||||||
|
name = "mount.fuse.gocryptfs-private";
|
||||||
|
runtimeInputs = with pkgs; [
|
||||||
|
coreutils-full
|
||||||
|
gocryptfs
|
||||||
|
inotify-tools
|
||||||
|
];
|
||||||
|
text = ''
|
||||||
|
# backing=$1
|
||||||
|
# facing=$2
|
||||||
|
mountArgs=("$@")
|
||||||
|
passdir=/run/gocryptfs
|
||||||
|
passfile="$passdir/private.key"
|
||||||
|
|
||||||
|
waitForPassfileOnce() {
|
||||||
|
local timeout=$1
|
||||||
|
if [ -f "$passfile" ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
# wait for some file to be created inside the directory.
|
||||||
|
# inotifywait returns 0 if the file was created. 1 or 2 if timeout was hit or it was interrupted by a different event.
|
||||||
|
inotifywait --timeout "$timeout" --event create "$passdir"
|
||||||
|
return 1 #< maybe it was created; we'll pick that up immediately, on next check
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
waitForPassfile() {
|
||||||
|
# there's a race condition between testing the path and starting `inotifywait`.
|
||||||
|
# therefore, use a retry loop. exponential backoff to decrease the impact of the race condition,
|
||||||
|
# especially near the start of boot to allow for quick reboots even if/when i hit the race.
|
||||||
|
for timeout in 4 4 8 8 8 8 16 16 16 16 16 16 16 16; do
|
||||||
|
if waitForPassfileOnce "$timeout"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
while true; do
|
||||||
|
if waitForPassfileOnce 30; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
tryOpenStore() {
|
||||||
|
# try to open the store (blocking), if it fails, then delete the passfile because the user probably entered the wrong password
|
||||||
|
echo "mounting with ''${mountArgs[*]}"
|
||||||
|
gocryptfs -fg "''${mountArgs[@]}"
|
||||||
|
rc=$?
|
||||||
|
# should only return if the mount errored -- probably because of a password failure!
|
||||||
|
rm -f "$passfile"
|
||||||
|
return "$rc"
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForPassfile
|
||||||
|
tryOpenStore
|
||||||
|
'';
|
||||||
|
};
|
||||||
in
|
in
|
||||||
lib.mkIf config.sane.persist.enable
|
lib.mkIf config.sane.persist.enable
|
||||||
{
|
{
|
||||||
@@ -28,7 +83,7 @@ lib.mkIf config.sane.persist.enable
|
|||||||
|
|
||||||
fileSystems."${origin}" = {
|
fileSystems."${origin}" = {
|
||||||
device = backing;
|
device = backing;
|
||||||
fsType = "fuse.gocryptfs";
|
fsType = "fuse.gocryptfs-private";
|
||||||
options = [
|
options = [
|
||||||
"noauto" # don't try to mount, until the user logs in!
|
"noauto" # don't try to mount, until the user logs in!
|
||||||
"nofail"
|
"nofail"
|
||||||
@@ -39,50 +94,22 @@ lib.mkIf config.sane.persist.enable
|
|||||||
# "quiet"
|
# "quiet"
|
||||||
# "defaults" # "unknown flag: --defaults. Try 'gocryptfs -help'"
|
# "defaults" # "unknown flag: --defaults. Try 'gocryptfs -help'"
|
||||||
"passfile=/run/gocryptfs/private.key"
|
"passfile=/run/gocryptfs/private.key"
|
||||||
|
# options so that we can block for the password file *without* systemd killing us.
|
||||||
|
# see: <https://bbs.archlinux.org/viewtopic.php?pid=1906174#p1906174>
|
||||||
|
"x-systemd.mount-timeout=infinity"
|
||||||
|
# "retry=10000"
|
||||||
|
"fg"
|
||||||
];
|
];
|
||||||
noCheck = true;
|
noCheck = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# let sane.fs know about the mount, and let systemd know to wait for the pass key before attempting a mount
|
# let sane.fs know about the mount
|
||||||
sane.fs."${origin}".mount = {
|
sane.fs."${origin}".mount = {};
|
||||||
depends = let
|
|
||||||
keyfile = config.sane.fs."/run/gocryptfs/private.key";
|
|
||||||
in [ keyfile.unit ];
|
|
||||||
};
|
|
||||||
# it also needs to know that the underlying device is an ordinary folder
|
# it also needs to know that the underlying device is an ordinary folder
|
||||||
sane.fs."${backing}" = sane-lib.fs.wanted {
|
sane.fs."${backing}" = sane-lib.fs.wanted {
|
||||||
dir.acl.user = config.sane.defaultUser;
|
dir.acl.user = config.sane.defaultUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.fs."/run/gocryptfs/private.key".generated = let
|
|
||||||
script = pkgs.writeShellScript "wait-for-gocryptfs-private" ''
|
|
||||||
file="$1"
|
|
||||||
dir=$(dirname "$file")
|
|
||||||
|
|
||||||
succeedOrWait() {
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
# wait for some file to be created inside the directory.
|
|
||||||
# inotifywait returns 0 if the file was created. 1 or 2 if timeout was hit or it was interrupted by a different event.
|
|
||||||
${lib.getExe' pkgs.inotify-tools "inotifywait"} --timeout "$1" --event create "$dir" || true
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
# there's a race condition between testing the path and starting `inotifywait`.
|
|
||||||
# therefore, use a retry loop. exponential backoff to decrease the impact of the race condition,
|
|
||||||
# especially near the start of boot to allow for quick reboots even if/when i hit the race.
|
|
||||||
for i in 4 4 8 8 16 16 16 16 16 16 16 16; do
|
|
||||||
succeedOrWait "$i"
|
|
||||||
done
|
|
||||||
while true; do
|
|
||||||
succeedOrWait 30
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
command = [ "${script}" "/run/gocryptfs/private.key" ];
|
|
||||||
# no need for anyone else to be able to read the key
|
|
||||||
acl.mode = "0400";
|
|
||||||
};
|
|
||||||
sane.fs."/run/gocryptfs" = sane-lib.fs.wanted {
|
sane.fs."/run/gocryptfs" = sane-lib.fs.wanted {
|
||||||
dir.acl.user = config.sane.defaultUser;
|
dir.acl.user = config.sane.defaultUser;
|
||||||
dir.acl.mode = "0700";
|
dir.acl.mode = "0700";
|
||||||
@@ -95,12 +122,13 @@ lib.mkIf config.sane.persist.enable
|
|||||||
"${originUnit}".wantedBy = [ "local-fs.target" ];
|
"${originUnit}".wantedBy = [ "local-fs.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: could add this *specifically* to the .mount file for the encrypted fs?
|
system.fsPackages = [ gocryptfs-private ];
|
||||||
system.fsPackages = [ pkgs.gocryptfs ]; # fuse needs to find gocryptfs
|
|
||||||
|
|
||||||
sane.user.services.gocryptfs-private = {
|
sane.user.services.gocryptfs-private = {
|
||||||
description = "wait for /mnt/persist/private to be mounted";
|
description = "wait for /mnt/persist/private to be mounted";
|
||||||
startCommand = "${lib.getExe' pkgs.systemd "systemctl"} start mnt-persist-private.mount";
|
# startCommand = "${lib.getExe' pkgs.systemd "systemctl"} start mnt-persist-private.mount";
|
||||||
|
command = "sleep infinity";
|
||||||
|
readiness.waitExists = [ "/mnt/persist/private/init" ];
|
||||||
partOf = [ "private-storage" ];
|
partOf = [ "private-storage" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user