Merge branch 'certmgmt-next' into 'master'
Switch to NixOS ACME module for certificate management Closes #256 and #267 See merge request simple-nixos-mailserver/nixos-mailserver!457
This commit is contained in:
+48
-100
@@ -32,7 +32,6 @@ let
|
|||||||
mkRemovedOptionModule
|
mkRemovedOptionModule
|
||||||
mkRenamedOptionModule
|
mkRenamedOptionModule
|
||||||
types
|
types
|
||||||
warn
|
|
||||||
;
|
;
|
||||||
|
|
||||||
cfg = config.mailserver;
|
cfg = config.mailserver;
|
||||||
@@ -131,20 +130,6 @@ in
|
|||||||
description = "The domains that this mail server serves.";
|
description = "The domains that this mail server serves.";
|
||||||
};
|
};
|
||||||
|
|
||||||
certificateDomains = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
example = [
|
|
||||||
"imap.example.com"
|
|
||||||
"pop3.example.com"
|
|
||||||
];
|
|
||||||
default = [ ];
|
|
||||||
description = ''
|
|
||||||
({option}`mailserver.certificateScheme` == `acme-nginx`)
|
|
||||||
|
|
||||||
Secondary domains and subdomains for which it is necessary to generate a certificate.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
messageSizeLimit = mkOption {
|
messageSizeLimit = mkOption {
|
||||||
type = types.int;
|
type = types.int;
|
||||||
example = 52428800;
|
example = 52428800;
|
||||||
@@ -167,12 +152,12 @@ in
|
|||||||
hashedPassword = mkOption {
|
hashedPassword = mkOption {
|
||||||
type = with types; nullOr str;
|
type = with types; nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
|
example = "$y$j9T$vfGrwkAaXCjCEWtVNMQck1$383uIXQmn2z0hnmVAA8kwFQmjNj78.nYbvWeyNLIaP1";
|
||||||
description = ''
|
description = ''
|
||||||
The user's hashed password. Use `mkpasswd` as follows
|
The user's hashed password. Use `mkpasswd` as follows
|
||||||
|
|
||||||
```
|
```
|
||||||
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
nix-shell -p mkpasswd --run 'mkpasswd -s'
|
||||||
```
|
```
|
||||||
|
|
||||||
Warning: this is stored in plaintext in the Nix store!
|
Warning: this is stored in plaintext in the Nix store!
|
||||||
@@ -188,7 +173,7 @@ in
|
|||||||
A file containing the user's hashed password. Use `mkpasswd` as follows
|
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 -s'
|
||||||
```
|
```
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@@ -212,7 +197,8 @@ in
|
|||||||
example = [ ''/^tom\..*@domain\.com$/'' ];
|
example = [ ''/^tom\..*@domain\.com$/'' ];
|
||||||
default = [ ];
|
default = [ ];
|
||||||
description = ''
|
description = ''
|
||||||
Same as {option}`mailserver.aliases` but using PCRE (Perl compatible regex).
|
Same as {option}`mailserver.loginAccounts.<name>.aliases` but
|
||||||
|
using PCRE (Perl compatible regex).
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -290,10 +276,10 @@ in
|
|||||||
);
|
);
|
||||||
example = {
|
example = {
|
||||||
user1 = {
|
user1 = {
|
||||||
hashedPassword = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
|
hashedPassword = "$y$j9T$y6eZ1o.IvVNfdGMAsUEvh1$6K/llP52uw2iDh4iSwtAn54/JYy7FzCcoCHmjmx00H5";
|
||||||
};
|
};
|
||||||
user2 = {
|
user2 = {
|
||||||
hashedPassword = "$6$oE0ZNv2n7Vk9gOf$9xcZWCCLGdMflIfuA0vR1Q1Xblw6RZqPrP94mEit2/81/7AKj2bqUai5yPyWE.QYPyv6wLMHZvjw3Rlg7yTCD/";
|
hashedPassword = "$y$j9T$hZ.ubq0M897Hw.znxnGG9.$14EJBoOwbwKeWt.W4vpnBPEBZC9mYz4fWI9kOCLoZf4";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
description = ''
|
description = ''
|
||||||
@@ -302,7 +288,7 @@ in
|
|||||||
follows
|
follows
|
||||||
|
|
||||||
```
|
```
|
||||||
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
nix-shell -p mkpasswd --run 'mkpasswd -s'
|
||||||
```
|
```
|
||||||
'';
|
'';
|
||||||
default = { };
|
default = { };
|
||||||
@@ -788,91 +774,43 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
certificateScheme =
|
x509 = {
|
||||||
let
|
useACMEHost = mkOption {
|
||||||
schemes = [
|
type = with types; nullOr str;
|
||||||
"manual"
|
default = null;
|
||||||
"selfsigned"
|
example = literalExpression "config.mailserver.fqdn";
|
||||||
"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 = ''
|
description = ''
|
||||||
The scheme to use for managing TLS certificates:
|
Common name used in the relevant `security.acme.certs` configuration.
|
||||||
|
|
||||||
1. `manual`: you specify locations via {option}`mailserver.certificateFile` and
|
Mutually exclusive with {option}`mailserver.x509.certificateFile` and {option}`mailserver.x509.privateKeyFile`.
|
||||||
{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 {
|
certificateFile = mkOption {
|
||||||
type = types.path;
|
type = with types; nullOr path;
|
||||||
example = "/root/mail-server.crt";
|
default = null;
|
||||||
description = ''
|
example = "/var/keys/certs/fullchain.pem";
|
||||||
({option}`mailserver.certificateScheme` == `manual`)
|
description = ''
|
||||||
|
Path to the signed X509 certificate including intermediate certificates.
|
||||||
|
|
||||||
Location of the certificate.
|
This is commonly referred to as {file}`fullchain.pem`.
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
keyFile = mkOption {
|
Mutually exclusive with {option}`mailserver.x509.useACMEHost`.
|
||||||
type = types.path;
|
'';
|
||||||
example = "/root/mail-server.key";
|
};
|
||||||
description = ''
|
|
||||||
({option}`mailserver.certificateScheme` == `manual`)
|
|
||||||
|
|
||||||
Location of the key file.
|
privateKeyFile = mkOption {
|
||||||
'';
|
type = with types; nullOr str;
|
||||||
};
|
default = null;
|
||||||
|
example = "/var/keys/certs/privkey.pem";
|
||||||
|
description = ''
|
||||||
|
Path to the X509 private key.
|
||||||
|
|
||||||
certificateDirectory = mkOption {
|
This is commonly referred to as {file}`privkey.pem`.
|
||||||
type = types.path;
|
|
||||||
default = "/var/certs";
|
|
||||||
description = ''
|
|
||||||
({option}`mailserver.certificateScheme` == `selfsigned`)
|
|
||||||
|
|
||||||
This is the folder where the self-signed certificate will be created. The name is
|
Mutually exclusive with {option}`mailserver.x509.useACMEHost`.
|
||||||
hardcoded to "cert-DOMAIN.pem" and "key-DOMAIN.pem" and the
|
'';
|
||||||
certificate is valid for 10 years.
|
};
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
acmeCertificateName = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = cfg.fqdn;
|
|
||||||
defaultText = literalExpression "config.mailserver.fqdn";
|
|
||||||
example = "example.com";
|
|
||||||
description = ''
|
|
||||||
({option}`mailserver.certificateScheme` == `acme`)
|
|
||||||
|
|
||||||
When the `acme` `certificateScheme` is selected, you can use this option
|
|
||||||
to override the default certificate name. This is useful if you've
|
|
||||||
generated a wildcard certificate, for example.
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enableImap = mkOption {
|
enableImap = mkOption {
|
||||||
@@ -1247,8 +1185,8 @@ in
|
|||||||
if failed port 25 protocol smtp for 5 cycles then restart
|
if failed port 25 protocol smtp for 5 cycles then restart
|
||||||
|
|
||||||
check process dovecot with pidfile /var/run/dovecot2/master.pid
|
check process dovecot with pidfile /var/run/dovecot2/master.pid
|
||||||
start program = "${pkgs.systemd}/bin/systemctl start dovecot2"
|
start program = "${pkgs.systemd}/bin/systemctl start dovecot"
|
||||||
stop program = "${pkgs.systemd}/bin/systemctl stop dovecot2"
|
stop program = "${pkgs.systemd}/bin/systemctl stop dovecot"
|
||||||
if failed host ${cfg.fqdn} port 993 type tcpssl sslauto protocol imap for 5 cycles then restart
|
if failed host ${cfg.fqdn} port 993 type tcpssl sslauto protocol imap for 5 cycles then restart
|
||||||
|
|
||||||
check process rspamd with matching "rspamd: main process"
|
check process rspamd with matching "rspamd: main process"
|
||||||
@@ -1502,7 +1440,6 @@ in
|
|||||||
./mail-server/dovecot.nix
|
./mail-server/dovecot.nix
|
||||||
./mail-server/postfix.nix
|
./mail-server/postfix.nix
|
||||||
./mail-server/rspamd.nix
|
./mail-server/rspamd.nix
|
||||||
./mail-server/nginx.nix
|
|
||||||
./mail-server/kresd.nix
|
./mail-server/kresd.nix
|
||||||
(mkRemovedOptionModule [ "mailserver" "policydSPFExtraConfig" ] ''
|
(mkRemovedOptionModule [ "mailserver" "policydSPFExtraConfig" ] ''
|
||||||
SPF checking has been migrated to Rspamd, which makes this config redundant. Please look into the rspamd config to migrate your settings.
|
SPF checking has been migrated to Rspamd, which makes this config redundant. Please look into the rspamd config to migrate your settings.
|
||||||
@@ -1531,5 +1468,16 @@ in
|
|||||||
(mkRemovedOptionModule [ "mailserver" "dmarcReporting" "fromName" ] ''
|
(mkRemovedOptionModule [ "mailserver" "dmarcReporting" "fromName" ] ''
|
||||||
The name in the `FROM` field for DMARC report now uses the `mailserver.systemName`.
|
The name in the `FROM` field for DMARC report now uses the `mailserver.systemName`.
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
(mkRemovedOptionModule [ "mailserver" "certificateDomains" ] ''
|
||||||
|
Configure `security.acme.certs.''${config.mailserver.fqdn}.extraDomains` instead.
|
||||||
|
'')
|
||||||
|
(mkRemovedOptionModule [ "mailserver" "certificateScheme" ] "")
|
||||||
|
(mkRemovedOptionModule [ "mailserver" "certificateDirectory" ] ''
|
||||||
|
Automatic creation of self-signed certificates is no longer supported.
|
||||||
|
'')
|
||||||
|
(mkRenamedOptionModule [ "mailserver" "acmeCertificateName" ] [ "mailserver" "x509" "useACMEHost" ])
|
||||||
|
(mkRenamedOptionModule [ "mailserver" "certificateFile" ] [ "mailserver" "x509" "certificateFile" ])
|
||||||
|
(mkRenamedOptionModule [ "mailserver" "keyFile" ] [ "mailserver" "x509" "privateKeyFile" ])
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -45,11 +45,11 @@ For remediating this issue the following steps are required:
|
|||||||
wcurl https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/raw/master/migrations/nixos-mailserver-migration-03.py
|
wcurl https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/raw/master/migrations/nixos-mailserver-migration-03.py
|
||||||
chmod +x nixos-mailserver-migration-03.py
|
chmod +x nixos-mailserver-migration-03.py
|
||||||
|
|
||||||
2. Stop the ``dovecot2.service``.
|
2. Stop the ``dovecot.service``.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
systemctl stop dovecot2.service
|
systemctl stop dovecot.service
|
||||||
|
|
||||||
3. Create a backup or snapshot of your ``mailserver.mailDirectory``, so you can restore
|
3. Create a backup or snapshot of your ``mailserver.mailDirectory``, so you can restore
|
||||||
should anything go wrong.
|
should anything go wrong.
|
||||||
@@ -101,7 +101,7 @@ This migration is required if you both:
|
|||||||
|
|
||||||
For remediating this issue the following steps are required:
|
For remediating this issue the following steps are required:
|
||||||
|
|
||||||
1. Stop ``dovecot2.service``.
|
1. Stop ``dovecot.service``.
|
||||||
2. Move ``/var/vmail/ldap`` below your ``mailserver.mailDirectory``.
|
2. Move ``/var/vmail/ldap`` below your ``mailserver.mailDirectory``.
|
||||||
3. Update the ``mailserver.stateVersion`` to ``2``.
|
3. Update the ``mailserver.stateVersion`` to ``2``.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
Release Notes
|
Release Notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
NixOS 26.05
|
||||||
|
-----------
|
||||||
|
|
||||||
|
- Certificate handling was simplified. We recommend setting
|
||||||
|
:option:`mailserver.x509.useACMEHost` to a ``security.acme.certs``
|
||||||
|
configuration. If that does not fit your requirements, configure certificate
|
||||||
|
and private key using :option:`mailserver.x509.certificateFile` and
|
||||||
|
:option:`mailserver.x509.privateKeyFile` instead. Support for automatic
|
||||||
|
creation of self-signed certificates has been removed.
|
||||||
|
|
||||||
NixOS 25.11
|
NixOS 25.11
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(builtins.fetchTarball {
|
||||||
|
# Pick a release version you are interested in and set its hash, e.g.
|
||||||
|
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.11/nixos-mailserver-nixos-25.11.tar.gz";
|
||||||
|
# To get the sha256 of the nixos-mailserver tarball, we can use the nix-prefetch-url command:
|
||||||
|
# release="nixos-25.11"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
|
||||||
|
sha256 = "0000000000000000000000000000000000000000000000000000";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
security.acme = {
|
||||||
|
acceptTerms = true;
|
||||||
|
defaults.email = "security@example.com";
|
||||||
|
certs.${config.mailserver.fqdn} = {
|
||||||
|
# Further setup required, check the manual:
|
||||||
|
# https://nixos.org/manual/nixos/stable/#module-security-acme
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mailserver = {
|
||||||
|
enable = true;
|
||||||
|
stateVersion = 3;
|
||||||
|
fqdn = "mail.example.com";
|
||||||
|
domains = [ "example.com" ];
|
||||||
|
|
||||||
|
# reference an existing ACME configuration
|
||||||
|
x509.useACMEHost = config.mailserver.fqdn;
|
||||||
|
|
||||||
|
# A list of all login accounts. To create the password hashes, use
|
||||||
|
# nix-shell -p mkpasswd --run 'mkpasswd -s'
|
||||||
|
loginAccounts = {
|
||||||
|
"user1@example.com" = {
|
||||||
|
hashedPasswordFile = "/a/file/containing/a/hashed/password";
|
||||||
|
aliases = [ "postmaster@example.com" ];
|
||||||
|
};
|
||||||
|
"user2@example.com" = {
|
||||||
|
# ...
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
+2
-36
@@ -57,42 +57,8 @@ though there are more possible options (see the `NixOS Mailserver
|
|||||||
options documentation <options.html>`_), these should be the most
|
options documentation <options.html>`_), these should be the most
|
||||||
common ones.
|
common ones.
|
||||||
|
|
||||||
.. code:: nix
|
.. literalinclude:: ./setup-example.nix
|
||||||
|
:language: nix
|
||||||
{ config, pkgs, ... }: {
|
|
||||||
imports = [
|
|
||||||
(builtins.fetchTarball {
|
|
||||||
# Pick a release version you are interested in and set its hash, e.g.
|
|
||||||
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.11/nixos-mailserver-nixos-25.11.tar.gz";
|
|
||||||
# To get the sha256 of the nixos-mailserver tarball, we can use the nix-prefetch-url command:
|
|
||||||
# release="nixos-25.11"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
|
|
||||||
sha256 = "0000000000000000000000000000000000000000000000000000";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
mailserver = {
|
|
||||||
enable = true;
|
|
||||||
stateVersion = 3;
|
|
||||||
fqdn = "mail.example.com";
|
|
||||||
domains = [ "example.com" ];
|
|
||||||
|
|
||||||
# A list of all login accounts. To create the password hashes, use
|
|
||||||
# nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
|
||||||
loginAccounts = {
|
|
||||||
"user1@example.com" = {
|
|
||||||
hashedPasswordFile = "/a/file/containing/a/hashed/password";
|
|
||||||
aliases = ["postmaster@example.com"];
|
|
||||||
};
|
|
||||||
"user2@example.com" = { ... };
|
|
||||||
};
|
|
||||||
|
|
||||||
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
|
|
||||||
# down nginx and opens port 80.
|
|
||||||
certificateScheme = "acme-nginx";
|
|
||||||
};
|
|
||||||
security.acme.acceptTerms = true;
|
|
||||||
security.acme.defaults.email = "security@example.com";
|
|
||||||
}
|
|
||||||
|
|
||||||
After a ``nixos-rebuild switch`` your server should be running all
|
After a ``nixos-rebuild switch`` your server should be running all
|
||||||
mail components.
|
mail components.
|
||||||
|
|||||||
@@ -112,6 +112,7 @@
|
|||||||
"logo\\.png"
|
"logo\\.png"
|
||||||
"conf\\.py"
|
"conf\\.py"
|
||||||
"Makefile"
|
"Makefile"
|
||||||
|
".*\\.nix"
|
||||||
".*\\.rst"
|
".*\\.rst"
|
||||||
];
|
];
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
|
|||||||
@@ -38,6 +38,20 @@ in
|
|||||||
assertion = config.mailserver.stateVersion != null;
|
assertion = config.mailserver.stateVersion != null;
|
||||||
message = "The `mailserver.stateVersion` option is not set. Check https://nixos-mailserver.readthedocs.io/en/latest/migrations.html to determine the proper value to initialize it at.";
|
message = "The `mailserver.stateVersion` option is not set. Check https://nixos-mailserver.readthedocs.io/en/latest/migrations.html to determine the proper value to initialize it at.";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
assertion =
|
||||||
|
config.mailserver.x509.useACMEHost != null
|
||||||
|
-> config.mailserver.x509.certificateFile == null && config.mailserver.x509.privateKeyFile == null;
|
||||||
|
message = "Configuring an ACME certificate (`mailserver.x509.useACMEHost`) is not possible while also passing an existing certificate (`mailserver.x509.certificateFile`, `mailserver.x509.privateKeyFile`).";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion =
|
||||||
|
config.mailserver.x509.useACMEHost != null
|
||||||
|
|| (
|
||||||
|
config.mailserver.x509.certificateFile != null && config.mailserver.x509.privateKeyFile != null
|
||||||
|
);
|
||||||
|
message = "Configure either an ACME certificate (`mailserver.x509.useACMEHost`) or pass an existing certificate (`mailserver.x509.certificateFile`, `mailserver.x509.privateKeyFile`).";
|
||||||
|
}
|
||||||
]
|
]
|
||||||
++ lib.optionals config.mailserver.ldap.enable [
|
++ lib.optionals config.mailserver.ldap.enable [
|
||||||
{
|
{
|
||||||
@@ -57,7 +71,7 @@ in
|
|||||||
message = ''
|
message = ''
|
||||||
Issue: The dovecot homedir for LDAP users was previously not respecting `mailserver.mailDirectory`.
|
Issue: The dovecot homedir for LDAP users was previously not respecting `mailserver.mailDirectory`.
|
||||||
Remediation:
|
Remediation:
|
||||||
- Stop the `dovecot2.service`
|
- Stop the `dovecot.service`
|
||||||
- Move `/var/vmail/ldap` below your `mailserver.mailDirectory`
|
- Move `/var/vmail/ldap` below your `mailserver.mailDirectory`
|
||||||
- Increase the `stateVersion` to 2.
|
- Increase the `stateVersion` to 2.
|
||||||
|
|
||||||
@@ -75,11 +89,5 @@ in
|
|||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
++ lib.optionals (config.mailserver.certificateScheme != "acme") [
|
|
||||||
{
|
|
||||||
assertion = config.mailserver.acmeCertificateName == config.mailserver.fqdn;
|
|
||||||
message = "When the certificate scheme is not 'acme' (mailserver.certificateScheme != \"acme\"), it is not possible to define mailserver.acmeCertificateName";
|
|
||||||
}
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-20
@@ -24,28 +24,20 @@
|
|||||||
let
|
let
|
||||||
cfg = config.mailserver;
|
cfg = config.mailserver;
|
||||||
in
|
in
|
||||||
{
|
rec {
|
||||||
# cert :: PATH
|
withACME = cfg.x509.useACMEHost != null;
|
||||||
certificatePath =
|
|
||||||
if cfg.certificateScheme == "manual" then
|
|
||||||
cfg.certificateFile
|
|
||||||
else if cfg.certificateScheme == "selfsigned" then
|
|
||||||
"${cfg.certificateDirectory}/cert-${cfg.fqdn}.pem"
|
|
||||||
else if cfg.certificateScheme == "acme" || cfg.certificateScheme == "acme-nginx" then
|
|
||||||
"${config.security.acme.certs.${cfg.acmeCertificateName}.directory}/fullchain.pem"
|
|
||||||
else
|
|
||||||
throw "unknown certificate scheme";
|
|
||||||
|
|
||||||
# key :: PATH
|
x509CertificateFile =
|
||||||
keyPath =
|
if withACME then
|
||||||
if cfg.certificateScheme == "manual" then
|
"${config.security.acme.certs.${cfg.x509.useACMEHost}.directory}/fullchain.pem"
|
||||||
cfg.keyFile
|
|
||||||
else if cfg.certificateScheme == "selfsigned" then
|
|
||||||
"${cfg.certificateDirectory}/key-${cfg.fqdn}.pem"
|
|
||||||
else if cfg.certificateScheme == "acme" || cfg.certificateScheme == "acme-nginx" then
|
|
||||||
"${config.security.acme.certs.${cfg.acmeCertificateName}.directory}/key.pem"
|
|
||||||
else
|
else
|
||||||
throw "unknown certificate scheme";
|
cfg.x509.certificateFile;
|
||||||
|
|
||||||
|
x509PrivateKeyFile =
|
||||||
|
if withACME then
|
||||||
|
"${config.security.acme.certs.${cfg.x509.useACMEHost}.directory}/key.pem"
|
||||||
|
else
|
||||||
|
cfg.x509.privateKeyFile;
|
||||||
|
|
||||||
passwordFiles =
|
passwordFiles =
|
||||||
let
|
let
|
||||||
|
|||||||
+12
-2
@@ -196,6 +196,12 @@ in
|
|||||||
multiple languages are present in the configuration.
|
multiple languages are present in the configuration.
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
security.acme.certs = lib.mkIf withACME {
|
||||||
|
${cfg.x509.useACMEHost} = {
|
||||||
|
reloadServices = [ "dovecot.service" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# for sieve-test. Shelling it in on demand usually doesnt' work, as it reads
|
# for sieve-test. Shelling it in on demand usually doesnt' work, as it reads
|
||||||
# the global config and tries to open shared libraries configured in there,
|
# the global config and tries to open shared libraries configured in there,
|
||||||
# which are usually not compatible.
|
# which are usually not compatible.
|
||||||
@@ -216,8 +222,8 @@ in
|
|||||||
mailGroup = cfg.vmailGroupName;
|
mailGroup = cfg.vmailGroupName;
|
||||||
mailUser = cfg.vmailUserName;
|
mailUser = cfg.vmailUserName;
|
||||||
mailLocation = dovecotMaildir;
|
mailLocation = dovecotMaildir;
|
||||||
sslServerCert = certificatePath;
|
sslServerCert = x509CertificateFile;
|
||||||
sslServerKey = keyPath;
|
sslServerKey = x509PrivateKeyFile;
|
||||||
enableDHE = lib.mkDefault false;
|
enableDHE = lib.mkDefault false;
|
||||||
enableLmtp = true;
|
enableLmtp = true;
|
||||||
mailPlugins.globally.enable = lib.optionals cfg.fullTextSearch.enable [
|
mailPlugins.globally.enable = lib.optionals cfg.fullTextSearch.enable [
|
||||||
@@ -455,6 +461,10 @@ in
|
|||||||
${genPasswdScript}
|
${genPasswdScript}
|
||||||
''
|
''
|
||||||
+ (lib.optionalString cfg.ldap.enable setPwdInLdapConfFile);
|
+ (lib.optionalString cfg.ldap.enable setPwdInLdapConfFile);
|
||||||
|
reloadTriggers = lib.mkIf (!withACME) [
|
||||||
|
x509CertificateFile
|
||||||
|
x509PrivateKeyFile
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.postfix.restartTriggers = [
|
systemd.services.postfix.restartTriggers = [
|
||||||
|
|||||||
@@ -26,14 +26,11 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
environment.systemPackages =
|
environment.systemPackages = with pkgs; [
|
||||||
with pkgs;
|
dovecot
|
||||||
[
|
openssh
|
||||||
dovecot
|
postfix
|
||||||
openssh
|
rspamd
|
||||||
postfix
|
];
|
||||||
rspamd
|
|
||||||
]
|
|
||||||
++ (if cfg.certificateScheme == "selfsigned" then [ openssl ] else [ ]);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ in
|
|||||||
++ lib.optional cfg.enableImapSsl 993
|
++ lib.optional cfg.enableImapSsl 993
|
||||||
++ lib.optional cfg.enablePop3 110
|
++ lib.optional cfg.enablePop3 110
|
||||||
++ lib.optional cfg.enablePop3Ssl 995
|
++ lib.optional cfg.enablePop3Ssl 995
|
||||||
++ lib.optional cfg.enableManageSieve 4190
|
++ lib.optional cfg.enableManageSieve 4190;
|
||||||
++ lib.optional (cfg.certificateScheme == "acme-nginx") 80;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
# nixos-mailserver: a simple mail server
|
|
||||||
# Copyright (C) 2016-2018 Robin Raymond
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# 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,
|
|
||||||
options,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
with (import ./common.nix {
|
|
||||||
inherit
|
|
||||||
config
|
|
||||||
options
|
|
||||||
lib
|
|
||||||
pkgs
|
|
||||||
;
|
|
||||||
});
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.mailserver;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config =
|
|
||||||
lib.mkIf (cfg.enable && (cfg.certificateScheme == "acme" || cfg.certificateScheme == "acme-nginx"))
|
|
||||||
{
|
|
||||||
services.nginx = lib.mkIf (cfg.certificateScheme == "acme-nginx") {
|
|
||||||
enable = true;
|
|
||||||
virtualHosts."${cfg.fqdn}" = {
|
|
||||||
serverName = cfg.fqdn;
|
|
||||||
serverAliases = cfg.certificateDomains;
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
security.acme.certs."${cfg.acmeCertificateName}" = {
|
|
||||||
extraDomainNames = lib.mkIf (cfg.certificateScheme == "acme") cfg.certificateDomains;
|
|
||||||
reloadServices = [
|
|
||||||
"postfix.service"
|
|
||||||
"dovecot.service"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
+13
-2
@@ -279,6 +279,17 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
security.acme.certs = lib.mkIf withACME {
|
||||||
|
${cfg.x509.useACMEHost} = {
|
||||||
|
reloadServices = [ "postfix.service" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.postfix.reloadTriggers = lib.mkIf (!withACME) [
|
||||||
|
x509CertificateFile
|
||||||
|
x509PrivateKeyFile
|
||||||
|
];
|
||||||
|
|
||||||
systemd.services.postfix-setup = lib.mkIf cfg.ldap.enable {
|
systemd.services.postfix-setup = lib.mkIf cfg.ldap.enable {
|
||||||
preStart = ''
|
preStart = ''
|
||||||
${appendPwdInVirtualMailboxMap}
|
${appendPwdInVirtualMailboxMap}
|
||||||
@@ -364,8 +375,8 @@ in
|
|||||||
|
|
||||||
# The X509 private key followed by the corresponding certificate
|
# The X509 private key followed by the corresponding certificate
|
||||||
smtpd_tls_chain_files = [
|
smtpd_tls_chain_files = [
|
||||||
"${keyPath}"
|
"${x509PrivateKeyFile}"
|
||||||
"${certificatePath}"
|
"${x509CertificateFile}"
|
||||||
];
|
];
|
||||||
|
|
||||||
# TLS for incoming mail is optional
|
# TLS for incoming mail is optional
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ let
|
|||||||
pkgs.writeShellScript "dkim-keygen-${domain}" ''
|
pkgs.writeShellScript "dkim-keygen-${domain}" ''
|
||||||
if [ ! -f "${privateKey}" ]
|
if [ ! -f "${privateKey}" ]
|
||||||
then
|
then
|
||||||
|
export PATH=${lib.makeBinPath [ pkgs.openssl ]}
|
||||||
${lib.getExe' pkgs.rspamd "rspamadm"} dkim_keygen \
|
${lib.getExe' pkgs.rspamd "rspamadm"} dkim_keygen \
|
||||||
--domain "${domain}" \
|
--domain "${domain}" \
|
||||||
--selector "${cfg.dkimSelector}" \
|
--selector "${cfg.dkimSelector}" \
|
||||||
|
|||||||
+7
-38
@@ -33,47 +33,16 @@ with (import ./common.nix {
|
|||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.mailserver;
|
cfg = config.mailserver;
|
||||||
certificatesDeps =
|
certificateDeps = lib.optionals withACME [
|
||||||
if cfg.certificateScheme == "manual" then
|
"acme-order-renew-${cfg.x509.useACMEHost}.service"
|
||||||
[ ]
|
];
|
||||||
else if cfg.certificateScheme == "selfsigned" then
|
|
||||||
[ "mailserver-selfsigned-certificate.service" ]
|
|
||||||
else
|
|
||||||
[ "acme-finished-${cfg.fqdn}.target" ];
|
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
# Create self signed certificate
|
|
||||||
systemd.services.mailserver-selfsigned-certificate =
|
|
||||||
lib.mkIf (cfg.certificateScheme == "selfsigned")
|
|
||||||
{
|
|
||||||
after = [ "local-fs.target" ];
|
|
||||||
script = ''
|
|
||||||
# Create certificates if they do not exist yet
|
|
||||||
dir="${cfg.certificateDirectory}"
|
|
||||||
fqdn="${cfg.fqdn}"
|
|
||||||
[[ $fqdn == /* ]] && fqdn=$(< "$fqdn")
|
|
||||||
key="$dir/key-${cfg.fqdn}.pem";
|
|
||||||
cert="$dir/cert-${cfg.fqdn}.pem";
|
|
||||||
|
|
||||||
if [[ ! -f $key || ! -f $cert ]]; then
|
|
||||||
mkdir -p "${cfg.certificateDirectory}"
|
|
||||||
(umask 077; "${pkgs.openssl}/bin/openssl" genrsa -out "$key" 2048) &&
|
|
||||||
"${pkgs.openssl}/bin/openssl" req -new -key "$key" -x509 -subj "/CN=$fqdn" \
|
|
||||||
-days 3650 -out "$cert"
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
PrivateTmp = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Create maildir folder before dovecot startup
|
|
||||||
systemd.services.dovecot = {
|
systemd.services.dovecot = {
|
||||||
wants = certificatesDeps;
|
wants = certificateDeps;
|
||||||
after = certificatesDeps;
|
after = certificateDeps;
|
||||||
preStart =
|
preStart =
|
||||||
let
|
let
|
||||||
directories = lib.strings.escapeShellArgs (
|
directories = lib.strings.escapeShellArgs (
|
||||||
@@ -93,12 +62,12 @@ in
|
|||||||
|
|
||||||
# Postfix requires dovecot lmtp socket, dovecot auth socket and certificate to work
|
# Postfix requires dovecot lmtp socket, dovecot auth socket and certificate to work
|
||||||
systemd.services.postfix = {
|
systemd.services.postfix = {
|
||||||
wants = certificatesDeps;
|
wants = certificateDeps;
|
||||||
after = [
|
after = [
|
||||||
"dovecot.service"
|
"dovecot.service"
|
||||||
]
|
]
|
||||||
++ lib.optional cfg.dkimSigning "rspamd.service"
|
++ lib.optional cfg.dkimSigning "rspamd.service"
|
||||||
++ certificatesDeps;
|
++ certificateDeps;
|
||||||
requires = [ "dovecot.service" ] ++ lib.optional cfg.dkimSigning "rspamd.service";
|
requires = [ "dovecot.service" ] ++ lib.optional cfg.dkimSigning "rspamd.service";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ header = """
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
template = """
|
template = """
|
||||||
|
({key})=
|
||||||
`````{{option}} {key}
|
`````{{option}} {key}
|
||||||
{description}
|
{description}
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ options = json.load(f)
|
|||||||
|
|
||||||
groups = [
|
groups = [
|
||||||
"mailserver.loginAccounts",
|
"mailserver.loginAccounts",
|
||||||
"mailserver.certificate",
|
"mailserver.x509",
|
||||||
"mailserver.dkim",
|
"mailserver.dkim",
|
||||||
"mailserver.srs",
|
"mailserver.srs",
|
||||||
"mailserver.dmarcReporting",
|
"mailserver.dmarcReporting",
|
||||||
|
|||||||
+2
-2
@@ -248,7 +248,7 @@
|
|||||||
with subtest("no warnings or errors"):
|
with subtest("no warnings or errors"):
|
||||||
server.fail("journalctl -u postfix | grep -i error >&2")
|
server.fail("journalctl -u postfix | grep -i error >&2")
|
||||||
server.fail("journalctl -u postfix | grep -i warning >&2")
|
server.fail("journalctl -u postfix | grep -i warning >&2")
|
||||||
server.fail("journalctl -u dovecot2 | grep -i error >&2")
|
server.fail("journalctl -u dovecot | grep -i error >&2")
|
||||||
server.fail("journalctl -u dovecot2 | grep -i warning >&2")
|
server.fail("journalctl -u dovecot | grep -i warning >&2")
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-7
@@ -26,7 +26,10 @@
|
|||||||
./lib/config.nix
|
./lib/config.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [ netcat ];
|
environment.systemPackages = with pkgs; [
|
||||||
|
netcat
|
||||||
|
openssl
|
||||||
|
];
|
||||||
|
|
||||||
virtualisation.memorySize = 1024;
|
virtualisation.memorySize = 1024;
|
||||||
|
|
||||||
@@ -486,9 +489,9 @@
|
|||||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||||
|
|
||||||
client.succeed("imap-mark-spam >&2")
|
client.succeed("imap-mark-spam >&2")
|
||||||
server.wait_until_succeeds("journalctl -u dovecot -u dovecot2 | grep -i rspamd-learn-spam.sh >&2")
|
server.wait_until_succeeds("journalctl -u dovecot | grep -i rspamd-learn-spam.sh >&2")
|
||||||
client.succeed("imap-mark-ham >&2")
|
client.succeed("imap-mark-ham >&2")
|
||||||
server.wait_until_succeeds("journalctl -u dovecot -u dovecot2 | grep -i rspamd-learn-ham.sh >&2")
|
server.wait_until_succeeds("journalctl -u dovecot | grep -i rspamd-learn-ham.sh >&2")
|
||||||
|
|
||||||
with subtest("full text search and indexation"):
|
with subtest("full text search and indexation"):
|
||||||
# send 2 email from user2 to user1
|
# send 2 email from user2 to user1
|
||||||
@@ -506,9 +509,9 @@
|
|||||||
# should fail because this folder is not indexed
|
# should fail because this folder is not indexed
|
||||||
client.fail("search Junk a >&2")
|
client.fail("search Junk a >&2")
|
||||||
# check that search really goes through the indexer
|
# check that search really goes through the indexer
|
||||||
server.succeed("journalctl -u dovecot -u dovecot2 | grep 'fts-flatcurve(INBOX): Query ' >&2")
|
server.succeed("journalctl -u dovecot | grep 'fts-flatcurve(INBOX): Query ' >&2")
|
||||||
# check that Junk is not indexed
|
# check that Junk is not indexed
|
||||||
server.fail("journalctl -u dovecot -u dovecot2 | grep 'fts-flatcurve(JUNK): Indexing ' >&2")
|
server.fail("journalctl -u dovecot | grep 'fts-flatcurve(JUNK): Indexing ' >&2")
|
||||||
|
|
||||||
with subtest("dmarc reporting"):
|
with subtest("dmarc reporting"):
|
||||||
server.systemctl("start rspamd-dmarc-reporter.service")
|
server.systemctl("start rspamd-dmarc-reporter.service")
|
||||||
@@ -516,10 +519,10 @@
|
|||||||
with subtest("no warnings or errors"):
|
with subtest("no warnings or errors"):
|
||||||
server.fail("journalctl -u postfix | grep -i error >&2")
|
server.fail("journalctl -u postfix | grep -i error >&2")
|
||||||
server.fail("journalctl -u postfix | grep -i warning >&2")
|
server.fail("journalctl -u postfix | grep -i warning >&2")
|
||||||
server.fail("journalctl -u dovecot -u dovecot2 | grep -v 'imap-login: Debug: SSL error: Connection closed' | grep -i error >&2")
|
server.fail("journalctl -u dovecot | grep -v 'imap-login: Debug: SSL error: Connection closed' | grep -i error >&2")
|
||||||
# harmless ? https://dovecot.org/pipermail/dovecot/2020-August/119575.html
|
# harmless ? https://dovecot.org/pipermail/dovecot/2020-August/119575.html
|
||||||
server.fail(
|
server.fail(
|
||||||
"journalctl -u dovecot -u dovecot2 | \
|
"journalctl -u dovecot | \
|
||||||
grep -v 'Expunged message reappeared, giving a new UID' | \
|
grep -v 'Expunged message reappeared, giving a new UID' | \
|
||||||
grep -v 'Time moved forwards' | \
|
grep -v 'Time moved forwards' | \
|
||||||
grep -i warning >&2"
|
grep -i warning >&2"
|
||||||
|
|||||||
+2
-1
@@ -38,7 +38,7 @@ let
|
|||||||
inherit password;
|
inherit password;
|
||||||
}
|
}
|
||||||
''
|
''
|
||||||
mkpasswd -sm bcrypt <<<"$password" > $out
|
mkpasswd -s <<<"$password" > $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
hashedPasswordFile = hashPassword "my-password";
|
hashedPasswordFile = hashPassword "my-password";
|
||||||
@@ -113,6 +113,7 @@ in
|
|||||||
''
|
''
|
||||||
machine.start()
|
machine.start()
|
||||||
machine.wait_for_unit("multi-user.target")
|
machine.wait_for_unit("multi-user.target")
|
||||||
|
machine.wait_for_unit("dovecot.service")
|
||||||
|
|
||||||
# Regression test for https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/205
|
# Regression test for https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/205
|
||||||
with subtest("mail forwarded can are locally kept"):
|
with subtest("mail forwarded can are locally kept"):
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBizCCATGgAwIBAgIUN4ncJfMVIQSSurMkdE73x4aefTMwCgYIKoZIzj0EAwIw
|
||||||
|
GzEZMBcGA1UEAwwQdGVzdC5sb2NhbGRvbWFpbjAeFw0yNTEwMTgyMTQ4MTNaFw0z
|
||||||
|
NTEwMTYyMTQ4MTNaMBsxGTAXBgNVBAMMEHRlc3QubG9jYWxkb21haW4wWTATBgcq
|
||||||
|
hkjOPQIBBggqhkjOPQMBBwNCAARCJUj4j7eC/7Xso3REUscqHlWPvW9zvl5I6TIy
|
||||||
|
zEXFsWxM0QxMuNW4oXE56UiCyJklcpk0JfQUGat+kKQqSUJyo1MwUTAdBgNVHQ4E
|
||||||
|
FgQUW3CnmBf3n/Y30vfj3ERsIQnXu9QwHwYDVR0jBBgwFoAUW3CnmBf3n/Y30vfj
|
||||||
|
3ERsIQnXu9QwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAhwAi
|
||||||
|
K4xdr8KxD5xRvvzShheh48i8X7NtBIQ3bd01Jx4CIG/kYTDK5nDZri7UYOMsgz2l
|
||||||
|
iWss56p2dGWTL7LrBHgM
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -10,6 +10,17 @@
|
|||||||
# Keep testing submission with explicit TLS
|
# Keep testing submission with explicit TLS
|
||||||
mailserver.enableSubmission = true;
|
mailserver.enableSubmission = true;
|
||||||
|
|
||||||
|
# Certificate created for testing purposes from RFC9500 private key
|
||||||
|
# https://datatracker.ietf.org/doc/rfc9500/
|
||||||
|
# openssl req -x509 -new -key key.pem \
|
||||||
|
# -subj "/CN=test.localdomain" \
|
||||||
|
# -sha256 -days 3650 \
|
||||||
|
# -out cert.pem
|
||||||
|
mailserver.x509 = {
|
||||||
|
certificateFile = "${./cert.pem}";
|
||||||
|
privateKeyFile = "${./key.pem}";
|
||||||
|
};
|
||||||
|
|
||||||
# Enable second CPU core
|
# Enable second CPU core
|
||||||
virtualisation.cores = lib.mkDefault 2;
|
virtualisation.cores = lib.mkDefault 2;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIObLW92AqkWunJXowVR2Z5/+yVPBaFHnEedDk5WJxk/BoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEQiVI+I+3gv+17KN0RFLHKh5Vj71vc75eSOkyMsxFxbFsTNEMTLjV
|
||||||
|
uKFxOelIgsiZJXKZNCX0FBmrfpCkKklCcg==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
+4
-3
@@ -15,7 +15,7 @@ let
|
|||||||
inherit password;
|
inherit password;
|
||||||
}
|
}
|
||||||
''
|
''
|
||||||
mkpasswd -sm bcrypt <<<"$password" > $out
|
mkpasswd -s <<<"$password" > $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
password = pkgs.writeText "password" "password";
|
password = pkgs.writeText "password" "password";
|
||||||
@@ -93,8 +93,9 @@ in
|
|||||||
testScript = ''
|
testScript = ''
|
||||||
start_all()
|
start_all()
|
||||||
|
|
||||||
domain1.wait_for_unit("multi-user.target")
|
for domain in [domain1, domain2]:
|
||||||
domain2.wait_for_unit("multi-user.target")
|
domain.wait_for_unit("multi-user.target")
|
||||||
|
domain.wait_for_unit("dovecot.service")
|
||||||
|
|
||||||
# TODO put this blocking into the systemd units?
|
# TODO put this blocking into the systemd units?
|
||||||
domain1.wait_until_succeeds(
|
domain1.wait_until_succeeds(
|
||||||
|
|||||||
Reference in New Issue
Block a user