1 { config, lib, pkgs, ... }:
5 inherit (lib.options) literalExpression mkEnableOption mkOption;
6 inherit (lib.types) bool enum ints lines attrsOf nonEmptyStr nullOr path str submodule;
7 inherit (lib.modules) mkDefault mkIf mkMerge;
10 Values can be either strings or integers
11 (which will be added to the config file verbatimly)
13 (which will be translated to multiple
14 lines with the same configuration key).
15 Boolean values are translated to "Yes" or "No".
16 The default contains some reasonable
17 configuration to yield an operational system.
21 # Options in HylaFAX configuration files can be
22 # booleans, strings, integers, or list thereof
23 # representing multiple config directives with the same key.
24 # This type definition resolves all
25 # those types into a list of strings.
27 inherit (lib.types) attrsOf coercedTo int listOf;
28 innerType = coercedTo bool (x: if x then "Yes" else "No")
29 (coercedTo int (toString) str);
31 attrsOf (coercedTo innerType lib.singleton (listOf innerType));
33 cfg = config.services.hylafax;
35 modemConfigOptions = { name, config, ... }: {
40 description = lib.mdDoc ''
42 will be searched for in {file}`/dev`.
48 description = lib.mdDoc ''
49 Name of modem configuration file,
50 will be searched for in {file}`config`
51 in the spooling area directory.
55 type = configAttrType;
60 LocalIdentifier = "LostInBerlin";
62 description = lib.mdDoc ''
63 Attribute set of values for the given modem.
65 Options defined here override options in
66 {option}`commonModemConfig` for this modem.
70 config.name = mkDefault name;
71 config.config.Include = [ "config/${config.type}" ];
76 inherit (config.security) wrapperDir;
77 inherit (config.services.mail.sendmailSetuidWrapper) program;
78 mkIfDefault = cond: value: mkIf cond (mkDefault value);
79 noWrapper = config.services.mail.sendmailSetuidWrapper==null;
80 # If a sendmail setuid wrapper exists,
81 # we add the path to the default configuration file.
82 # Otherwise, we use `false` to provoke
83 # an error if hylafax tries to use it.
84 c.sendmailPath = mkMerge [
85 (mkIfDefault noWrapper "${pkgs.coreutils}/bin/false")
86 (mkIfDefault (!noWrapper) "${wrapperDir}/${program}")
88 importDefaultConfig = file:
90 (lib.trivial.const mkDefault)
91 (import file { inherit pkgs; });
92 c.commonModemConfig = importDefaultConfig ./modem-default.nix;
93 c.faxqConfig = importDefaultConfig ./faxq-default.nix;
94 c.hfaxdConfig = importDefaultConfig ./hfaxd-default.nix;
100 c.hfaxdConfig.UserAccessFile = cfg.userAccessFile;
101 c.faxqConfig = lib.attrsets.mapAttrs
102 (lib.trivial.const (v: mkIf (v!=null) v))
104 AreaCode = cfg.areaCode;
105 CountryCode = cfg.countryCode;
106 LongDistancePrefix = cfg.longDistancePrefix;
107 InternationalPrefix = cfg.internationalPrefix;
109 c.commonModemConfig = c.faxqConfig;
119 options.services.hylafax = {
121 enable = mkEnableOption (lib.mdDoc "HylaFAX server");
123 autostart = mkOption {
127 description = lib.mdDoc ''
128 Autostart the HylaFAX queue manager at system start.
129 If this is `false`, the queue manager
130 will still be started if there are pending
131 jobs or if a user tries to connect to it.
135 countryCode = mkOption {
136 type = nullOr nonEmptyStr;
139 description = lib.mdDoc "Country code for server and all modems.";
142 areaCode = mkOption {
143 type = nullOr nonEmptyStr;
146 description = lib.mdDoc "Area code for server and all modems.";
149 longDistancePrefix = mkOption {
153 description = lib.mdDoc "Long distance prefix for server and all modems.";
156 internationalPrefix = mkOption {
160 description = lib.mdDoc "International prefix for server and all modems.";
163 spoolAreaPath = mkOption {
165 default = "/var/spool/fax";
166 description = lib.mdDoc ''
167 The spooling area will be created/maintained
168 at the location given here.
172 userAccessFile = mkOption {
174 default = "/etc/hosts.hfaxd";
175 description = lib.mdDoc ''
176 The {file}`hosts.hfaxd`
177 file entry in the spooling area
178 will be symlinked to the location given here.
179 This file must exist and be
180 readable only by the `uucp` user.
181 See hosts.hfaxd(5) for details.
182 This configuration permits access for all users:
184 environment.etc."hosts.hfaxd" = {
190 Note that host-based access can be controlled with
191 {option}`config.systemd.sockets.hylafax-hfaxd.listenStreams`;
192 by default, only 127.0.0.1 is permitted to connect.
196 sendmailPath = mkOption {
198 example = literalExpression ''"''${pkgs.postfix}/bin/sendmail"'';
200 description = lib.mdDoc ''
201 Path to {file}`sendmail` program.
202 The default uses the local sendmail wrapper
203 (see {option}`config.services.mail.sendmailSetuidWrapper`),
204 otherwise the {file}`false`
205 binary to cause an error if used.
209 hfaxdConfig = mkOption {
210 type = configAttrType;
211 example.RecvqProtection = "0400";
212 description = lib.mdDoc ''
213 Attribute set of lines for the global
214 hfaxd config file {file}`etc/hfaxd.conf`.
219 faxqConfig = mkOption {
220 type = configAttrType;
222 InternationalPrefix = "00";
223 LongDistancePrefix = "0";
225 description = lib.mdDoc ''
226 Attribute set of lines for the global
227 faxq config file {file}`etc/config`.
232 commonModemConfig = mkOption {
233 type = configAttrType;
235 InternationalPrefix = "00";
236 LongDistancePrefix = "0";
238 description = lib.mdDoc ''
239 Attribute set of default values for
240 modem config files {file}`etc/config.*`.
242 Think twice before changing
243 paths of fax-processing scripts.
248 type = attrsOf (submodule [ modemConfigOptions ]);
253 FAXNumber = "123456";
254 LocalIdentifier = "Smith";
257 description = lib.mdDoc ''
258 Description of installed modems.
259 At least on modem must be defined
260 to enable the HylaFAX server.
264 spoolExtraInit = mkOption {
267 example = "chmod 0755 . # everyone may read my faxes";
268 description = lib.mdDoc ''
269 Additional shell code that is executed within the
270 spooling area directory right after its setup.
274 faxcron.enable.spoolInit = mkEnableOption (lib.mdDoc ''
275 Purge old files from the spooling area with
277 each time the spooling area is initialized.
279 faxcron.enable.frequency = mkOption {
280 type = nullOr nonEmptyStr;
283 description = lib.mdDoc ''
284 Purge old files from the spooling area with
285 {file}`faxcron` with the given frequency
286 (see systemd.time(7)).
289 faxcron.infoDays = mkOption {
290 type = ints.positive;
292 description = lib.mdDoc ''
293 Set the expiration time for data in the
294 remote machine information directory in days.
297 faxcron.logDays = mkOption {
298 type = ints.positive;
300 description = lib.mdDoc ''
301 Set the expiration time for
302 session trace log files in days.
305 faxcron.rcvDays = mkOption {
306 type = ints.positive;
308 description = lib.mdDoc ''
309 Set the expiration time for files in
310 the received facsimile queue in days.
314 faxqclean.enable.spoolInit = mkEnableOption (lib.mdDoc ''
315 Purge old files from the spooling area with
317 each time the spooling area is initialized.
319 faxqclean.enable.frequency = mkOption {
320 type = nullOr nonEmptyStr;
323 description = lib.mdDoc ''
324 Purge old files from the spooling area with
325 {file}`faxcron` with the given frequency
326 (see systemd.time(7)).
329 faxqclean.archiving = mkOption {
330 type = enum [ "never" "as-flagged" "always" ];
331 default = "as-flagged";
333 description = lib.mdDoc ''
334 Enable or suppress job archiving:
335 `never` disables job archiving,
336 `as-flagged` archives jobs that
337 have been flagged for archiving by sendfax,
338 `always` forces archiving of all jobs.
339 See also sendfax(1) and faxqclean(8).
342 faxqclean.doneqMinutes = mkOption {
343 type = ints.positive;
345 example = literalExpression "24*60";
346 description = lib.mdDoc ''
348 age threshold (in minutes) that controls how long
349 jobs may reside in the doneq directory.
352 faxqclean.docqMinutes = mkOption {
353 type = ints.positive;
355 example = literalExpression "24*60";
356 description = lib.mdDoc ''
358 age threshold (in minutes) that controls how long
359 unreferenced files may reside in the docq directory.
366 config.services.hylafax =
368 (config.services.hylafax.enable)
369 (mkMerge [ defaultConfig localConfig ])