1{ lib, config, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.znc;
8
9 networkOpts = {
10 options = {
11
12 server = mkOption {
13 type = types.str;
14 example = "irc.libera.chat";
15 description = lib.mdDoc ''
16 IRC server address.
17 '';
18 };
19
20 port = mkOption {
21 type = types.port;
22 default = 6697;
23 description = lib.mdDoc ''
24 IRC server port.
25 '';
26 };
27
28 password = mkOption {
29 type = types.str;
30 default = "";
31 description = lib.mdDoc ''
32 IRC server password, such as for a Slack gateway.
33 '';
34 };
35
36 useSSL = mkOption {
37 type = types.bool;
38 default = true;
39 description = lib.mdDoc ''
40 Whether to use SSL to connect to the IRC server.
41 '';
42 };
43
44 modules = mkOption {
45 type = types.listOf types.str;
46 default = [ "simple_away" ];
47 example = literalExpression ''[ "simple_away" "sasl" ]'';
48 description = lib.mdDoc ''
49 ZNC network modules to load.
50 '';
51 };
52
53 channels = mkOption {
54 type = types.listOf types.str;
55 default = [];
56 example = [ "nixos" ];
57 description = lib.mdDoc ''
58 IRC channels to join.
59 '';
60 };
61
62 hasBitlbeeControlChannel = mkOption {
63 type = types.bool;
64 default = false;
65 description = lib.mdDoc ''
66 Whether to add the special Bitlbee operations channel.
67 '';
68 };
69
70 extraConf = mkOption {
71 default = "";
72 type = types.lines;
73 example = ''
74 Encoding = ^UTF-8
75 FloodBurst = 4
76 FloodRate = 1.00
77 IRCConnectEnabled = true
78 Ident = johntron
79 JoinDelay = 0
80 Nick = johntron
81 '';
82 description = lib.mdDoc ''
83 Extra config for the network. Consider using
84 {option}`services.znc.config` instead.
85 '';
86 };
87 };
88 };
89
90in
91
92{
93
94 options = {
95 services.znc = {
96
97 useLegacyConfig = mkOption {
98 default = true;
99 type = types.bool;
100 description = lib.mdDoc ''
101 Whether to propagate the legacy options under
102 {option}`services.znc.confOptions.*` to the znc config. If this
103 is turned on, the znc config will contain a user with the default name
104 "znc", global modules "webadmin" and "adminlog" will be enabled by
105 default, and more, all controlled through the
106 {option}`services.znc.confOptions.*` options.
107 You can use {command}`nix-instantiate --eval --strict '<nixpkgs/nixos>' -A config.services.znc.config`
108 to view the current value of the config.
109
110 In any case, if you need more flexibility,
111 {option}`services.znc.config` can be used to override/add to
112 all of the legacy options.
113 '';
114 };
115
116 confOptions = {
117 modules = mkOption {
118 type = types.listOf types.str;
119 default = [ "webadmin" "adminlog" ];
120 example = [ "partyline" "webadmin" "adminlog" "log" ];
121 description = lib.mdDoc ''
122 A list of modules to include in the `znc.conf` file.
123 '';
124 };
125
126 userModules = mkOption {
127 type = types.listOf types.str;
128 default = [ "chansaver" "controlpanel" ];
129 example = [ "chansaver" "controlpanel" "fish" "push" ];
130 description = lib.mdDoc ''
131 A list of user modules to include in the `znc.conf` file.
132 '';
133 };
134
135 userName = mkOption {
136 default = "znc";
137 example = "johntron";
138 type = types.str;
139 description = lib.mdDoc ''
140 The user name used to log in to the ZNC web admin interface.
141 '';
142 };
143
144 networks = mkOption {
145 default = { };
146 type = with types; attrsOf (submodule networkOpts);
147 description = lib.mdDoc ''
148 IRC networks to connect the user to.
149 '';
150 example = literalExpression ''
151 {
152 "libera" = {
153 server = "irc.libera.chat";
154 port = 6697;
155 useSSL = true;
156 modules = [ "simple_away" ];
157 };
158 };
159 '';
160 };
161
162 nick = mkOption {
163 default = "znc-user";
164 example = "john";
165 type = types.str;
166 description = lib.mdDoc ''
167 The IRC nick.
168 '';
169 };
170
171 passBlock = mkOption {
172 example = ''
173 <Pass password>
174 Method = sha256
175 Hash = e2ce303c7ea75c571d80d8540a8699b46535be6a085be3414947d638e48d9e93
176 Salt = l5Xryew4g*!oa(ECfX2o
177 </Pass>
178 '';
179 type = types.str;
180 description = lib.mdDoc ''
181 Generate with {command}`nix-shell -p znc --command "znc --makepass"`.
182 This is the password used to log in to the ZNC web admin interface.
183 You can also set this through
184 {option}`services.znc.config.User.<username>.Pass.Method`
185 and co.
186 '';
187 };
188
189 port = mkOption {
190 default = 5000;
191 type = types.port;
192 description = lib.mdDoc ''
193 Specifies the port on which to listen.
194 '';
195 };
196
197 useSSL = mkOption {
198 default = true;
199 type = types.bool;
200 description = lib.mdDoc ''
201 Indicates whether the ZNC server should use SSL when listening on
202 the specified port. A self-signed certificate will be generated.
203 '';
204 };
205
206 uriPrefix = mkOption {
207 type = types.nullOr types.str;
208 default = null;
209 example = "/znc/";
210 description = lib.mdDoc ''
211 An optional URI prefix for the ZNC web interface. Can be
212 used to make ZNC available behind a reverse proxy.
213 '';
214 };
215
216 extraZncConf = mkOption {
217 default = "";
218 type = types.lines;
219 description = lib.mdDoc ''
220 Extra config to `znc.conf` file.
221 '';
222 };
223 };
224
225 };
226 };
227
228 config = mkIf cfg.useLegacyConfig {
229
230 services.znc.config = let
231 c = cfg.confOptions;
232 # defaults here should override defaults set in the non-legacy part
233 mkDefault = mkOverride 900;
234 in {
235 LoadModule = mkDefault c.modules;
236 Listener.l = {
237 Port = mkDefault c.port;
238 IPv4 = mkDefault true;
239 IPv6 = mkDefault true;
240 SSL = mkDefault c.useSSL;
241 URIPrefix = c.uriPrefix;
242 };
243 User.${c.userName} = {
244 Admin = mkDefault true;
245 Nick = mkDefault c.nick;
246 AltNick = mkDefault "${c.nick}_";
247 Ident = mkDefault c.nick;
248 RealName = mkDefault c.nick;
249 LoadModule = mkDefault c.userModules;
250 Network = mapAttrs (name: net: {
251 LoadModule = mkDefault net.modules;
252 Server = mkDefault "${net.server} ${optionalString net.useSSL "+"}${toString net.port} ${net.password}";
253 Chan = optionalAttrs net.hasBitlbeeControlChannel { "&bitlbee" = mkDefault {}; } //
254 listToAttrs (map (n: nameValuePair "#${n}" (mkDefault {})) net.channels);
255 extraConfig = if net.extraConf == "" then mkDefault null else net.extraConf;
256 }) c.networks;
257 extraConfig = [ c.passBlock ];
258 };
259 extraConfig = optional (c.extraZncConf != "") c.extraZncConf;
260 };
261 };
262
263 imports = [
264 (mkRemovedOptionModule ["services" "znc" "zncConf"] ''
265 Instead of `services.znc.zncConf = "... foo ...";`, use
266 `services.znc.configFile = pkgs.writeText "znc.conf" "... foo ...";`.
267 '')
268 ];
269}