at 21.11-pre 11 kB view raw
1{ config, lib, pkgs, ... }: 2 3let 4 5 inherit (lib.options) literalExample mkEnableOption mkOption; 6 inherit (lib.types) bool enum ints lines attrsOf nullOr path str submodule; 7 inherit (lib.modules) mkDefault mkIf mkMerge; 8 9 commonDescr = '' 10 Values can be either strings or integers 11 (which will be added to the config file verbatimly) 12 or lists thereof 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. 18 ''; 19 20 str1 = lib.types.addCheck str (s: s!=""); # non-empty string 21 22 configAttrType = 23 # Options in HylaFAX configuration files can be 24 # booleans, strings, integers, or list thereof 25 # representing multiple config directives with the same key. 26 # This type definition resolves all 27 # those types into a list of strings. 28 let 29 inherit (lib.types) attrsOf coercedTo int listOf; 30 innerType = coercedTo bool (x: if x then "Yes" else "No") 31 (coercedTo int (toString) str); 32 in 33 attrsOf (coercedTo innerType lib.singleton (listOf innerType)); 34 35 cfg = config.services.hylafax; 36 37 modemConfigOptions = { name, config, ... }: { 38 options = { 39 name = mkOption { 40 type = str1; 41 example = "ttyS1"; 42 description = '' 43 Name of modem device, 44 will be searched for in <filename>/dev</filename>. 45 ''; 46 }; 47 type = mkOption { 48 type = str1; 49 example = "cirrus"; 50 description = '' 51 Name of modem configuration file, 52 will be searched for in <filename>config</filename> 53 in the spooling area directory. 54 ''; 55 }; 56 config = mkOption { 57 type = configAttrType; 58 example = { 59 AreaCode = "49"; 60 LocalCode = "30"; 61 FAXNumber = "123456"; 62 LocalIdentifier = "LostInBerlin"; 63 }; 64 description = '' 65 Attribute set of values for the given modem. 66 ${commonDescr} 67 Options defined here override options in 68 <option>commonModemConfig</option> for this modem. 69 ''; 70 }; 71 }; 72 config.name = mkDefault name; 73 config.config.Include = [ "config/${config.type}" ]; 74 }; 75 76 defaultConfig = 77 let 78 inherit (config.security) wrapperDir; 79 inherit (config.services.mail.sendmailSetuidWrapper) program; 80 mkIfDefault = cond: value: mkIf cond (mkDefault value); 81 noWrapper = config.services.mail.sendmailSetuidWrapper==null; 82 # If a sendmail setuid wrapper exists, 83 # we add the path to the default configuration file. 84 # Otherwise, we use `false` to provoke 85 # an error if hylafax tries to use it. 86 c.sendmailPath = mkMerge [ 87 (mkIfDefault noWrapper "${pkgs.coreutils}/bin/false") 88 (mkIfDefault (!noWrapper) "${wrapperDir}/${program}") 89 ]; 90 importDefaultConfig = file: 91 lib.attrsets.mapAttrs 92 (lib.trivial.const mkDefault) 93 (import file { inherit pkgs; }); 94 c.commonModemConfig = importDefaultConfig ./modem-default.nix; 95 c.faxqConfig = importDefaultConfig ./faxq-default.nix; 96 c.hfaxdConfig = importDefaultConfig ./hfaxd-default.nix; 97 in 98 c; 99 100 localConfig = 101 let 102 c.hfaxdConfig.UserAccessFile = cfg.userAccessFile; 103 c.faxqConfig = lib.attrsets.mapAttrs 104 (lib.trivial.const (v: mkIf (v!=null) v)) 105 { 106 AreaCode = cfg.areaCode; 107 CountryCode = cfg.countryCode; 108 LongDistancePrefix = cfg.longDistancePrefix; 109 InternationalPrefix = cfg.internationalPrefix; 110 }; 111 c.commonModemConfig = c.faxqConfig; 112 in 113 c; 114 115in 116 117 118{ 119 120 121 options.services.hylafax = { 122 123 enable = mkEnableOption "HylaFAX server"; 124 125 autostart = mkOption { 126 type = bool; 127 default = true; 128 example = false; 129 description = '' 130 Autostart the HylaFAX queue manager at system start. 131 If this is <literal>false</literal>, the queue manager 132 will still be started if there are pending 133 jobs or if a user tries to connect to it. 134 ''; 135 }; 136 137 countryCode = mkOption { 138 type = nullOr str1; 139 default = null; 140 example = "49"; 141 description = "Country code for server and all modems."; 142 }; 143 144 areaCode = mkOption { 145 type = nullOr str1; 146 default = null; 147 example = "30"; 148 description = "Area code for server and all modems."; 149 }; 150 151 longDistancePrefix = mkOption { 152 type = nullOr str; 153 default = null; 154 example = "0"; 155 description = "Long distance prefix for server and all modems."; 156 }; 157 158 internationalPrefix = mkOption { 159 type = nullOr str; 160 default = null; 161 example = "00"; 162 description = "International prefix for server and all modems."; 163 }; 164 165 spoolAreaPath = mkOption { 166 type = path; 167 default = "/var/spool/fax"; 168 description = '' 169 The spooling area will be created/maintained 170 at the location given here. 171 ''; 172 }; 173 174 userAccessFile = mkOption { 175 type = path; 176 default = "/etc/hosts.hfaxd"; 177 description = '' 178 The <filename>hosts.hfaxd</filename> 179 file entry in the spooling area 180 will be symlinked to the location given here. 181 This file must exist and be 182 readable only by the <literal>uucp</literal> user. 183 See hosts.hfaxd(5) for details. 184 This configuration permits access for all users: 185 <literal> 186 environment.etc."hosts.hfaxd" = { 187 mode = "0600"; 188 user = "uucp"; 189 text = ".*"; 190 }; 191 </literal> 192 Note that host-based access can be controlled with 193 <option>config.systemd.sockets.hylafax-hfaxd.listenStreams</option>; 194 by default, only 127.0.0.1 is permitted to connect. 195 ''; 196 }; 197 198 sendmailPath = mkOption { 199 type = path; 200 example = literalExample "''${pkgs.postfix}/bin/sendmail"; 201 # '' ; # fix vim 202 description = '' 203 Path to <filename>sendmail</filename> program. 204 The default uses the local sendmail wrapper 205 (see <option>config.services.mail.sendmailSetuidWrapper</option>), 206 otherwise the <filename>false</filename> 207 binary to cause an error if used. 208 ''; 209 }; 210 211 hfaxdConfig = mkOption { 212 type = configAttrType; 213 example.RecvqProtection = "0400"; 214 description = '' 215 Attribute set of lines for the global 216 hfaxd config file <filename>etc/hfaxd.conf</filename>. 217 ${commonDescr} 218 ''; 219 }; 220 221 faxqConfig = mkOption { 222 type = configAttrType; 223 example = { 224 InternationalPrefix = "00"; 225 LongDistancePrefix = "0"; 226 }; 227 description = '' 228 Attribute set of lines for the global 229 faxq config file <filename>etc/config</filename>. 230 ${commonDescr} 231 ''; 232 }; 233 234 commonModemConfig = mkOption { 235 type = configAttrType; 236 example = { 237 InternationalPrefix = "00"; 238 LongDistancePrefix = "0"; 239 }; 240 description = '' 241 Attribute set of default values for 242 modem config files <filename>etc/config.*</filename>. 243 ${commonDescr} 244 Think twice before changing 245 paths of fax-processing scripts. 246 ''; 247 }; 248 249 modems = mkOption { 250 type = attrsOf (submodule [ modemConfigOptions ]); 251 default = {}; 252 example.ttyS1 = { 253 type = "cirrus"; 254 config = { 255 FAXNumber = "123456"; 256 LocalIdentifier = "Smith"; 257 }; 258 }; 259 description = '' 260 Description of installed modems. 261 At least on modem must be defined 262 to enable the HylaFAX server. 263 ''; 264 }; 265 266 spoolExtraInit = mkOption { 267 type = lines; 268 default = ""; 269 example = "chmod 0755 . # everyone may read my faxes"; 270 description = '' 271 Additional shell code that is executed within the 272 spooling area directory right after its setup. 273 ''; 274 }; 275 276 faxcron.enable.spoolInit = mkEnableOption '' 277 Purge old files from the spooling area with 278 <filename>faxcron</filename> 279 each time the spooling area is initialized. 280 ''; 281 faxcron.enable.frequency = mkOption { 282 type = nullOr str1; 283 default = null; 284 example = "daily"; 285 description = '' 286 Purge old files from the spooling area with 287 <filename>faxcron</filename> with the given frequency 288 (see systemd.time(7)). 289 ''; 290 }; 291 faxcron.infoDays = mkOption { 292 type = ints.positive; 293 default = 30; 294 description = '' 295 Set the expiration time for data in the 296 remote machine information directory in days. 297 ''; 298 }; 299 faxcron.logDays = mkOption { 300 type = ints.positive; 301 default = 30; 302 description = '' 303 Set the expiration time for 304 session trace log files in days. 305 ''; 306 }; 307 faxcron.rcvDays = mkOption { 308 type = ints.positive; 309 default = 7; 310 description = '' 311 Set the expiration time for files in 312 the received facsimile queue in days. 313 ''; 314 }; 315 316 faxqclean.enable.spoolInit = mkEnableOption '' 317 Purge old files from the spooling area with 318 <filename>faxqclean</filename> 319 each time the spooling area is initialized. 320 ''; 321 faxqclean.enable.frequency = mkOption { 322 type = nullOr str1; 323 default = null; 324 example = "daily"; 325 description = '' 326 Purge old files from the spooling area with 327 <filename>faxcron</filename> with the given frequency 328 (see systemd.time(7)). 329 ''; 330 }; 331 faxqclean.archiving = mkOption { 332 type = enum [ "never" "as-flagged" "always" ]; 333 default = "as-flagged"; 334 example = "always"; 335 description = '' 336 Enable or suppress job archiving: 337 <literal>never</literal> disables job archiving, 338 <literal>as-flagged</literal> archives jobs that 339 have been flagged for archiving by sendfax, 340 <literal>always</literal> forces archiving of all jobs. 341 See also sendfax(1) and faxqclean(8). 342 ''; 343 }; 344 faxqclean.doneqMinutes = mkOption { 345 type = ints.positive; 346 default = 15; 347 example = literalExample "24*60"; 348 description = '' 349 Set the job 350 age threshold (in minutes) that controls how long 351 jobs may reside in the doneq directory. 352 ''; 353 }; 354 faxqclean.docqMinutes = mkOption { 355 type = ints.positive; 356 default = 60; 357 example = literalExample "24*60"; 358 description = '' 359 Set the document 360 age threshold (in minutes) that controls how long 361 unreferenced files may reside in the docq directory. 362 ''; 363 }; 364 365 }; 366 367 368 config.services.hylafax = 369 mkIf 370 (config.services.hylafax.enable) 371 (mkMerge [ defaultConfig localConfig ]) 372 ; 373 374}