Skip to content

Commit 7259c93

Browse files
committedMar 23, 2025
Add wsdd2 NixOS service module
1 parent 2989a23 commit 7259c93

File tree

5 files changed

+218
-0
lines changed

5 files changed

+218
-0
lines changed
 

‎nixos/modules/module-list.nix

+1
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,7 @@
10261026
./services/network-filesystems/orangefs/server.nix
10271027
./services/network-filesystems/rsyncd.nix
10281028
./services/network-filesystems/samba-wsdd.nix
1029+
./services/network-filesystems/samba-wsdd2.nix
10291030
./services/network-filesystems/samba.nix
10301031
./services/network-filesystems/saunafs.nix
10311032
./services/network-filesystems/tahoe.nix
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
{ config, lib, pkgs, ... }:
2+
let
3+
cfg = config.services.samba-wsdd2;
4+
repeatFlag = flag: level:
5+
lib.concatStrings (builtins.genList (_: flag) level);
6+
args = lib.concatStringsSep " " ([
7+
(lib.optionalString cfg.ipv4Only "-4")
8+
(lib.optionalString cfg.ipv6Only "-6")
9+
(lib.optionalString cfg.udpOnly "-u")
10+
(lib.optionalString cfg.tcpOnly "-t")
11+
(lib.optionalString cfg.llmnrOnly "-l")
12+
(lib.optionalString cfg.wsddOnly "-w")
13+
(repeatFlag "-L" cfg.llmnrDebugLevel)
14+
(repeatFlag "-W" cfg.wsddDebugLevel)
15+
(lib.optionalString (cfg.interface != null) "-i ${cfg.interface}")
16+
(lib.optionalString (cfg.hostname != null) "-H ${cfg.hostname}")
17+
(lib.optionalString (cfg.aliases != null)
18+
''-A "${lib.concatStringsSep "," cfg.aliases}"'')
19+
(lib.optionalString (cfg.netbiosName != null) "-N ${cfg.netbiosName}")
20+
(lib.optionalString (cfg.netbiosAliases != null)
21+
''-B "${lib.concatStringsSep "," cfg.netbiosAliases}"'')
22+
(lib.optionalString (cfg.workgroup != null) "-G ${cfg.workgroup}")
23+
(lib.optionalString (cfg.bootParameters != null)
24+
''-b "${cfg.bootParameters}"'')
25+
]);
26+
in {
27+
options.services.samba-wsdd2 = {
28+
enable = lib.mkEnableOption "Web Services Dynamic Discovery Daemon (wsdd2)";
29+
30+
openFirewall = lib.mkOption {
31+
type = lib.types.bool;
32+
default = false;
33+
description = "Open required firewall ports for WSDD2.";
34+
};
35+
ipv4Only = lib.mkOption {
36+
type = lib.types.bool;
37+
default = false;
38+
description = "Run wsdd2 as a daemon.";
39+
};
40+
ipv6Only = lib.mkOption {
41+
type = lib.types.bool;
42+
default = false;
43+
description = "Enable IPv6-only mode.";
44+
};
45+
udpOnly = lib.mkOption {
46+
type = lib.types.bool;
47+
default = false;
48+
description = "Use UDP-only mode.";
49+
};
50+
tcpOnly = lib.mkOption {
51+
type = lib.types.bool;
52+
default = false;
53+
description = "Use TCP-only mode.";
54+
};
55+
llmnrOnly = lib.mkOption {
56+
type = lib.types.bool;
57+
default = false;
58+
description = "Enable LLMNR-only mode.";
59+
};
60+
wsddOnly = lib.mkOption {
61+
type = lib.types.bool;
62+
default = false;
63+
description = "Enable WSDD-only mode.";
64+
};
65+
llmnrDebugLevel = lib.mkOption {
66+
type = lib.types.int;
67+
default = 0;
68+
description = "Set LLMNR debug level (e.g., 1 = -L, 2 = -LL, etc.).";
69+
};
70+
wsddDebugLevel = lib.mkOption {
71+
type = lib.types.int;
72+
default = 0;
73+
description = "Set WSDD debug level (e.g., 1 = -W, 2 = -WW, etc.).";
74+
};
75+
interface = lib.mkOption {
76+
type = lib.types.nullOr lib.types.str;
77+
default = null;
78+
description = "Network interface to bind to (e.g., br0).";
79+
};
80+
hostname = lib.mkOption {
81+
type = lib.types.nullOr lib.types.str;
82+
default = null;
83+
description = "Set host name for WSDD.";
84+
};
85+
aliases = lib.mkOption {
86+
type = lib.types.nullOr (lib.types.listOf lib.types.str);
87+
default = null;
88+
description = "Set host aliases.";
89+
};
90+
netbiosName = lib.mkOption {
91+
type = lib.types.nullOr lib.types.str;
92+
default = null;
93+
description = "NetBIOS name to advertise.";
94+
};
95+
netbiosAliases = lib.mkOption {
96+
type = lib.types.nullOr (lib.types.listOf lib.types.str);
97+
default = null;
98+
description = "NetBIOS aliases.";
99+
};
100+
workgroup = lib.mkOption {
101+
type = lib.types.nullOr lib.types.str;
102+
default = null;
103+
example = "HOME";
104+
description = "Set workgroup name.";
105+
};
106+
bootParameters = lib.mkOption {
107+
type = lib.types.nullOr lib.types.str;
108+
default = null;
109+
description = "Boot parameters in the format key1:val1,key2:val2,...";
110+
};
111+
};
112+
config = lib.mkIf cfg.enable {
113+
systemd.services.samba-wsdd2 = {
114+
description = "Web Services Dynamic Discovery Daemon (wsdd2)";
115+
after = [ "network.target" ];
116+
wants = [ "network.target" ];
117+
wantedBy = [ "multi-user.target" ];
118+
serviceConfig = {
119+
ExecStart = "${pkgs.wsdd2}/bin/wsdd2 ${args}";
120+
Restart = "always";
121+
RestartSec = "5s";
122+
# Security Hardening Options
123+
LockPersonality = true;
124+
MemoryDenyWriteExecute = true;
125+
NoNewPrivileges = true;
126+
PrivateDevices = true;
127+
PrivateMounts = true;
128+
PrivateTmp = true;
129+
PrivateUsers = false;
130+
ProtectClock = true;
131+
ProtectControlGroups = true;
132+
ProtectHome = true;
133+
ProtectHostname = true;
134+
ProtectKernelLogs = true;
135+
ProtectKernelModules = true;
136+
ProtectKernelTunables = true;
137+
ProtectSystem = "strict";
138+
RestrictAddressFamilies =
139+
[ "AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK" ];
140+
RestrictNamespaces = true;
141+
RestrictRealtime = true;
142+
RestrictSUIDSGID = true;
143+
RuntimeDirectoryMode = "0750";
144+
SystemCallArchitectures = "native";
145+
SystemCallFilter = [
146+
"~@cpu-emulation"
147+
"~@debug"
148+
"~@mount"
149+
"~@obsolete"
150+
"~@privileged"
151+
"~@resources"
152+
];
153+
UMask = "0027";
154+
};
155+
};
156+
environment.systemPackages = [ pkgs.wsdd2 ];
157+
158+
networking.firewall = lib.mkIf cfg.openFirewall {
159+
allowedUDPPorts = [ 3702 5355 ]; # WS-Discovery + LLMNR multicast UDP
160+
allowedTCPPorts = [ 5355 ]; # LLMNR unicast TCP
161+
extraCommands = ''
162+
ip6tables -A INPUT -p udp -m udp --dport 3702 -d ff02::c -j ACCEPT
163+
ip6tables -A INPUT -p udp -m udp --dport 5355 -d ff02::1:3 -j ACCEPT
164+
'';
165+
};
166+
};
167+
}

