mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-11 20:25:32 +03:00

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-builda08b3a4d19
.tar.gz \ --argstr baseRevb32a094368
result/bin/apply-formatting $NIXPKGS_PATH
547 lines
16 KiB
Nix
547 lines
16 KiB
Nix
{
|
||
config,
|
||
options,
|
||
pkgs,
|
||
lib,
|
||
...
|
||
}:
|
||
|
||
with lib;
|
||
|
||
let
|
||
|
||
cfg = config.services.rspamd;
|
||
opt = options.services.rspamd;
|
||
postfixCfg = config.services.postfix;
|
||
|
||
bindSocketOpts =
|
||
{ options, config, ... }:
|
||
{
|
||
options = {
|
||
socket = mkOption {
|
||
type = types.str;
|
||
example = "localhost:11333";
|
||
description = ''
|
||
Socket for this worker to listen on in a format acceptable by rspamd.
|
||
'';
|
||
};
|
||
mode = mkOption {
|
||
type = types.str;
|
||
default = "0644";
|
||
description = "Mode to set on unix socket";
|
||
};
|
||
owner = mkOption {
|
||
type = types.str;
|
||
default = "${cfg.user}";
|
||
description = "Owner to set on unix socket";
|
||
};
|
||
group = mkOption {
|
||
type = types.str;
|
||
default = "${cfg.group}";
|
||
description = "Group to set on unix socket";
|
||
};
|
||
rawEntry = mkOption {
|
||
type = types.str;
|
||
internal = true;
|
||
};
|
||
};
|
||
config.rawEntry =
|
||
let
|
||
maybeOption = option: optionalString options.${option}.isDefined " ${option}=${config.${option}}";
|
||
in
|
||
if (!(hasPrefix "/" config.socket)) then
|
||
"${config.socket}"
|
||
else
|
||
"${config.socket}${maybeOption "mode"}${maybeOption "owner"}${maybeOption "group"}";
|
||
};
|
||
|
||
traceWarning = w: x: builtins.trace "[1;31mwarning: ${w}[0m" x;
|
||
|
||
workerOpts =
|
||
{ name, options, ... }:
|
||
{
|
||
options = {
|
||
enable = mkOption {
|
||
type = types.nullOr types.bool;
|
||
default = null;
|
||
description = "Whether to run the rspamd worker.";
|
||
};
|
||
name = mkOption {
|
||
type = types.nullOr types.str;
|
||
default = name;
|
||
description = "Name of the worker";
|
||
};
|
||
type = mkOption {
|
||
type = types.nullOr (
|
||
types.enum [
|
||
"normal"
|
||
"controller"
|
||
"fuzzy"
|
||
"rspamd_proxy"
|
||
"lua"
|
||
"proxy"
|
||
]
|
||
);
|
||
description = ''
|
||
The type of this worker. The type `proxy` is
|
||
deprecated and only kept for backwards compatibility and should be
|
||
replaced with `rspamd_proxy`.
|
||
'';
|
||
apply =
|
||
let
|
||
from = "services.rspamd.workers.\"${name}\".type";
|
||
files = options.type.files;
|
||
warning = "The option `${from}` defined in ${showFiles files} has enum value `proxy` which has been renamed to `rspamd_proxy`";
|
||
in
|
||
x: if x == "proxy" then traceWarning warning "rspamd_proxy" else x;
|
||
};
|
||
bindSockets = mkOption {
|
||
type = types.listOf (types.either types.str (types.submodule bindSocketOpts));
|
||
default = [ ];
|
||
description = ''
|
||
List of sockets to listen, in format acceptable by rspamd
|
||
'';
|
||
example = [
|
||
{
|
||
socket = "/run/rspamd.sock";
|
||
mode = "0666";
|
||
owner = "rspamd";
|
||
}
|
||
"*:11333"
|
||
];
|
||
apply =
|
||
value:
|
||
map (
|
||
each:
|
||
if (isString each) then
|
||
if (isUnixSocket each) then
|
||
{
|
||
socket = each;
|
||
owner = cfg.user;
|
||
group = cfg.group;
|
||
mode = "0644";
|
||
rawEntry = "${each}";
|
||
}
|
||
else
|
||
{
|
||
socket = each;
|
||
rawEntry = "${each}";
|
||
}
|
||
else
|
||
each
|
||
) value;
|
||
};
|
||
count = mkOption {
|
||
type = types.nullOr types.int;
|
||
default = null;
|
||
description = ''
|
||
Number of worker instances to run
|
||
'';
|
||
};
|
||
includes = mkOption {
|
||
type = types.listOf types.str;
|
||
default = [ ];
|
||
description = ''
|
||
List of files to include in configuration
|
||
'';
|
||
};
|
||
extraConfig = mkOption {
|
||
type = types.lines;
|
||
default = "";
|
||
description = "Additional entries to put verbatim into worker section of rspamd config file.";
|
||
};
|
||
};
|
||
config =
|
||
mkIf (name == "normal" || name == "controller" || name == "fuzzy" || name == "rspamd_proxy")
|
||
{
|
||
type = mkDefault name;
|
||
includes = mkDefault [ "$CONFDIR/worker-${if name == "rspamd_proxy" then "proxy" else name}.inc" ];
|
||
bindSockets =
|
||
let
|
||
unixSocket = name: {
|
||
mode = "0660";
|
||
socket = "/run/rspamd/${name}.sock";
|
||
owner = cfg.user;
|
||
group = cfg.group;
|
||
};
|
||
in
|
||
mkDefault (
|
||
if name == "normal" then
|
||
[ (unixSocket "rspamd") ]
|
||
else if name == "controller" then
|
||
[ "localhost:11334" ]
|
||
else if name == "rspamd_proxy" then
|
||
[ (unixSocket "proxy") ]
|
||
else
|
||
[ ]
|
||
);
|
||
};
|
||
};
|
||
|
||
isUnixSocket = socket: hasPrefix "/" (if (isString socket) then socket else socket.socket);
|
||
|
||
mkBindSockets =
|
||
enabled: socks:
|
||
concatStringsSep "\n " (flatten (map (each: "bind_socket = \"${each.rawEntry}\";") socks));
|
||
|
||
rspamdConfFile = pkgs.writeText "rspamd.conf" ''
|
||
.include "$CONFDIR/common.conf"
|
||
|
||
options {
|
||
pidfile = "$RUNDIR/rspamd.pid";
|
||
.include "$CONFDIR/options.inc"
|
||
.include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/options.inc"
|
||
.include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/options.inc"
|
||
}
|
||
|
||
logging {
|
||
type = "syslog";
|
||
.include "$CONFDIR/logging.inc"
|
||
.include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/logging.inc"
|
||
.include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/logging.inc"
|
||
}
|
||
|
||
${concatStringsSep "\n" (
|
||
mapAttrsToList (
|
||
name: value:
|
||
let
|
||
includeName = if name == "rspamd_proxy" then "proxy" else name;
|
||
tryOverride = boolToString (value.extraConfig == "");
|
||
in
|
||
''
|
||
worker "${value.type}" {
|
||
type = "${value.type}";
|
||
${optionalString (value.enable != null)
|
||
"enabled = ${if value.enable != false then "yes" else "no"};"
|
||
}
|
||
${mkBindSockets value.enable value.bindSockets}
|
||
${optionalString (value.count != null) "count = ${toString value.count};"}
|
||
${concatStringsSep "\n " (map (each: ".include \"${each}\"") value.includes)}
|
||
.include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/worker-${includeName}.inc"
|
||
.include(try=${tryOverride}; priority=10) "$LOCAL_CONFDIR/override.d/worker-${includeName}.inc"
|
||
}
|
||
''
|
||
) cfg.workers
|
||
)}
|
||
|
||
${optionalString (cfg.extraConfig != "") ''
|
||
.include(priority=10) "$LOCAL_CONFDIR/override.d/extra-config.inc"
|
||
''}
|
||
'';
|
||
|
||
filterFiles = files: filterAttrs (n: v: v.enable) files;
|
||
rspamdDir = pkgs.linkFarm "etc-rspamd-dir" (
|
||
(mapAttrsToList (name: file: {
|
||
name = "local.d/${name}";
|
||
path = file.source;
|
||
}) (filterFiles cfg.locals))
|
||
++ (mapAttrsToList (name: file: {
|
||
name = "override.d/${name}";
|
||
path = file.source;
|
||
}) (filterFiles cfg.overrides))
|
||
++ (optional (cfg.localLuaRules != null) {
|
||
name = "rspamd.local.lua";
|
||
path = cfg.localLuaRules;
|
||
})
|
||
++ [
|
||
{
|
||
name = "rspamd.conf";
|
||
path = rspamdConfFile;
|
||
}
|
||
]
|
||
);
|
||
|
||
configFileModule =
|
||
prefix:
|
||
{ name, config, ... }:
|
||
{
|
||
options = {
|
||
enable = mkOption {
|
||
type = types.bool;
|
||
default = true;
|
||
description = ''
|
||
Whether this file ${prefix} should be generated. This
|
||
option allows specific ${prefix} files to be disabled.
|
||
'';
|
||
};
|
||
|
||
text = mkOption {
|
||
default = null;
|
||
type = types.nullOr types.lines;
|
||
description = "Text of the file.";
|
||
};
|
||
|
||
source = mkOption {
|
||
type = types.path;
|
||
description = "Path of the source file.";
|
||
};
|
||
};
|
||
config = {
|
||
source = mkIf (config.text != null) (
|
||
let
|
||
name' = "rspamd-${prefix}-" + baseNameOf name;
|
||
in
|
||
mkDefault (pkgs.writeText name' config.text)
|
||
);
|
||
};
|
||
};
|
||
|
||
configOverrides =
|
||
(mapAttrs' (
|
||
n: v:
|
||
nameValuePair "worker-${if n == "rspamd_proxy" then "proxy" else n}.inc" {
|
||
text = v.extraConfig;
|
||
}
|
||
) (filterAttrs (n: v: v.extraConfig != "") cfg.workers))
|
||
// (lib.optionalAttrs (cfg.extraConfig != "") {
|
||
"extra-config.inc".text = cfg.extraConfig;
|
||
});
|
||
in
|
||
|
||
{
|
||
###### interface
|
||
|
||
options = {
|
||
|
||
services.rspamd = {
|
||
|
||
enable = mkEnableOption "rspamd, the Rapid spam filtering system";
|
||
|
||
debug = mkOption {
|
||
type = types.bool;
|
||
default = false;
|
||
description = "Whether to run the rspamd daemon in debug mode.";
|
||
};
|
||
|
||
locals = mkOption {
|
||
type = with types; attrsOf (submodule (configFileModule "locals"));
|
||
default = { };
|
||
description = ''
|
||
Local configuration files, written into {file}`/etc/rspamd/local.d/{name}`.
|
||
'';
|
||
example = literalExpression ''
|
||
{ "redis.conf".source = "/nix/store/.../etc/dir/redis.conf";
|
||
"arc.conf".text = "allow_envfrom_empty = true;";
|
||
}
|
||
'';
|
||
};
|
||
|
||
overrides = mkOption {
|
||
type = with types; attrsOf (submodule (configFileModule "overrides"));
|
||
default = { };
|
||
description = ''
|
||
Overridden configuration files, written into {file}`/etc/rspamd/override.d/{name}`.
|
||
'';
|
||
example = literalExpression ''
|
||
{ "redis.conf".source = "/nix/store/.../etc/dir/redis.conf";
|
||
"arc.conf".text = "allow_envfrom_empty = true;";
|
||
}
|
||
'';
|
||
};
|
||
|
||
localLuaRules = mkOption {
|
||
default = null;
|
||
type = types.nullOr types.path;
|
||
description = ''
|
||
Path of file to link to {file}`/etc/rspamd/rspamd.local.lua` for local
|
||
rules written in Lua
|
||
'';
|
||
};
|
||
|
||
workers = mkOption {
|
||
type = with types; attrsOf (submodule workerOpts);
|
||
description = ''
|
||
Attribute set of workers to start.
|
||
'';
|
||
default = {
|
||
normal = { };
|
||
controller = { };
|
||
};
|
||
example = literalExpression ''
|
||
{
|
||
normal = {
|
||
includes = [ "$CONFDIR/worker-normal.inc" ];
|
||
bindSockets = [{
|
||
socket = "/run/rspamd/rspamd.sock";
|
||
mode = "0660";
|
||
owner = "''${config.${opt.user}}";
|
||
group = "''${config.${opt.group}}";
|
||
}];
|
||
};
|
||
controller = {
|
||
includes = [ "$CONFDIR/worker-controller.inc" ];
|
||
bindSockets = [ "[::1]:11334" ];
|
||
};
|
||
}
|
||
'';
|
||
};
|
||
|
||
extraConfig = mkOption {
|
||
type = types.lines;
|
||
default = "";
|
||
description = ''
|
||
Extra configuration to add at the end of the rspamd configuration
|
||
file.
|
||
'';
|
||
};
|
||
|
||
user = mkOption {
|
||
type = types.str;
|
||
default = "rspamd";
|
||
description = ''
|
||
User to use when no root privileges are required.
|
||
'';
|
||
};
|
||
|
||
group = mkOption {
|
||
type = types.str;
|
||
default = "rspamd";
|
||
description = ''
|
||
Group to use when no root privileges are required.
|
||
'';
|
||
};
|
||
|
||
postfix = {
|
||
enable = mkOption {
|
||
type = types.bool;
|
||
default = false;
|
||
description = "Add rspamd milter to postfix main.conf";
|
||
};
|
||
|
||
config = mkOption {
|
||
type =
|
||
with types;
|
||
attrsOf (oneOf [
|
||
bool
|
||
str
|
||
(listOf str)
|
||
]);
|
||
description = ''
|
||
Addon to postfix configuration
|
||
'';
|
||
default = {
|
||
smtpd_milters = [ "unix:/run/rspamd/rspamd-milter.sock" ];
|
||
non_smtpd_milters = [ "unix:/run/rspamd/rspamd-milter.sock" ];
|
||
};
|
||
};
|
||
};
|
||
};
|
||
};
|
||
|
||
###### implementation
|
||
|
||
config = mkIf cfg.enable {
|
||
services.rspamd.overrides = configOverrides;
|
||
services.rspamd.workers = mkIf cfg.postfix.enable {
|
||
controller = { };
|
||
rspamd_proxy = {
|
||
bindSockets = [
|
||
{
|
||
mode = "0660";
|
||
socket = "/run/rspamd/rspamd-milter.sock";
|
||
owner = cfg.user;
|
||
group = postfixCfg.group;
|
||
}
|
||
];
|
||
extraConfig = ''
|
||
upstream "local" {
|
||
default = yes; # Self-scan upstreams are always default
|
||
self_scan = yes; # Enable self-scan
|
||
}
|
||
'';
|
||
};
|
||
};
|
||
services.postfix.config = mkIf cfg.postfix.enable cfg.postfix.config;
|
||
|
||
systemd.services.postfix = mkIf cfg.postfix.enable {
|
||
serviceConfig.SupplementaryGroups = [ postfixCfg.group ];
|
||
};
|
||
|
||
# Allow users to run 'rspamc' and 'rspamadm'.
|
||
environment.systemPackages = [ pkgs.rspamd ];
|
||
|
||
users.users.${cfg.user} = {
|
||
description = "rspamd daemon";
|
||
uid = config.ids.uids.rspamd;
|
||
group = cfg.group;
|
||
};
|
||
|
||
users.groups.${cfg.group} = {
|
||
gid = config.ids.gids.rspamd;
|
||
};
|
||
|
||
environment.etc.rspamd.source = rspamdDir;
|
||
|
||
systemd.services.rspamd = {
|
||
description = "Rspamd Service";
|
||
|
||
wantedBy = [ "multi-user.target" ];
|
||
after = [ "network.target" ];
|
||
restartTriggers = [ rspamdDir ];
|
||
|
||
serviceConfig = {
|
||
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} -c /etc/rspamd/rspamd.conf -f";
|
||
Restart = "always";
|
||
|
||
User = "${cfg.user}";
|
||
Group = "${cfg.group}";
|
||
SupplementaryGroups = mkIf cfg.postfix.enable [ postfixCfg.group ];
|
||
|
||
RuntimeDirectory = "rspamd";
|
||
RuntimeDirectoryMode = "0755";
|
||
StateDirectory = "rspamd";
|
||
StateDirectoryMode = "0700";
|
||
|
||
AmbientCapabilities = [ ];
|
||
CapabilityBoundingSet = "";
|
||
DevicePolicy = "closed";
|
||
LockPersonality = true;
|
||
NoNewPrivileges = true;
|
||
PrivateDevices = true;
|
||
PrivateMounts = true;
|
||
PrivateTmp = true;
|
||
# we need to chown socket to rspamd-milter
|
||
PrivateUsers = !cfg.postfix.enable;
|
||
ProtectClock = true;
|
||
ProtectControlGroups = true;
|
||
ProtectHome = true;
|
||
ProtectHostname = true;
|
||
ProtectKernelLogs = true;
|
||
ProtectKernelModules = true;
|
||
ProtectKernelTunables = true;
|
||
ProtectSystem = "strict";
|
||
RemoveIPC = true;
|
||
RestrictAddressFamilies = [
|
||
"AF_INET"
|
||
"AF_INET6"
|
||
"AF_UNIX"
|
||
];
|
||
RestrictNamespaces = true;
|
||
RestrictRealtime = true;
|
||
RestrictSUIDSGID = true;
|
||
SystemCallArchitectures = "native";
|
||
SystemCallFilter = "@system-service";
|
||
UMask = "0077";
|
||
};
|
||
};
|
||
};
|
||
imports = [
|
||
(mkRemovedOptionModule [
|
||
"services"
|
||
"rspamd"
|
||
"socketActivation"
|
||
] "Socket activation never worked correctly and could at this time not be fixed and so was removed")
|
||
(mkRenamedOptionModule
|
||
[ "services" "rspamd" "bindSocket" ]
|
||
[ "services" "rspamd" "workers" "normal" "bindSockets" ]
|
||
)
|
||
(mkRenamedOptionModule
|
||
[ "services" "rspamd" "bindUISocket" ]
|
||
[ "services" "rspamd" "workers" "controller" "bindSockets" ]
|
||
)
|
||
(mkRemovedOptionModule [
|
||
"services"
|
||
"rmilter"
|
||
] "Use services.rspamd.* instead to set up milter service")
|
||
];
|
||
}
|