1{ config, lib, pkgs, utils, ... }:
2
3with lib;
4
5let
6
7 bootFs = filterAttrs (n: fs: (fs.fsType == "bcachefs") && (utils.fsNeededForBoot fs)) config.fileSystems;
8
9 commonFunctions = ''
10 prompt() {
11 local name="$1"
12 printf "enter passphrase for $name: "
13 }
14 tryUnlock() {
15 local name="$1"
16 local path="$2"
17 if bcachefs unlock -c $path > /dev/null 2> /dev/null; then # test for encryption
18 prompt $name
19 until bcachefs unlock $path 2> /dev/null; do # repeat until successfully unlocked
20 printf "unlocking failed!\n"
21 prompt $name
22 done
23 printf "unlocking successful.\n"
24 fi
25 }
26 '';
27
28 openCommand = name: fs:
29 let
30 # we need only unlock one device manually, and cannot pass multiple at once
31 # remove this adaptation when bcachefs implements mounting by filesystem uuid
32 # also, implement automatic waiting for the constituent devices when that happens
33 # bcachefs does not support mounting devices with colons in the path, ergo we don't (see #49671)
34 firstDevice = head (splitString ":" fs.device);
35 in
36 ''
37 tryUnlock ${name} ${firstDevice}
38 '';
39
40in
41
42{
43 config = mkIf (elem "bcachefs" config.boot.supportedFilesystems) (mkMerge [
44 {
45 # We do not want to include bachefs in the fsPackages for systemd-initrd
46 # because we provide the unwrapped version of mount.bcachefs
47 # through the extraBin option, which will make it available for use.
48 system.fsPackages = lib.optional (!config.boot.initrd.systemd.enable) pkgs.bcachefs-tools;
49 environment.systemPackages = lib.optional (config.boot.initrd.systemd.enable) pkgs.bcachefs-tools;
50
51 # use kernel package with bcachefs support until it's in mainline
52 boot.kernelPackages = pkgs.linuxPackages_testing_bcachefs;
53 }
54
55 (mkIf ((elem "bcachefs" config.boot.initrd.supportedFilesystems) || (bootFs != {})) {
56 # chacha20 and poly1305 are required only for decryption attempts
57 boot.initrd.availableKernelModules = [ "bcachefs" "sha256" "chacha20" "poly1305" ];
58
59 boot.initrd.systemd.extraBin = {
60 "bcachefs" = "${pkgs.bcachefs-tools}/bin/bcachefs";
61 "mount.bcachefs" = pkgs.runCommand "mount.bcachefs" {} ''
62 cp -pdv ${pkgs.bcachefs-tools}/bin/.mount.bcachefs.sh-wrapped $out
63 '';
64 };
65
66 boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) ''
67 copy_bin_and_libs ${pkgs.bcachefs-tools}/bin/bcachefs
68 '';
69 boot.initrd.extraUtilsCommandsTest = ''
70 $out/bin/bcachefs version
71 '';
72
73 boot.initrd.postDeviceCommands = commonFunctions + concatStrings (mapAttrsToList openCommand bootFs);
74 })
75 ]);
76}