1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.samba-wsdd;
9
10in
11{
12 options = {
13 services.samba-wsdd = {
14 enable = lib.mkEnableOption ''
15 Web Services Dynamic Discovery host daemon. This enables (Samba) hosts, like your local NAS device,
16 to be found by Web Service Discovery Clients like Windows
17 '';
18 interface = lib.mkOption {
19 type = lib.types.nullOr lib.types.str;
20 default = null;
21 example = "eth0";
22 description = "Interface or address to use.";
23 };
24 hoplimit = lib.mkOption {
25 type = lib.types.nullOr lib.types.int;
26 default = null;
27 example = 2;
28 description = "Hop limit for multicast packets (default = 1).";
29 };
30 openFirewall = lib.mkOption {
31 description = ''
32 Whether to open the required firewall ports in the firewall.
33 '';
34 default = false;
35 type = lib.types.bool;
36 };
37 workgroup = lib.mkOption {
38 type = lib.types.nullOr lib.types.str;
39 default = null;
40 example = "HOME";
41 description = "Set workgroup name (default WORKGROUP).";
42 };
43 hostname = lib.mkOption {
44 type = lib.types.nullOr lib.types.str;
45 default = null;
46 example = "FILESERVER";
47 description = "Override (NetBIOS) hostname to be used (default hostname).";
48 };
49 domain = lib.mkOption {
50 type = lib.types.nullOr lib.types.str;
51 default = null;
52 description = "Set domain name (disables workgroup).";
53 };
54 discovery = lib.mkOption {
55 type = lib.types.bool;
56 default = false;
57 description = "Enable discovery operation mode.";
58 };
59 listen = lib.mkOption {
60 type = lib.types.str;
61 default = "/run/wsdd/wsdd.sock";
62 description = "Listen on path or localhost port in discovery mode.";
63 };
64 extraOptions = lib.mkOption {
65 type = lib.types.listOf lib.types.str;
66 default = [ "--shortlog" ];
67 example = [
68 "--verbose"
69 "--no-http"
70 "--ipv4only"
71 "--no-host"
72 ];
73 description = "Additional wsdd options.";
74 };
75 };
76 };
77
78 config = lib.mkIf cfg.enable {
79
80 environment.systemPackages = [ pkgs.wsdd ];
81
82 systemd.services.samba-wsdd = {
83 description = "Web Services Dynamic Discovery host daemon";
84 after = [ "network.target" ];
85 wantedBy = [ "multi-user.target" ];
86 serviceConfig = {
87 DynamicUser = true;
88 Type = "simple";
89 ExecStart = ''
90 ${pkgs.wsdd}/bin/wsdd ${
91 lib.optionalString (cfg.interface != null) "--interface '${cfg.interface}'"
92 } \
93 ${
94 lib.optionalString (cfg.hoplimit != null) "--hoplimit '${toString cfg.hoplimit}'"
95 } \
96 ${
97 lib.optionalString (cfg.workgroup != null) "--workgroup '${cfg.workgroup}'"
98 } \
99 ${lib.optionalString (cfg.hostname != null) "--hostname '${cfg.hostname}'"} \
100 ${lib.optionalString (cfg.domain != null) "--domain '${cfg.domain}'"} \
101 ${lib.optionalString cfg.discovery "--discovery --listen '${cfg.listen}'"} \
102 ${lib.escapeShellArgs cfg.extraOptions}
103 '';
104 # Runtime directory and mode
105 RuntimeDirectory = "wsdd";
106 RuntimeDirectoryMode = "0750";
107 # Access write directories
108 UMask = "0027";
109 # Capabilities
110 CapabilityBoundingSet = "";
111 # Security
112 NoNewPrivileges = true;
113 # Sandboxing
114 ProtectSystem = "strict";
115 ProtectHome = true;
116 PrivateTmp = true;
117 PrivateDevices = true;
118 PrivateUsers = false;
119 ProtectHostname = true;
120 ProtectClock = true;
121 ProtectKernelTunables = true;
122 ProtectKernelModules = true;
123 ProtectKernelLogs = true;
124 ProtectControlGroups = true;
125 RestrictAddressFamilies = [
126 "AF_UNIX"
127 "AF_INET"
128 "AF_INET6"
129 "AF_NETLINK"
130 ];
131 RestrictNamespaces = true;
132 LockPersonality = true;
133 MemoryDenyWriteExecute = true;
134 RestrictRealtime = true;
135 RestrictSUIDSGID = true;
136 PrivateMounts = true;
137 # System Call Filtering
138 SystemCallArchitectures = "native";
139 SystemCallFilter = "~@cpu-emulation @debug @mount @obsolete @privileged @resources";
140 };
141 };
142
143 networking.firewall = lib.mkIf cfg.openFirewall {
144 allowedTCPPorts = [ 5357 ];
145 allowedUDPPorts = [ 3702 ];
146 };
147 };
148}