summaryrefslogtreecommitdiff
path: root/sigils/system/mapped-devices.scm
blob: ac5c00186dd5f16d34b77c2bd8b1ce35d6182b71 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
(define-module (sigils system mapped-devices)
  #:use-module (guix gexp)
  ;; #:use-module (guix records)
  ;; #:use-module ((guix modules) #:hide (file-name->module-name))
  ;; #:use-module (guix i18n)
  ;; #:use-module ((guix diagnostics)
  ;;               #:select (source-properties->location
  ;;                         formatted-message
  ;;                         &fix-hint
  ;;                         &error-location))
  ;; #:use-module (guix deprecation)
  ;; #:use-module (gnu services)
  ;; #:use-module (gnu services shepherd)
  ;; #:use-module (gnu system uuid)
  ;; #:autoload   (gnu build file-systems) (find-partition-by-luks-uuid)
  ;; #:autoload   (gnu build linux-modules)
  ;; (missing-modules)
  ;; #:autoload   (gnu packages cryptsetup) (cryptsetup-static)
  ;; #:autoload   (gnu packages linux) (mdadm-static lvm2-static)
  ;; #:use-module (srfi srfi-1)
  ;; #:use-module (srfi srfi-26)
  ;; #:use-module (srfi srfi-34)
  ;; #:use-module (srfi srfi-35)
  #:use-module (ice-9 match)
  ;; #:use-module (ice-9 format)
  #:export (luks-device-mapping-with-options))

;;;
;;; Common device mappings.
;;;

(define* (open-luks-device source targets #:key key-file allow-discards?)
  "Return a gexp that maps SOURCE to TARGET as a LUKS device, using
'cryptsetup'."
  (with-imported-modules (source-module-closure
                          '((gnu build file-systems)
                            (guix build utils))) ;; For mkdir-p
    (match targets
      ((target)
       #~(let ((source #$(if (uuid? source)
                             (uuid-bytevector source)
                             source))
               (keyfile #$key-file))

           ;; Create '/run/cryptsetup/' if it does not exist, as device locking
           ;; is mandatory for LUKS2.
           (mkdir-p "/run/cryptsetup/")

           ;; Use 'cryptsetup-static', not 'cryptsetup', to avoid pulling the
           ;; whole world inside the initrd (for when we're in an initrd).
           ;; 'cryptsetup open' requires standard input t #f)o be a tty to allow
           ;; for interaction but shepherd sets standard input to /dev/null;
           ;; thus, explicitly request a tty.
           (let ((partition
                  ;; Note: We cannot use the "UUID=source" syntax here
                  ;; because 'cryptsetup' implements it by searching the
                  ;; udev-populated /dev/disk/by-id directory but udev may
                  ;; be unavailable at the time we run this.
                  (if (bytevector? source)
                      (or (let loop ((tries-left 10))
                            (and (positive? tries-left)
                                 (or (find-partition-by-luks-uuid source)
                                     ;; If the underlying partition is
                                     ;; not found, try again after
                                     ;; waiting a second, up to ten
                                     ;; times.  FIXME: This should be
                                     ;; dealt with in a more robust way.
                                     (begin (sleep 1)
                                            (loop (- tries-left 1))))))
                          (error "LUKS partition not found" source))
                      source)))
             ;; We want to fallback to the password unlock if the keyfile fails.
             (or (and keyfile
                      (zero? (system*/tty
                              #$(file-append cryptsetup-static "/sbin/cryptsetup")
                              "open" "--type" "luks" (if allow-discards? "--allow-discards")
                              "--key-file" keyfile
                              partition #$target)))
                 (zero? (system*/tty
                         #$(file-append cryptsetup-static "/sbin/cryptsetup")
                         "open" "--type" "luks" (if allow-discards? "--allow-discards")
                         partition #$target)))))))))

(define* (luks-device-mapping-with-options #:key key-file allow-discards?)
  "Return a luks-device-mapping object with open modified to pass the arguments
into the open-luks-device procedure."
  ((@@ (gnu system mapped-devices) mapped-device-kind)
   (inherit (@@ (gnu system mapped-devices) luks-device-mapping))
   (open (λ (source targets)
           (open-luks-device source targets
                             #:key-file key-file
                             #:allow-discards? allow-discards?)))))