0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-19 08:31:01 +03:00
nixpkgs/nixos/modules/services/networking/hylafax/systemd.nix
Silvan Mosberger d9d87c5196 treewide: format all inactive Nix files
After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build https://github.com/infinisil/treewide-nixpkgs-reformat-script/archive/a08b3a4d199c6124ac5b36a889d9099b4383463f.tar.gz \
      --argstr baseRev 0128fbb0a5
    result/bin/apply-formatting $NIXPKGS_PATH
2024-12-10 20:29:24 +01:00

255 lines
8.9 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkIf mkMerge;
inherit (lib) concatStringsSep optionalString;
cfg = config.services.hylafax;
mapModems = lib.forEach (lib.attrValues cfg.modems);
mkConfigFile =
name: conf:
# creates hylafax config file,
# makes sure "Include" is listed *first*
let
mkLines = lib.flip lib.pipe [
(lib.mapAttrsToList (key: map (val: "${key}: ${val}")))
lib.concatLists
];
include = mkLines { Include = conf.Include or [ ]; };
other = mkLines (conf // { Include = [ ]; });
in
pkgs.writeText "hylafax-config${name}" (concatStringsSep "\n" (include ++ other));
globalConfigPath = mkConfigFile "" cfg.faxqConfig;
modemConfigPath =
let
mkModemConfigFile =
{ config, name, ... }: mkConfigFile ".${name}" (cfg.commonModemConfig // config);
mkLine =
{ name, type, ... }@modem:
''
# check if modem config file exists:
test -f "${pkgs.hylafaxplus}/spool/config/${type}"
ln \
--symbolic \
--no-target-directory \
"${mkModemConfigFile modem}" \
"$out/config.${name}"
'';
in
pkgs.runCommand "hylafax-config-modems" {
preferLocalBuild = true;
} ''mkdir --parents "$out/" ${concatStringsSep "\n" (mapModems mkLine)}'';
setupSpoolScript = pkgs.substituteAll {
name = "hylafax-setup-spool.sh";
src = ./spool.sh;
isExecutable = true;
faxuser = "uucp";
faxgroup = "uucp";
lockPath = "/var/lock";
inherit globalConfigPath modemConfigPath;
inherit (cfg) sendmailPath spoolAreaPath userAccessFile;
inherit (pkgs) hylafaxplus runtimeShell;
};
waitFaxqScript = pkgs.substituteAll {
# This script checks the modems status files
# and waits until all modems report readiness.
name = "hylafax-faxq-wait-start.sh";
src = ./faxq-wait.sh;
isExecutable = true;
timeoutSec = toString 10;
inherit (cfg) spoolAreaPath;
inherit (pkgs) runtimeShell;
};
sockets.hylafax-hfaxd = {
description = "HylaFAX server socket";
documentation = [ "man:hfaxd(8)" ];
wantedBy = [ "multi-user.target" ];
listenStreams = [ "127.0.0.1:4559" ];
socketConfig.FreeBind = true;
socketConfig.Accept = true;
};
paths.hylafax-faxq = {
description = "HylaFAX queue manager sendq watch";
documentation = [
"man:faxq(8)"
"man:sendq(5)"
];
wantedBy = [ "multi-user.target" ];
pathConfig.PathExistsGlob = [ "${cfg.spoolAreaPath}/sendq/q*" ];
};
timers = mkMerge [
(mkIf (cfg.faxcron.enable.frequency != null) { hylafax-faxcron.timerConfig.Persistent = true; })
(mkIf (cfg.faxqclean.enable.frequency != null) { hylafax-faxqclean.timerConfig.Persistent = true; })
];
hardenService =
# Add some common systemd service hardening settings,
# but allow each service (here) to override
# settings by explicitly setting those to `null`.
# More hardening would be nice but makes
# customizing hylafax setups very difficult.
# If at all, it should only be added along
# with some options to customize it.
let
hardening = {
PrivateDevices = true; # breaks /dev/tty...
PrivateNetwork = true;
PrivateTmp = true;
#ProtectClock = true; # breaks /dev/tty... (why?)
ProtectControlGroups = true;
#ProtectHome = true; # breaks custom spool dirs
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
#ProtectSystem = "strict"; # breaks custom spool dirs
RestrictNamespaces = true;
RestrictRealtime = true;
};
filter = key: value: (value != null) || !(lib.hasAttr key hardening);
apply = service: lib.filterAttrs filter (hardening // (service.serviceConfig or { }));
in
service: service // { serviceConfig = apply service; };
services.hylafax-spool = {
description = "HylaFAX spool area preparation";
documentation = [ "man:hylafax-server(4)" ];
script = ''
${setupSpoolScript}
cd "${cfg.spoolAreaPath}"
${cfg.spoolExtraInit}
if ! test -f "${cfg.spoolAreaPath}/etc/hosts.hfaxd"
then
echo hosts.hfaxd is missing
exit 1
fi
'';
serviceConfig.ExecStop = "${setupSpoolScript}";
serviceConfig.RemainAfterExit = true;
serviceConfig.Type = "oneshot";
unitConfig.RequiresMountsFor = [ cfg.spoolAreaPath ];
};
services.hylafax-faxq = {
description = "HylaFAX queue manager";
documentation = [ "man:faxq(8)" ];
requires = [ "hylafax-spool.service" ];
after = [ "hylafax-spool.service" ];
wants = mapModems ({ name, ... }: "hylafax-faxgetty@${name}.service");
wantedBy = mkIf cfg.autostart [ "multi-user.target" ];
serviceConfig.Type = "forking";
serviceConfig.ExecStart = ''${pkgs.hylafaxplus}/spool/bin/faxq -q "${cfg.spoolAreaPath}"'';
# This delays the "readiness" of this service until
# all modems are initialized (or a timeout is reached).
# Otherwise, sending a fax with the fax service
# stopped will always yield a failed send attempt:
# The fax service is started when the job is created with
# `sendfax`, but modems need some time to initialize.
serviceConfig.ExecStartPost = [ "${waitFaxqScript}" ];
# faxquit fails if the pipe is already gone
# (e.g. the service is already stopping)
serviceConfig.ExecStop = ''-${pkgs.hylafaxplus}/spool/bin/faxquit -q "${cfg.spoolAreaPath}"'';
# disable some systemd hardening settings
serviceConfig.PrivateDevices = null;
serviceConfig.RestrictRealtime = null;
};
services."hylafax-hfaxd@" = {
description = "HylaFAX server";
documentation = [ "man:hfaxd(8)" ];
after = [ "hylafax-faxq.service" ];
requires = [ "hylafax-faxq.service" ];
serviceConfig.StandardInput = "socket";
serviceConfig.StandardOutput = "socket";
serviceConfig.ExecStart = ''${pkgs.hylafaxplus}/spool/bin/hfaxd -q "${cfg.spoolAreaPath}" -d -I'';
unitConfig.RequiresMountsFor = [ cfg.userAccessFile ];
# disable some systemd hardening settings
serviceConfig.PrivateDevices = null;
serviceConfig.PrivateNetwork = null;
};
services.hylafax-faxcron = rec {
description = "HylaFAX spool area maintenance";
documentation = [ "man:faxcron(8)" ];
after = [ "hylafax-spool.service" ];
requires = [ "hylafax-spool.service" ];
wantedBy = mkIf cfg.faxcron.enable.spoolInit requires;
startAt = mkIf (cfg.faxcron.enable.frequency != null) cfg.faxcron.enable.frequency;
serviceConfig.ExecStart = concatStringsSep " " [
"${pkgs.hylafaxplus}/spool/bin/faxcron"
''-q "${cfg.spoolAreaPath}"''
''-info ${toString cfg.faxcron.infoDays}''
''-log ${toString cfg.faxcron.logDays}''
''-rcv ${toString cfg.faxcron.rcvDays}''
];
};
services.hylafax-faxqclean = rec {
description = "HylaFAX spool area queue cleaner";
documentation = [ "man:faxqclean(8)" ];
after = [ "hylafax-spool.service" ];
requires = [ "hylafax-spool.service" ];
wantedBy = mkIf cfg.faxqclean.enable.spoolInit requires;
startAt = mkIf (cfg.faxqclean.enable.frequency != null) cfg.faxqclean.enable.frequency;
serviceConfig.ExecStart = concatStringsSep " " [
"${pkgs.hylafaxplus}/spool/bin/faxqclean"
''-q "${cfg.spoolAreaPath}"''
"-v"
(optionalString (cfg.faxqclean.archiving != "never") "-a")
(optionalString (cfg.faxqclean.archiving == "always") "-A")
''-j ${toString (cfg.faxqclean.doneqMinutes * 60)}''
''-d ${toString (cfg.faxqclean.docqMinutes * 60)}''
];
};
mkFaxgettyService =
{ name, ... }:
lib.nameValuePair "hylafax-faxgetty@${name}" rec {
description = "HylaFAX faxgetty for %I";
documentation = [ "man:faxgetty(8)" ];
bindsTo = [ "dev-%i.device" ];
requires = [ "hylafax-spool.service" ];
after = bindsTo ++ requires;
before = [
"hylafax-faxq.service"
"getty.target"
];
unitConfig.StopWhenUnneeded = true;
unitConfig.AssertFileNotEmpty = "${cfg.spoolAreaPath}/etc/config.%I";
serviceConfig.UtmpIdentifier = "%I";
serviceConfig.TTYPath = "/dev/%I";
serviceConfig.Restart = "always";
serviceConfig.KillMode = "process";
serviceConfig.IgnoreSIGPIPE = false;
serviceConfig.ExecStart = ''-${pkgs.hylafaxplus}/spool/bin/faxgetty -q "${cfg.spoolAreaPath}" /dev/%I'';
# faxquit fails if the pipe is already gone
# (e.g. the service is already stopping)
serviceConfig.ExecStop = ''-${pkgs.hylafaxplus}/spool/bin/faxquit -q "${cfg.spoolAreaPath}" %I'';
# disable some systemd hardening settings
serviceConfig.PrivateDevices = null;
serviceConfig.RestrictRealtime = null;
};
modemServices = lib.listToAttrs (mapModems mkFaxgettyService);
in
{
config.systemd = mkIf cfg.enable {
inherit sockets timers paths;
services = lib.mapAttrs (lib.const hardenService) (services // modemServices);
};
}