summary refs log blame commit diff
path: root/modules/system/boot/luksroot.nix
blob: 38dfece44beee40a3036aaab69744c95db40601f (plain) (tree)
1
2
3
4
5
6
7
8




                    

                                 
                                                        




                                                                      
                                

                                                
                     




                                                
                                                                                            

     



                                                   



             

                                        
                                
      
 

                                         
                                                                                
                      
                                                                                          
                                                                                   
 
                                                                     
 
                                                                           
         







                                        
                                                                                    




                                
                                                               




                            
                                                                                              
          










                                                                                
        
      

    
                                      
 


                                                                                
 
                                                      
                                       








                                                                                           
                                   

       

                                                                          

                                                     
    
 
{pkgs, config, ...}:

with pkgs.lib;

let
  luks = config.boot.initrd.luks;

  openCommand = { name, device, allowDiscards, ... }: ''
    # Wait for luksRoot to appear, e.g. if on a usb drive.
    # XXX: copied and adapted from stage-1-init.sh - should be
    # available as a function.
    if ! test -e ${device}; then
        echo -n "waiting 10 seconds for device ${device} to appear..."
        for try in $(seq 10); do
            sleep 1
            if test -e ${device}; then break; fi
            echo -n .
        done
        echo "ok"
    fi

    # open luksRoot and scan for logical volumes
    cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"}
  '';

  isPreLVM = f: f.preLVM;
  preLVM = filter isPreLVM luks.devices;
  postLVM = filter (f: !(isPreLVM f)) luks.devices;

in
{

  options = {
    boot.initrd.luks.enable = mkOption {
      default = false;
      description = "Obsolete.";
    };

    boot.initrd.luks.devices = mkOption {
      default = [ ];
      example = [ { name = "luksroot"; device = "/dev/sda3"; preLVM = true; } ];
      description = ''
        The list of devices that should be decrypted using LUKS before trying to mount the
        root partition. This works for both LVM-over-LUKS and LUKS-over-LVM setups.

        The devices are decrypted to the device mapper names defined.

        Make sure that initrd has the crypto modules needed for decryption.
      '';

      type = types.list types.optionSet;

      options = {

        name = mkOption {
          example = "luksroot";
          type = types.string;
          description = "Named to be used for the generated device in /dev/mapper.";
        };

        device = mkOption {
          example = "/dev/sda2";
          type = types.string;
          description = "Path of the underlying block device.";
        };

        preLVM = mkOption {
          default = true;
          type = types.bool;
          description = "Whether the luksOpen will be attempted before LVM scan or after it.";
        };

        allowDiscards = mkOption {
          default = false;
          type = types.bool;
          description = ''
            Whether to allow TRIM requests to the underlying device. This option
            has security implications, please read the LUKS documentation before
            activating in.
          '';
        };

      };
    };
  };

  config = mkIf (luks.devices != []) {

    # Some modules that may be needed for mounting anything ciphered
    boot.initrd.kernelModules = [ "aes_generic" "aes_x86_64" "dm_mod" "dm_crypt"
      "sha256_generic" "cbc" "cryptd" ];

    # copy the cryptsetup binary and it's dependencies
    boot.initrd.extraUtilsCommands = ''
      cp -pdv ${pkgs.cryptsetup}/sbin/cryptsetup $out/bin
      # XXX: do we have a function that does this?
      for lib in $(ldd $out/bin/cryptsetup |grep '=>' |grep /nix/store/ |cut -d' ' -f3); do
        cp -pdvn $lib $out/lib
        cp -pvn $(readlink -f $lib) $out/lib
      done
    '';

    boot.initrd.extraUtilsCommandsTest = ''
      $out/bin/cryptsetup --version
    '';

    boot.initrd.preLVMCommands = concatMapStrings openCommand preLVM;
    boot.initrd.postDeviceCommands = concatMapStrings openCommand postLVM;

    environment.systemPackages = [ pkgs.cryptsetup ];
  };
}