at 25.11-pre 7.0 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.security.pam.mount; 9 10 oflRequired = cfg.logoutHup || cfg.logoutTerm || cfg.logoutKill; 11 12 fake_ofl = pkgs.writeShellScriptBin "fake_ofl" '' 13 SIGNAL=$1 14 MNTPT=$2 15 ${pkgs.lsof}/bin/lsof | ${pkgs.gnugrep}/bin/grep $MNTPT | ${pkgs.gawk}/bin/awk '{print $2}' | ${pkgs.findutils}/bin/xargs ${pkgs.util-linux}/bin/kill -$SIGNAL 16 ''; 17 18 anyPamMount = lib.any (svc: svc.enable && svc.pamMount) ( 19 lib.attrValues config.security.pam.services 20 ); 21in 22 23{ 24 options = { 25 26 security.pam.mount = { 27 enable = lib.mkOption { 28 type = lib.types.bool; 29 default = false; 30 description = '' 31 Enable PAM mount system to mount filesystems on user login. 32 ''; 33 }; 34 35 extraVolumes = lib.mkOption { 36 type = lib.types.listOf lib.types.str; 37 default = [ ]; 38 description = '' 39 List of volume definitions for pam_mount. 40 For more information, visit <https://pam-mount.sourceforge.net/pam_mount.conf.5.html>. 41 ''; 42 }; 43 44 additionalSearchPaths = lib.mkOption { 45 type = lib.types.listOf lib.types.package; 46 default = [ ]; 47 example = lib.literalExpression "[ pkgs.bindfs ]"; 48 description = '' 49 Additional programs to include in the search path of pam_mount. 50 Useful for example if you want to use some FUSE filesystems like bindfs. 51 ''; 52 }; 53 54 cryptMountOptions = lib.mkOption { 55 type = lib.types.listOf lib.types.str; 56 default = [ ]; 57 example = lib.literalExpression '' 58 [ "allow_discard" ] 59 ''; 60 description = '' 61 Global mount options that apply to every crypt volume. 62 You can define volume-specific options in the volume definitions. 63 ''; 64 }; 65 66 fuseMountOptions = lib.mkOption { 67 type = lib.types.listOf lib.types.str; 68 default = [ ]; 69 example = lib.literalExpression '' 70 [ "nodev" "nosuid" "force-user=%(USER)" "gid=%(USERGID)" "perms=0700" "chmod-deny" "chown-deny" "chgrp-deny" ] 71 ''; 72 description = '' 73 Global mount options that apply to every FUSE volume. 74 You can define volume-specific options in the volume definitions. 75 ''; 76 }; 77 78 debugLevel = lib.mkOption { 79 type = lib.types.int; 80 default = 0; 81 example = 1; 82 description = '' 83 Sets the Debug-Level. 0 disables debugging, 1 enables pam_mount tracing, 84 and 2 additionally enables tracing in mount.crypt. The default is 0. 85 For more information, visit <https://pam-mount.sourceforge.net/pam_mount.conf.5.html>. 86 ''; 87 }; 88 89 logoutWait = lib.mkOption { 90 type = lib.types.int; 91 default = 0; 92 description = '' 93 Amount of microseconds to wait until killing remaining processes after 94 final logout. 95 For more information, visit <https://pam-mount.sourceforge.net/pam_mount.conf.5.html>. 96 ''; 97 }; 98 99 logoutHup = lib.mkOption { 100 type = lib.types.bool; 101 default = false; 102 description = '' 103 Kill remaining processes after logout by sending a SIGHUP. 104 ''; 105 }; 106 107 logoutTerm = lib.mkOption { 108 type = lib.types.bool; 109 default = false; 110 description = '' 111 Kill remaining processes after logout by sending a SIGTERM. 112 ''; 113 }; 114 115 logoutKill = lib.mkOption { 116 type = lib.types.bool; 117 default = false; 118 description = '' 119 Kill remaining processes after logout by sending a SIGKILL. 120 ''; 121 }; 122 123 createMountPoints = lib.mkOption { 124 type = lib.types.bool; 125 default = true; 126 description = '' 127 Create mountpoints for volumes if they do not exist. 128 ''; 129 }; 130 131 removeCreatedMountPoints = lib.mkOption { 132 type = lib.types.bool; 133 default = true; 134 description = '' 135 Remove mountpoints created by pam_mount after logout. This 136 only affects mountpoints that have been created by pam_mount 137 in the same session. 138 ''; 139 }; 140 }; 141 142 }; 143 144 config = lib.mkIf (cfg.enable || anyPamMount) { 145 146 environment.systemPackages = [ pkgs.pam_mount ]; 147 environment.etc."security/pam_mount.conf.xml" = { 148 source = 149 let 150 extraUserVolumes = lib.filterAttrs ( 151 n: u: u.cryptHomeLuks != null || u.pamMount != { } 152 ) config.users.users; 153 mkAttr = k: v: ''${k}="${v}"''; 154 userVolumeEntry = 155 user: 156 let 157 attrs = { 158 user = user.name; 159 path = user.cryptHomeLuks; 160 mountpoint = user.home; 161 } // user.pamMount; 162 in 163 "<volume ${lib.concatStringsSep " " (lib.mapAttrsToList mkAttr attrs)} />\n"; 164 in 165 pkgs.writeText "pam_mount.conf.xml" '' 166 <?xml version="1.0" encoding="utf-8" ?> 167 <!DOCTYPE pam_mount SYSTEM "pam_mount.conf.xml.dtd"> 168 <!-- auto generated from Nixos: modules/config/users-groups.nix --> 169 <pam_mount> 170 <debug enable="${toString cfg.debugLevel}" /> 171 <!-- if activated, requires ofl from hxtools to be present --> 172 <logout wait="${toString cfg.logoutWait}" hup="${if cfg.logoutHup then "yes" else "no"}" term="${ 173 if cfg.logoutTerm then "yes" else "no" 174 }" kill="${if cfg.logoutKill then "yes" else "no"}" /> 175 <!-- set PATH variable for pam_mount module --> 176 <path>${lib.makeBinPath ([ pkgs.util-linux ] ++ cfg.additionalSearchPaths)}</path> 177 <!-- create mount point if not present --> 178 <mkmountpoint enable="${if cfg.createMountPoints then "1" else "0"}" remove="${ 179 if cfg.removeCreatedMountPoints then "true" else "false" 180 }" /> 181 <!-- specify the binaries to be called --> 182 <!-- the comma in front of the options is necessary for empty options --> 183 <fusemount>${pkgs.fuse}/bin/mount.fuse %(VOLUME) %(MNTPT) -o ,${ 184 lib.concatStringsSep "," (cfg.fuseMountOptions ++ [ "%(OPTIONS)" ]) 185 }'</fusemount> 186 <fuseumount>${pkgs.fuse}/bin/fusermount -u %(MNTPT)</fuseumount> 187 <!-- the comma in front of the options is necessary for empty options --> 188 <cryptmount>${pkgs.pam_mount}/bin/mount.crypt -o ,${ 189 lib.concatStringsSep "," (cfg.cryptMountOptions ++ [ "%(OPTIONS)" ]) 190 } %(VOLUME) %(MNTPT)</cryptmount> 191 <cryptumount>${pkgs.pam_mount}/bin/umount.crypt %(MNTPT)</cryptumount> 192 <pmvarrun>${pkgs.pam_mount}/bin/pmvarrun -u %(USER) -o %(OPERATION)</pmvarrun> 193 ${lib.optionalString oflRequired "<ofl>${fake_ofl}/bin/fake_ofl %(SIGNAL) %(MNTPT)</ofl>"} 194 ${lib.concatStrings (map userVolumeEntry (lib.attrValues extraUserVolumes))} 195 ${lib.concatStringsSep "\n" cfg.extraVolumes} 196 </pam_mount> 197 ''; 198 }; 199 200 }; 201}