‎nixos/tests/all-tests.nix

+1
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,7 @@ in {
10461046
sabnzbd = handleTest ./sabnzbd.nix {};
10471047
samba = handleTest ./samba.nix {};
10481048
samba-wsdd = handleTest ./samba-wsdd.nix {};
1049+
samba-wsdd2 = handleTest ./samba-wsdd2.nix {};
10491050
sane = handleTest ./sane.nix {};
10501051
sanoid = handleTest ./sanoid.nix {};
10511052
saunafs = handleTest ./saunafs.nix {};

‎nixos/tests/samba-wsdd2.nix

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import ./make-test-python.nix ({ pkgs, ... }:
2+
3+
{
4+
name = "samba-wsdd2";
5+
meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
6+
7+
nodes = {
8+
server_wsdd2 = { ... }: {
9+
services.samba-wsdd2 = {
10+
enable = true;
11+
openFirewall = true;
12+
interface = "eth1";
13+
workgroup = "WORKGROUP";
14+
hostname = "SERVER-WSDD";
15+
};
16+
};
17+
};
18+
19+
testScript = ''
20+
server_wsdd2.start()
21+
server_wsdd2.wait_for_unit("samba-wsdd2")
22+
'';
23+
})

‎pkgs/by-name/ws/wsdd2/package.nix

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{ stdenv, fetchFromGitHub, makeWrapper, lib }:
2+
stdenv.mkDerivation rec {
3+
pname = "wsdd2";
4+
version = "1.8.7";
5+
src = fetchFromGitHub {
6+
owner = "Netgear";
7+
repo = "wsdd2";
8+
rev = "${version}";
9+
hash = "sha256-K0pGqcWzTgJGdQOIvrkXUPosgaOSL1lm81MEevK8YXk=";
10+
};
11+
nativeBuildInputs = [ makeWrapper ];
12+
buildInputs = [ ];
13+
buildPhase = ''
14+
make
15+
'';
16+
installPhase = ''
17+
mkdir -p $out/bin
18+
install -m755 wsdd2 $out/bin/wsdd2
19+
'';
20+
meta = with lib; {
21+
description = "WSD/LLMNR Discovery/Name Service Daemon";
22+
homepage = "https://github.com/Netgear/wsdd2";
23+
license = licenses.gpl3;
24+
platforms = platforms.linux;
25+
};
26+
}

0 commit comments

Comments
 (0)
Failed to load comments.