[bug#71071] services: nix: Mount Nix store read only.
Commit Message
* gnu/services/nix.scm (nix-shepherd-service): Mount Nix store read only.
(%nix-store-directory, %immutable-nix-store): New variables.
(%nix-store-prefix): New parameter.
(nix-activation): Move /nix/store provision to 'nix-shepherd-service'.
Change-Id: I18a5d58c92c1f2b5b6dcecc3d5b439cc15bf4e49
---
gnu/services/nix.scm | 47 +++++++++++++++++++++++++++++++++++++-------
1 file changed, 40 insertions(+), 7 deletions(-)
base-commit: dd03be186adb64bdb77265dfd0ad53fe50ec016e
Comments
Hello,
Oleg Pykhalov <go.wigust@gmail.com> skribis:
> * gnu/services/nix.scm (nix-shepherd-service): Mount Nix store read only.
> (%nix-store-directory, %immutable-nix-store): New variables.
> (%nix-store-prefix): New parameter.
> (nix-activation): Move /nix/store provision to 'nix-shepherd-service'.
>
> Change-Id: I18a5d58c92c1f2b5b6dcecc3d5b439cc15bf4e49
That’s a good idea. Some suggestions:
> +(define %nix-store-directory
> + "/nix/store")
> +
> +(define %nix-store-prefix
> + ;; Absolute path to the Nix store.
> + (make-parameter %nix-store-directory))
I think you can omit this parameter and simply use
‘%nix-store-directory’ because…
> +(define %immutable-nix-store
> + ;; Read-only store to avoid users or daemons accidentally modifying it.
> + ;; 'nix-daemon' has provisions to remount it read-write in its own name
> + ;; space.
> + #~(file-system
> + (device #$(%nix-store-prefix))
> + (mount-point #$(%nix-store-prefix))
… the parameter is used at the top-level anyway, so changing its value
won’t have any effect.
> (start #~(make-forkexec-constructor
> - (list (string-append #$package "/bin/nix-daemon")
> - #$@extra-options)
> + (list
> + #$(program-file
> + "nix-daemon-wrapper"
> + (with-imported-modules (source-module-closure '((gnu build file-systems)
> + (gnu system file-systems)))
> + #~(begin
> + (use-modules (gnu build file-systems)
> + (gnu system file-systems)
> + (guix build syscalls)
> + (guix build utils))
> + (unless (member #$(%nix-store-prefix) (mount-points))
> + (mkdir-p "/nix/store")
> + (chown "/nix/store"
> + (passwd:uid (getpw "root"))
> + (group:gid (getpw "nixbld01")))
> + (chmod "/nix/store" #o775)
> + (mount-file-system #$%immutable-nix-store
> + #:root "/"))
> + (execl #$(file-append package "/bin/nix-daemon")
> + "nix-daemon" #$@extra-options)))))
> #:environment-variables
> (list (string-append "TMPDIR=" #$build-directory)
> "PATH=/run/current-system/profile/bin")))
Instead of having this wrapper, what about extending
‘file-system-service-type’ with a read-only bind-mount <file-system>
similar to ‘%immutable-store’?
The Shepherd service that spawns nix-daemon would depend on that file
system:
(requirement '(user-processes file-system-/nix/store))
Thanks,
Ludo’.
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2019, 2020, 2021 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2019, 2020, 2021, 2024 Oleg Pykhalov <go.wigust@gmail.com>
;;; Copyright © 2020 Peng Mei Yu <i@pengmeiyu.com>
;;;
;;; This file is part of GNU Guix.
@@ -97,12 +97,9 @@ (define (nix-activation _)
#~(begin
(use-modules (guix build utils)
(srfi srfi-26))
- (for-each (cut mkdir-p <>) '("/nix/store" "/nix/var/log"
+ (for-each (cut mkdir-p <>) '("/nix/var/log"
"/nix/var/nix/gcroots/per-user"
"/nix/var/nix/profiles/per-user"))
- (chown "/nix/store"
- (passwd:uid (getpw "root")) (group:gid (getpw "nixbld01")))
- (chmod "/nix/store" #o775)
(for-each (cut chmod <> #o777) '("/nix/var/nix/profiles"
"/nix/var/nix/profiles/per-user"))))
@@ -129,6 +126,24 @@ (define nix-service-etc
'#$build-sandbox-items))
(for-each (cut display <>) '#$extra-config)))))))))))
+(define %nix-store-directory
+ "/nix/store")
+
+(define %nix-store-prefix
+ ;; Absolute path to the Nix store.
+ (make-parameter %nix-store-directory))
+
+(define %immutable-nix-store
+ ;; Read-only store to avoid users or daemons accidentally modifying it.
+ ;; 'nix-daemon' has provisions to remount it read-write in its own name
+ ;; space.
+ #~(file-system
+ (device #$(%nix-store-prefix))
+ (mount-point #$(%nix-store-prefix))
+ (type "none")
+ (check? #f)
+ (flags '(read-only bind-mount))))
+
(define nix-shepherd-service
;; Return a <shepherd-service> for Nix.
(match-lambda
@@ -139,8 +154,26 @@ (define nix-shepherd-service
(documentation "Run nix-daemon.")
(requirement '())
(start #~(make-forkexec-constructor
- (list (string-append #$package "/bin/nix-daemon")
- #$@extra-options)
+ (list
+ #$(program-file
+ "nix-daemon-wrapper"
+ (with-imported-modules (source-module-closure '((gnu build file-systems)
+ (gnu system file-systems)))
+ #~(begin
+ (use-modules (gnu build file-systems)
+ (gnu system file-systems)
+ (guix build syscalls)
+ (guix build utils))
+ (unless (member #$(%nix-store-prefix) (mount-points))
+ (mkdir-p "/nix/store")
+ (chown "/nix/store"
+ (passwd:uid (getpw "root"))
+ (group:gid (getpw "nixbld01")))
+ (chmod "/nix/store" #o775)
+ (mount-file-system #$%immutable-nix-store
+ #:root "/"))
+ (execl #$(file-append package "/bin/nix-daemon")
+ "nix-daemon" #$@extra-options)))))
#:environment-variables
(list (string-append "TMPDIR=" #$build-directory)
"PATH=/run/current-system/profile/bin")))