at 23.11-pre 11 kB view raw
1{ config, lib, pkgs, ... }: 2 3let 4 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; 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 configAttrType = 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. 26 let 27 inherit (lib.types) attrsOf coercedTo int listOf; 28 innerType = coercedTo bool (x: if x then "Yes" else "No") 29 (coercedTo int (toString) str); 30 in 31 attrsOf (coercedTo innerType lib.singleton (listOf innerType)); 32 33 cfg = config.services.hylafax; 34 35 modemConfigOptions = { name, config, ... }: { 36 options = { 37 name = mkOption { 38 type = nonEmptyStr; 39 example = "ttyS1"; 40 description = lib.mdDoc '' 41 Name of modem device, 42 will be searched for in {file}`/dev`. 43 ''; 44 }; 45 type = mkOption { 46 type = nonEmptyStr; 47 example = "cirrus"; 48 description = lib.mdDoc '' 49 Name of modem configuration file, 50 will be searched for in {file}`config` 51 in the spooling area directory. 52 ''; 53 }; 54 config = mkOption { 55 type = configAttrType; 56 example = { 57 AreaCode = "49"; 58 LocalCode = "30"; 59 FAXNumber = "123456"; 60 LocalIdentifier = "LostInBerlin"; 61 }; 62 description = lib.mdDoc '' 63 Attribute set of values for the given modem. 64 ${commonDescr} 65 Options defined here override options in 66 {option}`commonModemConfig` for this modem. 67 ''; 68 }; 69 }; 70 config.name = mkDefault name; 71 config.config.Include = [ "config/${config.type}" ]; 72 }; 73 74 defaultConfig = 75 let 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}") 87 ]; 88 importDefaultConfig = file: 89 lib.attrsets.mapAttrs 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; 95 in 96 c; 97 98 localConfig = 99 let 100 c.hfaxdConfig.UserAccessFile = cfg.userAccessFile; 101 c.faxqConfig = lib.attrsets.mapAttrs 102 (lib.trivial.const (v: mkIf (v!=null) v)) 103 { 104 AreaCode = cfg.areaCode; 105 CountryCode = cfg.countryCode; 106 LongDistancePrefix = cfg.longDistancePrefix; 107 InternationalPrefix = cfg.internationalPrefix; 108 }; 109 c.commonModemConfig = c.faxqConfig; 110 in 111 c; 112 113in 114 115 116{ 117 118 119 options.services.hylafax = { 120 121 enable = mkEnableOption (lib.mdDoc "HylaFAX server"); 122 123 autostart = mkOption { 124 type = bool; 125 default = true; 126 example = false; 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. 132 ''; 133 }; 134 135 countryCode = mkOption { 136 type = nullOr nonEmptyStr; 137 default = null; 138 example = "49"; 139 description = lib.mdDoc "Country code for server and all modems."; 140 }; 141 142 areaCode = mkOption { 143 type = nullOr nonEmptyStr; 144 default = null; 145 example = "30"; 146 description = lib.mdDoc "Area code for server and all modems."; 147 }; 148 149 longDistancePrefix = mkOption { 150 type = nullOr str; 151 default = null; 152 example = "0"; 153 description = lib.mdDoc "Long distance prefix for server and all modems."; 154 }; 155 156 internationalPrefix = mkOption { 157 type = nullOr str; 158 default = null; 159 example = "00"; 160 description = lib.mdDoc "International prefix for server and all modems."; 161 }; 162 163 spoolAreaPath = mkOption { 164 type = path; 165 default = "/var/spool/fax"; 166 description = lib.mdDoc '' 167 The spooling area will be created/maintained 168 at the location given here. 169 ''; 170 }; 171 172 userAccessFile = mkOption { 173 type = path; 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: 183 ``` 184 environment.etc."hosts.hfaxd" = { 185 mode = "0600"; 186 user = "uucp"; 187 text = ".*"; 188 }; 189 ``` 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. 193 ''; 194 }; 195 196 sendmailPath = mkOption { 197 type = path; 198 example = literalExpression ''"''${pkgs.postfix}/bin/sendmail"''; 199 # '' ; # fix vim 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. 206 ''; 207 }; 208 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`. 215 ${commonDescr} 216 ''; 217 }; 218 219 faxqConfig = mkOption { 220 type = configAttrType; 221 example = { 222 InternationalPrefix = "00"; 223 LongDistancePrefix = "0"; 224 }; 225 description = lib.mdDoc '' 226 Attribute set of lines for the global 227 faxq config file {file}`etc/config`. 228 ${commonDescr} 229 ''; 230 }; 231 232 commonModemConfig = mkOption { 233 type = configAttrType; 234 example = { 235 InternationalPrefix = "00"; 236 LongDistancePrefix = "0"; 237 }; 238 description = lib.mdDoc '' 239 Attribute set of default values for 240 modem config files {file}`etc/config.*`. 241 ${commonDescr} 242 Think twice before changing 243 paths of fax-processing scripts. 244 ''; 245 }; 246 247 modems = mkOption { 248 type = attrsOf (submodule [ modemConfigOptions ]); 249 default = {}; 250 example.ttyS1 = { 251 type = "cirrus"; 252 config = { 253 FAXNumber = "123456"; 254 LocalIdentifier = "Smith"; 255 }; 256 }; 257 description = lib.mdDoc '' 258 Description of installed modems. 259 At least on modem must be defined 260 to enable the HylaFAX server. 261 ''; 262 }; 263 264 spoolExtraInit = mkOption { 265 type = lines; 266 default = ""; 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. 271 ''; 272 }; 273 274 faxcron.enable.spoolInit = mkEnableOption (lib.mdDoc '' 275 Purge old files from the spooling area with 276 {file}`faxcron` 277 each time the spooling area is initialized. 278 ''); 279 faxcron.enable.frequency = mkOption { 280 type = nullOr nonEmptyStr; 281 default = null; 282 example = "daily"; 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)). 287 ''; 288 }; 289 faxcron.infoDays = mkOption { 290 type = ints.positive; 291 default = 30; 292 description = lib.mdDoc '' 293 Set the expiration time for data in the 294 remote machine information directory in days. 295 ''; 296 }; 297 faxcron.logDays = mkOption { 298 type = ints.positive; 299 default = 30; 300 description = lib.mdDoc '' 301 Set the expiration time for 302 session trace log files in days. 303 ''; 304 }; 305 faxcron.rcvDays = mkOption { 306 type = ints.positive; 307 default = 7; 308 description = lib.mdDoc '' 309 Set the expiration time for files in 310 the received facsimile queue in days. 311 ''; 312 }; 313 314 faxqclean.enable.spoolInit = mkEnableOption (lib.mdDoc '' 315 Purge old files from the spooling area with 316 {file}`faxqclean` 317 each time the spooling area is initialized. 318 ''); 319 faxqclean.enable.frequency = mkOption { 320 type = nullOr nonEmptyStr; 321 default = null; 322 example = "daily"; 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)). 327 ''; 328 }; 329 faxqclean.archiving = mkOption { 330 type = enum [ "never" "as-flagged" "always" ]; 331 default = "as-flagged"; 332 example = "always"; 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). 340 ''; 341 }; 342 faxqclean.doneqMinutes = mkOption { 343 type = ints.positive; 344 default = 15; 345 example = literalExpression "24*60"; 346 description = lib.mdDoc '' 347 Set the job 348 age threshold (in minutes) that controls how long 349 jobs may reside in the doneq directory. 350 ''; 351 }; 352 faxqclean.docqMinutes = mkOption { 353 type = ints.positive; 354 default = 60; 355 example = literalExpression "24*60"; 356 description = lib.mdDoc '' 357 Set the document 358 age threshold (in minutes) that controls how long 359 unreferenced files may reside in the docq directory. 360 ''; 361 }; 362 363 }; 364 365 366 config.services.hylafax = 367 mkIf 368 (config.services.hylafax.enable) 369 (mkMerge [ defaultConfig localConfig ]) 370 ; 371 372}