summaryrefslogtreecommitdiff
path: root/gnu/services/linux.scm
diff options
context:
space:
mode:
authorEdouard Klein <edk@beaver-labs.com>2025-07-25 11:01:36 +0200
committerMaxim Cournoyer <maxim@guixotic.coop>2025-07-25 23:36:10 +0900
commitf05f8fb6b4e6982cd12db4c943deae95e5692924 (patch)
treeac84ee77530f452cba26defac67a4d03c0ef42a5 /gnu/services/linux.scm
parent8636c0910fa201f5f9f10cd10cfe8e98abf707a5 (diff)
services: Add vfs-mapping-service-type.
* gnu/services/linux.scm (vfs-mapping-service-type, vfs-mapping-configuration, vfs-mapping-binding): New variables. * doc/guix.texi: (Vfs Mapping Service): New subsubsection under "Linux Services". Change-Id: I7ebd48afb809ded9fa6fe9eb80c618accb856716 Signed-off-by: Maxim Cournoyer <maxim@guixotic.coop>
Diffstat (limited to 'gnu/services/linux.scm')
-rw-r--r--gnu/services/linux.scm164
1 files changed, 162 insertions, 2 deletions
diff --git a/gnu/services/linux.scm b/gnu/services/linux.scm
index d7aee1b82e1..80c35717a92 100644
--- a/gnu/services/linux.scm
+++ b/gnu/services/linux.scm
@@ -7,6 +7,7 @@
7;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz> 7;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz>
8;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu> 8;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
9;;; Copyright © 2023 Felix Lechner <felix.lechner@lease-up.com> 9;;; Copyright © 2023 Felix Lechner <felix.lechner@lease-up.com>
10;;; Copyright © 2025 Edouard Klein <edk@beaver-labs.com>
10;;; 11;;;
11;;; This file is part of GNU Guix. 12;;; This file is part of GNU Guix.
12;;; 13;;;
@@ -36,6 +37,7 @@
36 #:use-module (gnu services configuration) 37 #:use-module (gnu services configuration)
37 #:use-module (gnu services shepherd) 38 #:use-module (gnu services shepherd)
38 #:use-module (gnu packages linux) 39 #:use-module (gnu packages linux)
40 #:use-module (gnu packages file-systems)
39 #:use-module (srfi srfi-1) 41 #:use-module (srfi srfi-1)
40 #:use-module (srfi srfi-26) 42 #:use-module (srfi srfi-26)
41 #:use-module (srfi srfi-34) 43 #:use-module (srfi srfi-34)
@@ -101,7 +103,11 @@
101 zram-device-configuration-compression-algorithm 103 zram-device-configuration-compression-algorithm
102 zram-device-configuration-memory-limit 104 zram-device-configuration-memory-limit
103 zram-device-configuration-priority 105 zram-device-configuration-priority
104 zram-device-service-type)) 106 zram-device-service-type
107
108 vfs-mapping-service-type
109 vfs-mapping-configuration
110 vfs-mapping))
105 111
106 112
107;;; 113;;;
@@ -547,7 +553,6 @@ the Linux @code{cachefiles} module.")
547;;; 553;;;
548;;; Zram device 554;;; Zram device
549;;; 555;;;
550
551(define-record-type* <zram-device-configuration> 556(define-record-type* <zram-device-configuration>
552 zram-device-configuration make-zram-device-configuration 557 zram-device-configuration make-zram-device-configuration
553 zram-device-configuration? 558 zram-device-configuration?
@@ -628,3 +633,158 @@ placed in a udev rules file."
628 (service-extension udev-service-type 633 (service-extension udev-service-type
629 (compose list zram-device-udev-rule)))) 634 (compose list zram-device-udev-rule))))
630 (description "Creates a zram swap device."))) 635 (description "Creates a zram swap device.")))
636
637
638;;;
639;;; VFS Mapping.
640;;;
641
642(define-record-type* <vfs-mapping>
643 vfs-mapping make-vfs-mapping
644 vfs-mapping?
645 (source vfs-mapping-source)
646 (destination vfs-mapping-destination)
647 (policy vfs-mapping-policy
648 (default 'translate))
649 (user vfs-mapping-user
650 (default #f))
651 (group vfs-mapping-group
652 (default "users"))
653 (name vfs-mapping-name
654 (default (string-append
655 (vfs-mapping-source this-record) "-["
656 (vfs-mapping-policy this-record) "]->"
657 (vfs-mapping-destination this-record)))
658 (thunked))
659 (requirement vfs-mapping-requirement
660 (default '(file-systems user-homes))))
661
662(define (vfs-mapping-policy? x)
663 (and (symbol? x)
664 (or (memq x '(bind translate overlay)))))
665
666(define (path-like? x)
667 (or (string? x)
668 (file-like? x)
669 (gexp? x)))
670
671(define (valid-vfs-mapping? x)
672 ;; User must be set iff we are going to use it
673 (and (vfs-mapping? x)
674 (path-like? (vfs-mapping-source x))
675 (path-like? (vfs-mapping-destination x))
676 (string? (vfs-mapping-name x))
677 (vfs-mapping-policy? (vfs-mapping-policy x))
678 (cond
679 ((eq? (vfs-mapping-policy x) 'bind)
680 (not (vfs-mapping-user x)))
681 (#t
682 (and (string? (vfs-mapping-user x))
683 (string? (vfs-mapping-group x)))))))
684
685(define list-of-vfs-mapping? (list-of valid-vfs-mapping?))
686
687(define-configuration/no-serialization vfs-mapping-configuration
688 (bindfs (gexp #~(string-append #$bindfs "/bin/bindfs"))
689 "The bindfs command to use.")
690 (fusermount (gexp #~(string-append #$fuse-2 "/bin/fusermount"))
691 "The fusermount command to use.")
692 (umount (gexp #~(string-append #$util-linux+udev "/bin/umount"))
693 "The umount command to use.")
694 (bindings (list-of-vfs-mapping '())
695 "The list of bindings to mount"))
696
697(define vfs-mapping-shepherd-services
698 (match-record-lambda <vfs-mapping-configuration>
699 (fusermount bindfs umount bindings)
700 (map
701 (match-record-lambda <vfs-mapping>
702 (source destination policy user group name requirement)
703 (shepherd-service
704 ;; Each binding has its own service
705 (provision (list (string->symbol name)))
706 ;; Make sure the homes are already present
707 (requirement requirement)
708 (stop
709 #~(lambda args
710 (match (quote #$policy)
711 ('bind (invoke #$umount #$destination))
712 ('translate (invoke #$fusermount "-u" #$destination))
713 ('overlay (begin
714 ;; First the bindfs
715 (invoke #$fusermount "-u" #$destination)
716 ;; then the overlay
717 (invoke #$umount #$destination))))
718 #f))
719 (start
720 #~(lambda args
721 (define (mkdir-recursively dir user group)
722 ;; Like mkdir-p, but chown all created directories to the
723 ;; specified user.
724 (unless (eq? dir "/")
725 (when (not (file-exists? dir))
726 (mkdir-recursively (dirname dir) user group)
727 (mkdir dir)
728 (let* ((pw (getpw user))
729 (uid (passwd:uid pw))
730 (gid (passwd:gid pw)))
731 (chown dir uid gid)))))
732 (mkdir-recursively #$destination #$user #$group)
733 (let* ((stat (stat #$source))
734 (uid (stat:uid stat))
735 (gid (stat:gid stat))
736 (source-user (passwd:name (getpwuid uid)))
737 (source-group (group:name (getgrgid gid))))
738 (match (quote #$policy)
739 ('bind
740 (mount #$source #$destination
741 #f ;type
742 MS_BIND)) ;flags (bind mount)
743 ('translate
744 (invoke
745 #$bindfs
746 (string-append "--create-for-group=" source-group)
747 (string-append "--create-for-user=" source-user)
748 (string-append "--force-user=" #$user)
749 (string-append "--force-group=" #$group)
750 "-o" "nonempty"
751 #$source #$destination))
752 ('overlay
753 (let ((overlay (string-append #$destination "-overlay"))
754 (workdir (string-append #$destination "-workdir")))
755 (mkdir-recursively overlay #$user #$group)
756 (mkdir-recursively workdir #$user #$group)
757 (mount "overlay" ;source
758 #$destination
759 "overlay" ;type
760 0 ;flags
761 (string-append ;options
762 "lowerdir=" #$source ","
763 "upperdir=" overlay ","
764 "workdir=" workdir))
765 ;; Remount the target over itself to make it appear as if
766 ;; owned by user-name and user-group.
767 (invoke
768 #$bindfs
769 (string-append "--create-for-group=" source-group)
770 (string-append "--create-for-user=" source-user)
771 (string-append "--force-user=" #$user)
772 (string-append "--force-group=" #$group)
773 #$destination #$destination)))))
774 #t))))
775 bindings)))
776
777(define vfs-mapping-service-type
778 (service-type
779 (name 'vfs-mapping)
780 (extensions (list
781 (service-extension shepherd-root-service-type
782 vfs-mapping-shepherd-services)))
783 (compose concatenate)
784 (extend (lambda (original extensions)
785 (vfs-mapping-configuration
786 (inherit original)
787 (bindings (append (vfs-mapping-configuration-bindings original)
788 extensions)))))
789 (default-value (vfs-mapping-configuration))
790 (description "Share or expose a file name under a different name.")))