treewide: reformat with nixfmt-rfc-style

This commit is contained in:
Martin Weinelt 2025-06-15 03:39:44 +02:00
parent 03433d472f
commit 1a7f3d718c
No known key found for this signature in database
GPG key ID: 87C1E9888F856759
21 changed files with 2086 additions and 1680 deletions

View file

@ -14,7 +14,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
@ -56,14 +61,17 @@ in
domains = mkOption {
type = types.listOf types.str;
example = [ "example.com" ];
default = [];
default = [ ];
description = "The domains that this mail server serves.";
};
certificateDomains = mkOption {
type = types.listOf types.str;
example = [ "imap.example.com" "pop3.example.com" ];
default = [];
example = [
"imap.example.com"
"pop3.example.com"
];
default = [ ];
description = ''
({option}`mailserver.certificateScheme` == `acme-nginx`)
@ -79,130 +87,141 @@ in
};
loginAccounts = mkOption {
type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
name = mkOption {
type = types.str;
example = "user1@example.com";
description = "Username";
};
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
options = {
name = mkOption {
type = types.str;
example = "user1@example.com";
description = "Username";
};
hashedPassword = mkOption {
type = with types; nullOr str;
default = null;
example = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
description = ''
The user's hashed password. Use `mkpasswd` as follows
hashedPassword = mkOption {
type = with types; nullOr str;
default = null;
example = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
description = ''
The user's hashed password. Use `mkpasswd` as follows
```
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
```
```
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
```
Warning: this is stored in plaintext in the Nix store!
Use {option}`mailserver.loginAccounts.<name>.hashedPasswordFile` instead.
'';
};
Warning: this is stored in plaintext in the Nix store!
Use {option}`mailserver.loginAccounts.<name>.hashedPasswordFile` instead.
'';
};
hashedPasswordFile = mkOption {
type = with types; nullOr path;
default = null;
example = "/run/keys/user1-passwordhash";
description = ''
A file containing the user's hashed password. Use `mkpasswd` as follows
hashedPasswordFile = mkOption {
type = with types; nullOr path;
default = null;
example = "/run/keys/user1-passwordhash";
description = ''
A file containing the user's hashed password. Use `mkpasswd` as follows
```
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
```
'';
};
```
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
```
'';
};
aliases = mkOption {
type = with types; listOf types.str;
example = ["abuse@example.com" "postmaster@example.com"];
default = [];
description = ''
A list of aliases of this login account.
Note: Use list entries like "@example.com" to create a catchAll
that allows sending from all email addresses in these domain.
'';
};
aliases = mkOption {
type = with types; listOf types.str;
example = [
"abuse@example.com"
"postmaster@example.com"
];
default = [ ];
description = ''
A list of aliases of this login account.
Note: Use list entries like "@example.com" to create a catchAll
that allows sending from all email addresses in these domain.
'';
};
aliasesRegexp = mkOption {
type = with types; listOf types.str;
example = [''/^tom\..*@domain\.com$/''];
default = [];
description = ''
Same as {option}`mailserver.aliases` but using PCRE (Perl compatible regex).
'';
};
aliasesRegexp = mkOption {
type = with types; listOf types.str;
example = [ ''/^tom\..*@domain\.com$/'' ];
default = [ ];
description = ''
Same as {option}`mailserver.aliases` but using PCRE (Perl compatible regex).
'';
};
catchAll = mkOption {
type = with types; listOf (enum cfg.domains);
example = ["example.com" "example2.com"];
default = [];
description = ''
For which domains should this account act as a catch all?
Note: Does not allow sending from all addresses of these domains.
'';
};
catchAll = mkOption {
type = with types; listOf (enum cfg.domains);
example = [
"example.com"
"example2.com"
];
default = [ ];
description = ''
For which domains should this account act as a catch all?
Note: Does not allow sending from all addresses of these domains.
'';
};
quota = mkOption {
type = with types; nullOr types.str;
default = null;
example = "2G";
description = ''
Per user quota rules. Accepted sizes are `xx k/M/G/T` with the
obvious meaning. Leave blank for the standard quota `100G`.
'';
};
quota = mkOption {
type = with types; nullOr types.str;
default = null;
example = "2G";
description = ''
Per user quota rules. Accepted sizes are `xx k/M/G/T` with the
obvious meaning. Leave blank for the standard quota `100G`.
'';
};
sieveScript = mkOption {
type = with types; nullOr lines;
default = null;
example = ''
require ["fileinto", "mailbox"];
sieveScript = mkOption {
type = with types; nullOr lines;
default = null;
example = ''
require ["fileinto", "mailbox"];
if address :is "from" "gitlab@mg.gitlab.com" {
fileinto :create "GitLab";
stop;
}
if address :is "from" "gitlab@mg.gitlab.com" {
fileinto :create "GitLab";
stop;
}
# This must be the last rule, it will check if list-id is set, and
# file the message into the Lists folder for further investigation
elsif header :matches "list-id" "<?*>" {
fileinto :create "Lists";
stop;
}
'';
description = ''
Per-user sieve script.
'';
};
# This must be the last rule, it will check if list-id is set, and
# file the message into the Lists folder for further investigation
elsif header :matches "list-id" "<?*>" {
fileinto :create "Lists";
stop;
}
'';
description = ''
Per-user sieve script.
'';
};
sendOnly = mkOption {
type = types.bool;
default = false;
description = ''
Specifies if the account should be a send-only account.
Emails sent to send-only accounts will be rejected from
unauthorized senders with the `sendOnlyRejectMessage`
stating the reason.
'';
};
sendOnly = mkOption {
type = types.bool;
default = false;
description = ''
Specifies if the account should be a send-only account.
Emails sent to send-only accounts will be rejected from
unauthorized senders with the `sendOnlyRejectMessage`
stating the reason.
'';
};
sendOnlyRejectMessage = mkOption {
type = types.str;
default = "This account cannot receive emails.";
description = ''
The message that will be returned to the sender when an email is
sent to a send-only account. Only used if the account is marked
as send-only.
'';
};
};
sendOnlyRejectMessage = mkOption {
type = types.str;
default = "This account cannot receive emails.";
description = ''
The message that will be returned to the sender when an email is
sent to a send-only account. Only used if the account is marked
as send-only.
'';
};
};
config.name = mkDefault name;
}));
config.name = mkDefault name;
}
)
);
example = {
user1 = {
hashedPassword = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
@ -220,13 +239,13 @@ in
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
```
'';
default = {};
default = { };
};
ldap = {
enable = mkEnableOption "LDAP support";
uris = mkOption {
uris = mkOption {
type = types.listOf types.str;
example = literalExpression ''
[
@ -284,7 +303,11 @@ in
};
searchScope = mkOption {
type = types.enum [ "sub" "base" "one" ];
type = types.enum [
"sub"
"base"
"one"
];
default = "sub";
description = ''
Search scope below which users accounts are looked for.
@ -419,14 +442,22 @@ in
autoIndexExclude = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "\\Trash" "SomeFolder" "Other/*" ];
example = [
"\\Trash"
"SomeFolder"
"Other/*"
];
description = ''
Mailboxes to exclude from automatic indexing.
'';
};
enforced = mkOption {
type = types.enum [ "yes" "no" "body" ];
type = types.enum [
"yes"
"no"
"body"
];
default = "no";
description = ''
Fail searches when no index is available. If set to
@ -439,7 +470,10 @@ in
languages = mkOption {
type = types.nonEmptyListOf types.str;
default = [ "en" ];
example = [ "en" "de" ];
example = [
"en"
"de"
];
description = ''
A list of languages that the full text search should detect.
At least one language must be specified.
@ -488,7 +522,10 @@ in
};
lmtpSaveToDetailMailbox = mkOption {
type = types.enum ["yes" "no"];
type = types.enum [
"yes"
"no"
];
default = "yes";
description = ''
If an email address is delimited by a "+", should it be filed into a
@ -514,17 +551,23 @@ in
};
extraVirtualAliases = mkOption {
type = let
loginAccount = mkOptionType {
name = "Login Account";
check = account: builtins.elem account (builtins.attrNames cfg.loginAccounts);
};
in with types; attrsOf (either loginAccount (nonEmptyListOf loginAccount));
type =
let
loginAccount = mkOptionType {
name = "Login Account";
check = account: builtins.elem account (builtins.attrNames cfg.loginAccounts);
};
in
with types;
attrsOf (either loginAccount (nonEmptyListOf loginAccount));
example = {
"info@example.com" = "user1@example.com";
"postmaster@example.com" = "user1@example.com";
"abuse@example.com" = "user1@example.com";
"multi@example.com" = [ "user1@example.com" "user2@example.com" ];
"multi@example.com" = [
"user1@example.com"
"user2@example.com"
];
};
description = ''
Virtual Aliases. A virtual alias `"info@example.com" = "user1@example.com"` means that
@ -537,7 +580,7 @@ in
example all mails for `multi@example.com` will be forwarded to both
`user1@example.com` and `user2@example.com`.
'';
default = {};
default = { };
};
forwards = mkOption {
@ -554,28 +597,34 @@ in
can't send mail as `user@example.com`. Also, this option
allows to forward mails to external addresses.
'';
default = {};
default = { };
};
rejectSender = mkOption {
type = types.listOf types.str;
example = [ "example.com" "spammer@example.net" ];
example = [
"example.com"
"spammer@example.net"
];
description = ''
Reject emails from these addresses from unauthorized senders.
Use if a spammer is using the same domain or the same sender over and over.
'';
default = [];
default = [ ];
};
rejectRecipients = mkOption {
type = types.listOf types.str;
example = [ "sales@example.com" "info@example.com" ];
example = [
"sales@example.com"
"info@example.com"
];
description = ''
Reject emails addressed to these local addresses from unauthorized senders.
Use if a spammer has found email addresses in a catchall domain but you do
not want to disable the catchall.
'';
default = [];
default = [ ];
};
vmailUID = mkOption {
@ -673,28 +722,46 @@ in
};
};
certificateScheme = let
schemes = [ "manual" "selfsigned" "acme-nginx" "acme" ];
translate = i: warn "Setting mailserver.certificateScheme by number is deprecated, please use names instead: 'mailserver.certificateScheme = ${builtins.toString i}' can be replaced by 'mailserver.certificateScheme = \"${(builtins.elemAt schemes (i - 1))}\"'."
(builtins.elemAt schemes (i - 1));
in mkOption {
type = with types; coercedTo (enum [ 1 2 3 ]) translate (enum schemes);
default = "selfsigned";
description = ''
The scheme to use for managing TLS certificates:
certificateScheme =
let
schemes = [
"manual"
"selfsigned"
"acme-nginx"
"acme"
];
translate =
i:
warn
"Setting mailserver.certificateScheme by number is deprecated, please use names instead: 'mailserver.certificateScheme = ${builtins.toString i}' can be replaced by 'mailserver.certificateScheme = \"${
(builtins.elemAt schemes (i - 1))
}\"'."
(builtins.elemAt schemes (i - 1));
in
mkOption {
type =
with types;
coercedTo (enum [
1
2
3
]) translate (enum schemes);
default = "selfsigned";
description = ''
The scheme to use for managing TLS certificates:
1. `manual`: you specify locations via {option}`mailserver.certificateFile` and
{option}`mailserver.keyFile` and manually copy certificates there.
2. `selfsigned`: you let the server create new (self-signed) certificates on the fly.
3. `acme-nginx`: you let the server request certificates from [Let's Encrypt](https://letsencrypt.org)
via NixOS' ACME module. By default, this will set up a stripped-down Nginx server for
{option}`mailserver.fqdn` and open port 80. For this to work, the FQDN must be properly
configured to point to your server (see the [setup guide](setup-guide.rst) for more information).
4. `acme`: you already have an ACME certificate set up (for example, you're already running a TLS-enabled
Nginx server on the FQDN). This is better than `manual` because the appropriate services will be reloaded
when the certificate is renewed.
'';
};
1. `manual`: you specify locations via {option}`mailserver.certificateFile` and
{option}`mailserver.keyFile` and manually copy certificates there.
2. `selfsigned`: you let the server create new (self-signed) certificates on the fly.
3. `acme-nginx`: you let the server request certificates from [Let's Encrypt](https://letsencrypt.org)
via NixOS' ACME module. By default, this will set up a stripped-down Nginx server for
{option}`mailserver.fqdn` and open port 80. For this to work, the FQDN must be properly
configured to point to your server (see the [setup guide](setup-guide.rst) for more information).
4. `acme`: you already have an ACME certificate set up (for example, you're already running a TLS-enabled
Nginx server on the FQDN). This is better than `manual` because the appropriate services will be reloaded
when the certificate is renewed.
'';
};
certificateFile = mkOption {
type = types.path;
@ -851,7 +918,10 @@ in
};
dkimKeyType = mkOption {
type = types.enum [ "rsa" "ed25519" ];
type = types.enum [
"rsa"
"ed25519"
];
default = "rsa";
description = ''
The key type used for generating DKIM keys. ED25519 was introduced in RFC6376 (2018).
@ -864,16 +934,16 @@ in
};
dkimKeyBits = mkOption {
type = types.int;
default = 1024;
description = ''
How many bits in generated DKIM keys. RFC6376 advises minimum 1024-bit keys.
type = types.int;
default = 1024;
description = ''
How many bits in generated DKIM keys. RFC6376 advises minimum 1024-bit keys.
If you have already deployed a key with a different number of bits than specified
here, then you should use a different selector ({option}`mailserver.dkimSelector`). In order to get
this package to generate a key with the new number of bits, you will either have to
change the selector or delete the old key file.
'';
If you have already deployed a key with a different number of bits than specified
here, then you should use a different selector ({option}`mailserver.dkimSelector`). In order to get
this package to generate a key with the new number of bits, you will either have to
change the selector or delete the old key file.
'';
};
dmarcReporting = {
@ -938,7 +1008,7 @@ in
excludeDomains = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
description = ''
List of domains or eSLDs to be excluded from DMARC reports.
'';
@ -1150,7 +1220,15 @@ in
compression = {
method = mkOption {
type = types.nullOr (types.enum ["none" "lz4" "zstd" "zlib" "lzma"]);
type = types.nullOr (
types.enum [
"none"
"lz4"
"zstd"
"zlib"
"lzma"
]
);
default = null;
description = "Leaving this unset allows borg to choose. The default for borg 1.1.4 is lz4.";
};
@ -1208,14 +1286,14 @@ in
locations = mkOption {
type = types.listOf types.path;
default = [cfg.mailDirectory];
default = [ cfg.mailDirectory ];
defaultText = lib.literalExpression "[ config.mailserver.mailDirectory ]";
description = "The locations that are to be backed up by borg.";
};
extraArgumentsForInit = mkOption {
type = types.listOf types.str;
default = ["--critical"];
default = [ "--critical" ];
description = "Additional arguments to add to the borg init command line.";
};
@ -1295,9 +1373,9 @@ in
cronIntervals = mkOption {
type = types.attrsOf types.str;
default = {
# minute, hour, day-in-month, month, weekday (0 = sunday)
# minute, hour, day-in-month, month, weekday (0 = sunday)
hourly = " 0 * * * *"; # Every full hour
daily = "30 3 * * *"; # Every day at 3:30
daily = "30 3 * * *"; # Every day at 3:30
weekly = " 0 5 * * 0"; # Every sunday at 5:00 AM
};
description = ''
@ -1311,29 +1389,29 @@ in
imports = [
(lib.mkRemovedOptionModule [ "mailserver" "fullTextSearch" "maintenance" "enable" ] ''
This option is not needed for fts-flatcurve
This option is not needed for fts-flatcurve
'')
(lib.mkRemovedOptionModule [ "mailserver" "fullTextSearch" "maintenance" "onCalendar" ] ''
This option is not needed for fts-flatcurve
This option is not needed for fts-flatcurve
'')
(lib.mkRemovedOptionModule [ "mailserver" "fullTextSearch" "maintenance" "randomizedDelaySec" ] ''
This option is not needed for fts-flatcurve
This option is not needed for fts-flatcurve
'')
(lib.mkRemovedOptionModule [ "mailserver" "fullTextSearch" "minSize" ] ''
This option is not supported by fts-flatcurve
This option is not supported by fts-flatcurve
'')
(lib.mkRemovedOptionModule [ "mailserver" "fullTextSearch" "maxSize" ] ''
This option is not needed since fts-xapian 1.8.3
This option is not needed since fts-xapian 1.8.3
'')
(lib.mkRemovedOptionModule [ "mailserver" "fullTextSearch" "indexAttachments" ] ''
Text attachments are always indexed since fts-xapian 1.4.8
Text attachments are always indexed since fts-xapian 1.4.8
'')
(lib.mkRenamedOptionModule
[ "mailserver" "rebootAfterKernelUpgrade" "enable" ]
[ "system" "autoUpgrade" "allowReboot" ]
)
(lib.mkRemovedOptionModule [ "mailserver" "rebootAfterKernelUpgrade" "method" ] ''
Use `system.autoUpgrade` instead.
Use `system.autoUpgrade` instead.
'')
./mail-server/assertions.nix
./mail-server/borgbackup.nix