vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / nbd.nix
blobe4a7bb1604f9a933140a2b74fe93638f75667846
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.nbd;
7   iniFields = with types; attrsOf (oneOf [ bool int float str ]);
8   # The `[generic]` section must come before all the others in the
9   # config file.  This means we can't just dump an attrset to INI
10   # because that sorts the sections by name.  Instead, we serialize it
11   # on its own first.
12   genericSection = {
13     generic = (cfg.server.extraOptions // {
14       user = "root";
15       group = "root";
16       port = cfg.server.listenPort;
17     } // (optionalAttrs (cfg.server.listenAddress != null) {
18       listenaddr = cfg.server.listenAddress;
19     }));
20   };
21   exportSections =
22     mapAttrs
23       (_: { path, allowAddresses, extraOptions }:
24         extraOptions // {
25           exportname = path;
26         } // (optionalAttrs (allowAddresses != null) {
27           authfile = pkgs.writeText "authfile" (concatStringsSep "\n" allowAddresses);
28         }))
29       cfg.server.exports;
30   serverConfig =
31     pkgs.writeText "nbd-server-config" ''
32       ${lib.generators.toINI {} genericSection}
33       ${lib.generators.toINI {} exportSections}
34     '';
35   splitLists =
36     partition
37       (path: hasPrefix "/dev/" path)
38       (mapAttrsToList (_: { path, ... }: path) cfg.server.exports);
39   allowedDevices = splitLists.right;
40   boundPaths = splitLists.wrong;
43   options = {
44     services.nbd = {
45       server = {
46         enable = mkEnableOption "the Network Block Device (nbd) server";
48         listenPort = mkOption {
49           type = types.port;
50           default = 10809;
51           description = "Port to listen on. The port is NOT automatically opened in the firewall.";
52         };
54         extraOptions = mkOption {
55           type = iniFields;
56           default = {
57             allowlist = false;
58           };
59           description = ''
60             Extra options for the server. See
61             {manpage}`nbd-server(5)`.
62           '';
63         };
65         exports = mkOption {
66           description = "Files or block devices to make available over the network.";
67           default = { };
68           type = with types; attrsOf
69             (submodule {
70               options = {
71                 path = mkOption {
72                   type = str;
73                   description = "File or block device to export.";
74                   example = "/dev/sdb1";
75                 };
77                 allowAddresses = mkOption {
78                   type = nullOr (listOf str);
79                   default = null;
80                   example = [ "10.10.0.0/24" "127.0.0.1" ];
81                   description = "IPs and subnets that are authorized to connect for this device. If not specified, the server will allow all connections.";
82                 };
84                 extraOptions = mkOption {
85                   type = iniFields;
86                   default = {
87                     flush = true;
88                     fua = true;
89                   };
90                   description = ''
91                     Extra options for this export. See
92                     {manpage}`nbd-server(5)`.
93                   '';
94                 };
95               };
96             });
97         };
99         listenAddress = mkOption {
100           type = with types; nullOr str;
101           description = "Address to listen on. If not specified, the server will listen on all interfaces.";
102           default = null;
103           example = "10.10.0.1";
104         };
105       };
106     };
107   };
109   config = mkIf cfg.server.enable {
110     assertions = [
111       {
112         assertion = !(cfg.server.exports ? "generic");
113         message = "services.nbd.server exports must not be named 'generic'";
114       }
115     ];
117     boot.kernelModules = [ "nbd" ];
119     systemd.services.nbd-server = {
120       wants = [ "network-online.target" ];
121       after = [ "network-online.target" ];
122       before = [ "multi-user.target" ];
123       wantedBy = [ "multi-user.target" ];
124       serviceConfig = {
125         ExecStart = "${pkgs.nbd}/bin/nbd-server -C ${serverConfig}";
126         Type = "forking";
128         DeviceAllow = map (path: "${path} rw") allowedDevices;
129         BindPaths = boundPaths;
131         CapabilityBoundingSet = "";
132         DevicePolicy = "closed";
133         LockPersonality = true;
134         MemoryDenyWriteExecute = true;
135         NoNewPrivileges = true;
136         PrivateDevices = false;
137         PrivateMounts = true;
138         PrivateTmp = true;
139         PrivateUsers = true;
140         ProcSubset = "pid";
141         ProtectClock = true;
142         ProtectControlGroups = true;
143         ProtectHome = true;
144         ProtectHostname = true;
145         ProtectKernelLogs = true;
146         ProtectKernelModules = true;
147         ProtectKernelTunables = true;
148         ProtectProc = "noaccess";
149         ProtectSystem = "strict";
150         RestrictAddressFamilies = "AF_INET AF_INET6";
151         RestrictNamespaces = true;
152         RestrictRealtime = true;
153         RestrictSUIDSGID = true;
154         UMask = "0077";
155       };
156     };
157   };