1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7
8let
9 cfg = config.programs.singularity;
10in
11{
12
13 options.programs.singularity = {
14 enable = lib.mkEnableOption "singularity" // {
15 description = ''
16 Whether to install Singularity/Apptainer with system-level overriding such as SUID support.
17 '';
18 };
19 package = lib.mkPackageOption pkgs "singularity" { example = "apptainer"; };
20 packageOverriden = lib.mkOption {
21 type = lib.types.nullOr lib.types.package;
22 default = null;
23 description = ''
24 This option provides access to the overridden result of `programs.singularity.package`.
25
26 For example, the following configuration makes all the Nixpkgs packages use the overridden `singularity`:
27 ```Nix
28 { config, lib, pkgs, ... }:
29 {
30 nixpkgs.overlays = [
31 (final: prev: {
32 _singularity-orig = prev.singularity;
33 singularity = config.programs.singularity.packageOverriden;
34 })
35 ];
36 programs.singularity.enable = true;
37 programs.singularity.package = pkgs._singularity-orig;
38 }
39 ```
40
41 Use `lib.mkForce` to forcefully specify the overridden package.
42 '';
43 };
44 enableExternalLocalStateDir = lib.mkOption {
45 type = lib.types.bool;
46 default = true;
47 example = false;
48 description = ''
49 Whether to use top-level directories as LOCALSTATEDIR
50 instead of the store path ones.
51 This affects the SESSIONDIR of Apptainer/Singularity.
52 If set to true, the SESSIONDIR will become
53 `/var/lib/''${projectName}/mnt/session`.
54 '';
55 };
56 enableFakeroot = lib.mkOption {
57 type = lib.types.bool;
58 default = true;
59 example = false;
60 description = ''
61 Whether to enable the `--fakeroot` support of Singularity/Apptainer.
62 '';
63 };
64 enableSuid = lib.mkOption {
65 type = lib.types.bool;
66 # SingularityCE requires SETUID for most things. Apptainer prefers user
67 # namespaces, e.g. `apptainer exec --nv` would fail if built
68 # `--with-suid`:
69 # > `FATAL: nvidia-container-cli not allowed in setuid mode`
70 default = cfg.package.projectName != "apptainer";
71 defaultText = lib.literalExpression ''config.services.singularity.package.projectName != "apptainer"'';
72 example = false;
73 description = ''
74 Whether to enable the SUID support of Singularity/Apptainer.
75 '';
76 };
77 };
78
79 config = lib.mkIf cfg.enable {
80 programs.singularity.packageOverriden = (
81 cfg.package.override (
82 lib.optionalAttrs cfg.enableExternalLocalStateDir { externalLocalStateDir = "/var/lib"; }
83 // lib.optionalAttrs cfg.enableFakeroot {
84 newuidmapPath = "/run/wrappers/bin/newuidmap";
85 newgidmapPath = "/run/wrappers/bin/newgidmap";
86 }
87 // lib.optionalAttrs cfg.enableSuid {
88 enableSuid = true;
89 starterSuidPath = "/run/wrappers/bin/${cfg.package.projectName}-suid";
90 }
91 )
92 );
93 environment.systemPackages = [ cfg.packageOverriden ];
94 security.wrappers."${cfg.packageOverriden.projectName}-suid" = lib.mkIf cfg.enableSuid {
95 setuid = true;
96 owner = "root";
97 group = "root";
98 source = "${cfg.packageOverriden}/libexec/${cfg.packageOverriden.projectName}/bin/starter-suid.orig";
99 };
100 systemd.tmpfiles.rules = lib.mkIf cfg.enableExternalLocalStateDir [
101 "d /var/lib/${cfg.packageOverriden.projectName}/mnt/session 0770 root root -"
102 ];
103 };
104}