nixpkgs/nixos/modules/services/networking/nbd.nix
Alexandru Scvortov 252f20aaa2 nbd: add programs.nbd, services.nbd, and test
Changes:

nbd: Update nixos/modules/services/networking/nbd.nix

Co-authored-by: pennae <82953136+pennae@users.noreply.github.com>

nbd: Update nixos/modules/services/networking/nbd.nix

Co-authored-by: pennae <82953136+pennae@users.noreply.github.com>

nbd: Update nixos/tests/nbd.nix

Co-authored-by: pennae <82953136+pennae@users.noreply.github.com>

nbd: generalize options in nbd service

nbd: harden service

nbd: Update nixos/modules/services/networking/nbd.nix

Co-authored-by: pennae <82953136+pennae@users.noreply.github.com>

nbd: Update nixos/modules/services/networking/nbd.nix

Co-authored-by: pennae <82953136+pennae@users.noreply.github.com>

nbd: refactor code a bit and BindPaths automatically
2022-03-09 12:00:47 +00:00

147 lines
4.4 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.nbd;
configFormat = pkgs.formats.ini { };
iniFields = with types; attrsOf (oneOf [ bool int float str ]);
serverConfig = configFormat.generate "nbd-server-config"
({
generic =
(cfg.server.extraOptions // {
user = "root";
group = "root";
port = cfg.server.listenPort;
} // (optionalAttrs (cfg.server.listenAddress != null) {
listenaddr = cfg.server.listenAddress;
}));
}
// (mapAttrs
(_: { path, allowAddresses, extraOptions }:
extraOptions // {
exportname = path;
} // (optionalAttrs (allowAddresses != null) {
authfile = pkgs.writeText "authfile" (concatStringsSep "\n" allowAddresses);
}))
cfg.server.exports)
);
splitLists =
partition
(path: hasPrefix "/dev/" path)
(mapAttrsToList (_: { path, ... }: path) cfg.server.exports);
allowedDevices = splitLists.right;
boundPaths = splitLists.wrong;
in
{
options = {
services.nbd = {
server = {
enable = mkEnableOption "the Network Block Device (nbd) server";
listenPort = mkOption {
type = types.port;
default = 10809;
description = "Port to listen on. The port is NOT automatically opened in the firewall.";
};
extraOptions = mkOption {
type = iniFields;
default = {
allowlist = false;
};
description = ''
Extra options for the server. See
<citerefentry><refentrytitle>nbd-server</refentrytitle>
<manvolnum>5</manvolnum></citerefentry>.
'';
};
exports = mkOption {
description = "Files or block devices to make available over the network.";
default = { };
type = with types; attrsOf
(submodule {
options = {
path = mkOption {
type = str;
description = "File or block device to export.";
example = "/dev/sdb1";
};
allowAddresses = mkOption {
type = nullOr (listOf str);
default = null;
example = [ "10.10.0.0/24" "127.0.0.1" ];
description = "IPs and subnets that are authorized to connect for this device. If not specified, the server will allow all connections.";
};
extraOptions = mkOption {
type = iniFields;
default = {
flush = true;
fua = true;
};
description = ''
Extra options for this export. See
<citerefentry><refentrytitle>nbd-server</refentrytitle>
<manvolnum>5</manvolnum></citerefentry>.
'';
};
};
});
};
listenAddress = mkOption {
type = with types; nullOr str;
description = "Address to listen on. If not specified, the server will listen on all interfaces.";
default = null;
example = "10.10.0.1";
};
};
};
};
config = mkIf cfg.server.enable {
boot.kernelModules = [ "nbd" ];
systemd.services.nbd-server = {
after = [ "network-online.target" ];
before = [ "multi-user.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.nbd}/bin/nbd-server -C ${serverConfig}";
Type = "forking";
DeviceAllow = map (path: "${path} rw") allowedDevices;
BindPaths = boundPaths;
CapabilityBoundingSet = "";
DevicePolicy = "closed";
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = false;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "noaccess";
ProtectSystem = "strict";
RestrictAddressFamilies = "AF_INET AF_INET6";
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
UMask = "0077";
};
};
};
}