Compare commits
11 Commits
havefun-22
...
havefun-22
Author | SHA1 | Date | |
---|---|---|---|
|
5914595fb6 | ||
|
70a970f5a0 | ||
|
31eadb6388 | ||
|
033b3d2a45 | ||
|
694e7d34f6 | ||
|
fe36e7ae0d | ||
|
3f0b7a1b5c | ||
|
737eb4f398 | ||
|
a40e9c3abb | ||
|
004c229ca4 | ||
|
f535d8123c |
@ -3,11 +3,11 @@ hydra-pr:
|
|||||||
- merge_requests
|
- merge_requests
|
||||||
image: nixos/nix
|
image: nixos/nix
|
||||||
script:
|
script:
|
||||||
- nix --extra-experimental-features nix-command run -f channel:nixos-unstable hydra-cli -- -H https://hydra.nix-community.org jobset-wait simple-nixos-mailserver ${CI_MERGE_REQUEST_IID}
|
- nix-shell -I nixpkgs=channel:nixos-22.05 -p hydra-cli --run 'hydra-cli -H https://hydra.nix-community.org jobset-wait simple-nixos-mailserver ${CI_MERGE_REQUEST_IID}'
|
||||||
|
|
||||||
hydra-master:
|
hydra-master:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
image: nixos/nix
|
image: nixos/nix
|
||||||
script:
|
script:
|
||||||
- nix --extra-experimental-features nix-command run -f channel:nixos-unstable hydra-cli -- -H https://hydra.nix-community.org jobset-wait simple-nixos-mailserver master
|
- nix-shell -I nixpkgs=channel:nixos-22.05 -p hydra-cli --run 'hydra-cli -H https://hydra.nix-community.org jobset-wait simple-nixos-mailserver master'
|
||||||
|
@ -32,6 +32,8 @@ let
|
|||||||
|
|
||||||
desc = prJobsets // {
|
desc = prJobsets // {
|
||||||
"master" = mkFlakeJobset "master";
|
"master" = mkFlakeJobset "master";
|
||||||
|
"nixos-22.05" = mkFlakeJobset "nixos-22.05";
|
||||||
|
"nixos-22.11" = mkFlakeJobset "nixos-22.11";
|
||||||
};
|
};
|
||||||
|
|
||||||
log = {
|
log = {
|
||||||
|
10
README.md
10
README.md
@ -8,14 +8,14 @@
|
|||||||
For each NixOS release, we publish a branch. You then have to use the
|
For each NixOS release, we publish a branch. You then have to use the
|
||||||
SNM branch corresponding to your NixOS version.
|
SNM branch corresponding to your NixOS version.
|
||||||
|
|
||||||
|
* For NixOS 22.05
|
||||||
|
- Use the [SNM branch `nixos-22.05`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/nixos-22.05)
|
||||||
|
- [Documentation](https://nixos-mailserver.readthedocs.io/en/nixos-22.05/)
|
||||||
|
- [Release notes](https://nixos-mailserver.readthedocs.io/en/nixos-22.05/release-notes.html#nixos-22-05)
|
||||||
* For NixOS 21.11
|
* For NixOS 21.11
|
||||||
- Use the [SNM branch `nixos-21.11`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/nixos-21.11)
|
- Use the [SNM branch `nixos-21.11`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/nixos-21.11)
|
||||||
- [Documentation](https://nixos-mailserver.readthedocs.io/en/nixos-21.11/)
|
- [Documentation](https://nixos-mailserver.readthedocs.io/en/nixos-21.11/)
|
||||||
- [Release notes](https://nixos-mailserver.readthedocs.io/en/nixos-21.11/release-notes.html#nixos-21-11)
|
- [Release notes](https://nixos-mailserver.readthedocs.io/en/nixos-21.11/release-notes.html#nixos-21-11)
|
||||||
* For NixOS 21.05
|
|
||||||
- Use the [SNM branch `nixos-21.05`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/nixos-21.05)
|
|
||||||
- [Documentation](https://nixos-mailserver.readthedocs.io/en/nixos-21.05/)
|
|
||||||
- [Release notes](https://nixos-mailserver.readthedocs.io/en/nixos-21.05/release-notes.html#nixos-21-05)
|
|
||||||
* For NixOS unstable
|
* For NixOS unstable
|
||||||
- Use the [SNM branch `master`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/master)
|
- Use the [SNM branch `master`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/master)
|
||||||
- [Documentation](https://nixos-mailserver.readthedocs.io/en/latest/)
|
- [Documentation](https://nixos-mailserver.readthedocs.io/en/latest/)
|
||||||
@ -96,7 +96,7 @@ D9FE 4119 F082 6F15 93BD BD36 6162 DBA5 635E A16A
|
|||||||
domains = [ "example.com" "example2.com" ];
|
domains = [ "example.com" "example2.com" ];
|
||||||
loginAccounts = {
|
loginAccounts = {
|
||||||
"user1@example.com" = {
|
"user1@example.com" = {
|
||||||
# nix run nixpkgs.apacheHttpd -c htpasswd -nbB "" "super secret password" | cut -d: -f2 > /hashed/password/file/location
|
# nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt' > /hashed/password/file/location
|
||||||
hashedPasswordFile = "/hashed/password/file/location";
|
hashedPasswordFile = "/hashed/password/file/location";
|
||||||
|
|
||||||
aliases = [
|
aliases = [
|
||||||
|
73
default.nix
73
default.nix
@ -72,10 +72,10 @@ in
|
|||||||
default = null;
|
default = null;
|
||||||
example = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
|
example = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
|
||||||
description = ''
|
description = ''
|
||||||
The user's hashed password. Use `htpasswd` as follows
|
The user's hashed password. Use `mkpasswd` as follows
|
||||||
|
|
||||||
```
|
```
|
||||||
nix run nixpkgs.apacheHttpd -c htpasswd -nbB "" "super secret password" | cut -d: -f2
|
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
||||||
```
|
```
|
||||||
|
|
||||||
Warning: this is stored in plaintext in the Nix store!
|
Warning: this is stored in plaintext in the Nix store!
|
||||||
@ -88,10 +88,10 @@ in
|
|||||||
default = null;
|
default = null;
|
||||||
example = "/run/keys/user1-passwordhash";
|
example = "/run/keys/user1-passwordhash";
|
||||||
description = ''
|
description = ''
|
||||||
A file containing the user's hashed password. Use `htpasswd` as follows
|
A file containing the user's hashed password. Use `mkpasswd` as follows
|
||||||
|
|
||||||
```
|
```
|
||||||
nix run nixpkgs.apacheHttpd -c htpasswd -nbB "" "super secret password" | cut -d: -f2
|
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
||||||
```
|
```
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -184,11 +184,11 @@ in
|
|||||||
};
|
};
|
||||||
description = ''
|
description = ''
|
||||||
The login account of the domain. Every account is mapped to a unix user,
|
The login account of the domain. Every account is mapped to a unix user,
|
||||||
e.g. `user1@example.com`. To generate the passwords use `htpasswd` as
|
e.g. `user1@example.com`. To generate the passwords use `mkpasswd` as
|
||||||
follows
|
follows
|
||||||
|
|
||||||
```
|
```
|
||||||
nix run nixpkgs.apacheHttpd -c htpasswd -nbB "" "super secret password" | cut -d: -f2
|
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
||||||
```
|
```
|
||||||
'';
|
'';
|
||||||
default = {};
|
default = {};
|
||||||
@ -627,6 +627,67 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dmarcReporting = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to send out aggregated, daily DMARC reports in response to incoming
|
||||||
|
mail, when the sender domain defines a DMARC policy including the RUA tag.
|
||||||
|
|
||||||
|
This is helpful for the mail ecosystem, because it allows third parties to
|
||||||
|
get notified about SPF/DKIM violations originating from their sender domains.
|
||||||
|
|
||||||
|
See https://rspamd.com/doc/modules/dmarc.html#reporting
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
localpart = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "dmarc-noreply";
|
||||||
|
example = "dmarc-report";
|
||||||
|
description = ''
|
||||||
|
The local part of the email address used for outgoing DMARC reports.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
domain = mkOption {
|
||||||
|
type = types.enum (cfg.domains);
|
||||||
|
example = "example.com";
|
||||||
|
description = ''
|
||||||
|
The domain from which outgoing DMARC reports are served.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
email = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = with cfg.dmarcReporting; "${localpart}@${domain}";
|
||||||
|
defaultText = literalExpression ''"''${localpart}@''${domain}"'';
|
||||||
|
readOnly = true;
|
||||||
|
description = ''
|
||||||
|
The email address used for outgoing DMARC reports. Read-only.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
organizationName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "ACME Corp.";
|
||||||
|
description = ''
|
||||||
|
The name of your organization used in the <literal>org_name</literal> attribute in
|
||||||
|
DMARC reports.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
fromName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = cfg.dmarcReporting.organizationName;
|
||||||
|
defaultText = literalExpression "organizationName";
|
||||||
|
description = ''
|
||||||
|
The sender name for DMARC reports. Defaults to the organization name.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
debug = mkOption {
|
debug = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
|
@ -4,8 +4,8 @@ Add Radicale
|
|||||||
Configuration by @dotlambda
|
Configuration by @dotlambda
|
||||||
|
|
||||||
Starting with Radicale 3 (first introduced in NixOS 20.09) the traditional
|
Starting with Radicale 3 (first introduced in NixOS 20.09) the traditional
|
||||||
crypt passwords, as generated by `mkpasswd`, are no longer supported. Instead
|
crypt passwords are no longer supported. Instead bcrypt passwords
|
||||||
bcrypt passwords have to be used which can be generated using `htpasswd`.
|
have to be used. These can still be generated using `mkpasswd -m bcrypt`.
|
||||||
|
|
||||||
.. code:: nix
|
.. code:: nix
|
||||||
|
|
||||||
|
590
docs/options.rst
590
docs/options.rst
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,12 @@
|
|||||||
Release Notes
|
Release Notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
NixOS 22.05
|
||||||
|
-----------
|
||||||
|
|
||||||
|
- Make NixOS Mailserver options discoverable from search.nixos.org
|
||||||
|
- Add a roundcube setup guide in the documentation
|
||||||
|
|
||||||
NixOS 21.11
|
NixOS 21.11
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ these should be the most common ones.
|
|||||||
domains = [ "example.com" ];
|
domains = [ "example.com" ];
|
||||||
|
|
||||||
# A list of all login accounts. To create the password hashes, use
|
# A list of all login accounts. To create the password hashes, use
|
||||||
# nix run nixpkgs.apacheHttpd -c htpasswd -nbB "" "super secret password" | cut -d: -f2
|
# nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
||||||
loginAccounts = {
|
loginAccounts = {
|
||||||
"user1@example.com" = {
|
"user1@example.com" = {
|
||||||
hashedPasswordFile = "/a/file/containing/a/hashed/password";
|
hashedPasswordFile = "/a/file/containing/a/hashed/password";
|
||||||
@ -96,7 +96,14 @@ Set rDNS (reverse DNS) entry for server
|
|||||||
|
|
||||||
Wherever you have rented your server, you should be able to set reverse
|
Wherever you have rented your server, you should be able to set reverse
|
||||||
DNS entries for the IP’s you own. Add an entry resolving ``1.2.3.4``
|
DNS entries for the IP’s you own. Add an entry resolving ``1.2.3.4``
|
||||||
to ``mail.example.com``
|
to ``mail.example.com``.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
We don't recommend setting up a mail server if you are not able to
|
||||||
|
set a reverse DNS on your public IP because sent emails would be
|
||||||
|
mostly marked as spam. Note that many residential ISP providers
|
||||||
|
don't allow you to set a reverse DNS entry.
|
||||||
|
|
||||||
You can check this with
|
You can check this with
|
||||||
|
|
||||||
|
22
flake.lock
generated
22
flake.lock
generated
@ -18,11 +18,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1642635915,
|
"lastModified": 1669542132,
|
||||||
"narHash": "sha256-vabPA32j81xBO5m3+qXndWp5aqepe+vu96Wkd9UnngM=",
|
"narHash": "sha256-DRlg++NJAwPh8io3ExBJdNW7Djs3plVI5jgYQ+iXAZQ=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "6d8215281b2f87a5af9ed7425a26ac575da0438f",
|
"rev": "a115bb9bd56831941be3776c8a94005867f316a7",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -31,10 +31,26 @@
|
|||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-22_11": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1669558522,
|
||||||
|
"narHash": "sha256-yqxn+wOiPqe6cxzOo4leeJOp1bXE/fjPEi/3F/bBHv8=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "ce5fe99df1f15a09a91a86be9738d68fadfbad82",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-22.11",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"blobs": "blobs",
|
"blobs": "blobs",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-22_11": "nixpkgs-22_11",
|
||||||
"utils": "utils"
|
"utils": "utils"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
18
flake.nix
18
flake.nix
@ -4,13 +4,14 @@
|
|||||||
inputs = {
|
inputs = {
|
||||||
utils.url = "github:numtide/flake-utils";
|
utils.url = "github:numtide/flake-utils";
|
||||||
nixpkgs.url = "flake:nixpkgs/nixos-unstable";
|
nixpkgs.url = "flake:nixpkgs/nixos-unstable";
|
||||||
|
nixpkgs-22_11.url = "flake:nixpkgs/nixos-22.11";
|
||||||
blobs = {
|
blobs = {
|
||||||
url = "gitlab:simple-nixos-mailserver/blobs";
|
url = "gitlab:simple-nixos-mailserver/blobs";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, utils, blobs, nixpkgs }: let
|
outputs = { self, utils, blobs, nixpkgs, nixpkgs-22_11 }: let
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
releases = [
|
releases = [
|
||||||
@ -18,6 +19,10 @@
|
|||||||
name = "unstable";
|
name = "unstable";
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
name = "22.11";
|
||||||
|
pkgs = nixpkgs-22_11.legacyPackages.${system};
|
||||||
|
}
|
||||||
];
|
];
|
||||||
testNames = [
|
testNames = [
|
||||||
"internal"
|
"internal"
|
||||||
@ -54,7 +59,16 @@
|
|||||||
# don't care about this package but it is part of the
|
# don't care about this package but it is part of the
|
||||||
# NixOS module evaluation)
|
# NixOS module evaluation)
|
||||||
nixpkgs.config.allowBroken = true;
|
nixpkgs.config.allowBroken = true;
|
||||||
mailserver.fqdn = "mx.example.com";
|
mailserver = {
|
||||||
|
fqdn = "mx.example.com";
|
||||||
|
domains = [
|
||||||
|
"example.com"
|
||||||
|
];
|
||||||
|
dmarcReporting = {
|
||||||
|
organizationName = "Example Corp";
|
||||||
|
domain = "example.com";
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ in
|
|||||||
|
|
||||||
mail_access_groups = ${vmailGroupName}
|
mail_access_groups = ${vmailGroupName}
|
||||||
ssl = required
|
ssl = required
|
||||||
ssl_min_protocol = TLSv1.2
|
ssl_min_protocol = TLSv1
|
||||||
ssl_prefer_server_ciphers = yes
|
ssl_prefer_server_ciphers = yes
|
||||||
|
|
||||||
service lmtp {
|
service lmtp {
|
||||||
|
@ -206,10 +206,10 @@ in
|
|||||||
smtpd_tls_eecdh_grade = "ultra";
|
smtpd_tls_eecdh_grade = "ultra";
|
||||||
|
|
||||||
# Disable obselete protocols
|
# Disable obselete protocols
|
||||||
smtpd_tls_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
smtpd_tls_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, TLSv1, !SSLv2, !SSLv3";
|
||||||
smtp_tls_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
smtp_tls_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, TLSv1, !SSLv2, !SSLv3";
|
||||||
smtpd_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
smtpd_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, TLSv1, !SSLv2, !SSLv3";
|
||||||
smtp_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
smtp_tls_mandatory_protocols = "TLSv1.3, TLSv1.2, TLSv1.1, TLSv1, !SSLv2, !SSLv3";
|
||||||
|
|
||||||
smtp_tls_ciphers = "high";
|
smtp_tls_ciphers = "high";
|
||||||
smtpd_tls_ciphers = "high";
|
smtpd_tls_ciphers = "high";
|
||||||
|
@ -56,6 +56,17 @@ in
|
|||||||
# Disable outbound email signing, we use opendkim for this
|
# Disable outbound email signing, we use opendkim for this
|
||||||
enabled = false;
|
enabled = false;
|
||||||
''; };
|
''; };
|
||||||
|
"dmarc.conf" = { text = ''
|
||||||
|
${lib.optionalString cfg.dmarcReporting.enable ''
|
||||||
|
reporting {
|
||||||
|
enabled = true;
|
||||||
|
email = "${cfg.dmarcReporting.email}";
|
||||||
|
domain = "${cfg.dmarcReporting.domain}";
|
||||||
|
org_name = "${cfg.dmarcReporting.organizationName}";
|
||||||
|
from_name = "${cfg.dmarcReporting.fromName}";
|
||||||
|
msgid_from = "dmarc-rua";
|
||||||
|
}''}
|
||||||
|
''; };
|
||||||
};
|
};
|
||||||
|
|
||||||
overrides = {
|
overrides = {
|
||||||
@ -108,6 +119,64 @@ in
|
|||||||
after = [ "redis-rspamd.service" ] ++ (lib.optional cfg.virusScanning "clamav-daemon.service");
|
after = [ "redis-rspamd.service" ] ++ (lib.optional cfg.virusScanning "clamav-daemon.service");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services.rspamd-dmarc-reporter = lib.optionalAttrs (cfg.dmarcReporting.enable) {
|
||||||
|
# Explicitly select yesterday's date to work around broken
|
||||||
|
# default behaviour when called without a date.
|
||||||
|
# https://github.com/rspamd/rspamd/issues/4062
|
||||||
|
script = ''
|
||||||
|
${pkgs.rspamd}/bin/rspamadm dmarc_report $(date -d "yesterday" "+%Y%m%d")
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
User = "${config.services.rspamd.user}";
|
||||||
|
Group = "${config.services.rspamd.group}";
|
||||||
|
|
||||||
|
AmbientCapabilities = [];
|
||||||
|
CapabilityBoundingSet = "";
|
||||||
|
DevicePolicy = "closed";
|
||||||
|
IPAddressAllow = "localhost";
|
||||||
|
LockPersonality = true;
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
PrivateDevices = true;
|
||||||
|
PrivateMounts = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
PrivateUsers = true;
|
||||||
|
ProtectClock = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ProtectHome = true;
|
||||||
|
ProtectHostname = true;
|
||||||
|
ProtectKernelLogs = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectProc = "invisible";
|
||||||
|
ProcSubset = "pid";
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
RemoveIPC = true;
|
||||||
|
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
RestrictSUIDSGID = true;
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
SystemCallFilter = [
|
||||||
|
"@system-service"
|
||||||
|
"~@privileged"
|
||||||
|
];
|
||||||
|
UMask = "0077";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.timers.rspamd-dmarc-reporter = lib.optionalAttrs (cfg.dmarcReporting.enable) {
|
||||||
|
description = "Daily delivery of aggregated DMARC reports";
|
||||||
|
wantedBy = [
|
||||||
|
"timers.target"
|
||||||
|
];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "daily";
|
||||||
|
Persistent = true;
|
||||||
|
RandomizedDelaySec = 86400;
|
||||||
|
FixedRandomDelay = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.postfix = {
|
systemd.services.postfix = {
|
||||||
after = [ rspamdSocket ];
|
after = [ rspamdSocket ];
|
||||||
requires = [ rspamdSocket ];
|
requires = [ rspamdSocket ];
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
import textwrap
|
||||||
|
|
||||||
header = """
|
header = """
|
||||||
Mailserver Options
|
Mailserver Options
|
||||||
@ -19,6 +20,7 @@ template = """
|
|||||||
|
|
||||||
{type}
|
{type}
|
||||||
{default}
|
{default}
|
||||||
|
{example}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
f = open(sys.argv[1])
|
f = open(sys.argv[1])
|
||||||
@ -30,36 +32,44 @@ options = {k: v for k, v in options.items()
|
|||||||
groups = ["mailserver.loginAccount",
|
groups = ["mailserver.loginAccount",
|
||||||
"mailserver.certificate",
|
"mailserver.certificate",
|
||||||
"mailserver.dkim",
|
"mailserver.dkim",
|
||||||
|
"mailserver.dmarcReporting",
|
||||||
"mailserver.fullTextSearch",
|
"mailserver.fullTextSearch",
|
||||||
"mailserver.redis",
|
"mailserver.redis",
|
||||||
"mailserver.monitoring",
|
"mailserver.monitoring",
|
||||||
"mailserver.backup",
|
"mailserver.backup",
|
||||||
"mailserver.borg"]
|
"mailserver.borg"]
|
||||||
|
|
||||||
|
def render_option_value(opt, attr):
|
||||||
|
if attr in opt:
|
||||||
|
if isinstance(opt[attr], dict) and '_type' in opt[attr]:
|
||||||
|
if opt[attr]['_type'] == 'literalExpression':
|
||||||
|
if '\n' in opt[attr]['text']:
|
||||||
|
res = '\n.. code:: nix\n\n' + textwrap.indent(opt[attr]['text'], ' ') + '\n'
|
||||||
|
else:
|
||||||
|
res = '``{}``'.format(opt[attr]['text'])
|
||||||
|
elif opt[attr]['_type'] == 'literalDocBook':
|
||||||
|
res = opt[attr]['text']
|
||||||
|
else:
|
||||||
|
s = str(opt[attr])
|
||||||
|
if s == "":
|
||||||
|
res = '``""``'
|
||||||
|
elif '\n' in s:
|
||||||
|
res = '\n.. code::\n\n' + textwrap.indent(s, ' ') + '\n'
|
||||||
|
else:
|
||||||
|
res = '``{}``'.format(s)
|
||||||
|
res = '- ' + attr + ': ' + res
|
||||||
|
else:
|
||||||
|
res = ""
|
||||||
|
return res
|
||||||
|
|
||||||
def print_option(name, value):
|
def print_option(name, value):
|
||||||
if 'default' in value:
|
|
||||||
if value['default'] == "":
|
|
||||||
default = '``""``'
|
|
||||||
elif isinstance(value['default'], dict) and '_type' in value['default']:
|
|
||||||
if value['default']['_type'] == 'literalExpression':
|
|
||||||
default = '``{}``'.format(value['default']['text'])
|
|
||||||
if value['default']['_type'] == 'literalDocBook':
|
|
||||||
default = value['default']['text']
|
|
||||||
else:
|
|
||||||
default = '``{}``'.format(value['default'])
|
|
||||||
# Some default values contains OUTPUTPATHS which make the
|
|
||||||
# output not stable across nixpkgs updates.
|
|
||||||
default = re.sub('/nix/store/[\w.-]*/', '<OUTPUT-PATH>/', default) # noqa
|
|
||||||
default = '- Default: ' + default
|
|
||||||
else:
|
|
||||||
default = ""
|
|
||||||
print(template.format(
|
print(template.format(
|
||||||
key=name,
|
key=name,
|
||||||
line="-"*len(name),
|
line="-"*len(name),
|
||||||
description=value['description'],
|
description=value['description'] or "",
|
||||||
type="- Type: ``{}``".format(value['type']),
|
type="- type: ``{}``".format(value['type']),
|
||||||
default=default))
|
default=render_option_value(value, 'default'),
|
||||||
|
example=render_option_value(value, 'example')))
|
||||||
|
|
||||||
|
|
||||||
print(header)
|
print(header)
|
||||||
|
@ -189,10 +189,10 @@ pkgs.nixosTest {
|
|||||||
|
|
||||||
# TODO put this blocking into the systemd units? I am not sure if rspamd already waits for the clamd socket.
|
# TODO put this blocking into the systemd units? I am not sure if rspamd already waits for the clamd socket.
|
||||||
server.wait_until_succeeds(
|
server.wait_until_succeeds(
|
||||||
"set +e; timeout 1 ${nodes.server.pkgs.netcat}/bin/nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
"set +e; timeout 1 ${nodes.server.nixpkgs.pkgs.netcat}/bin/nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||||
)
|
)
|
||||||
server.wait_until_succeeds(
|
server.wait_until_succeeds(
|
||||||
"set +e; timeout 1 ${nodes.server.pkgs.netcat}/bin/nc -U /run/clamav/clamd.ctl < /dev/null; [ $? -eq 124 ]"
|
"set +e; timeout 1 ${nodes.server.nixpkgs.pkgs.netcat}/bin/nc -U /run/clamav/clamd.ctl < /dev/null; [ $? -eq 124 ]"
|
||||||
)
|
)
|
||||||
|
|
||||||
client.execute("cp -p /etc/root/.* ~/")
|
client.execute("cp -p /etc/root/.* ~/")
|
||||||
|
@ -43,6 +43,11 @@ pkgs.nixosTest {
|
|||||||
domains = [ "example.com" "example2.com" ];
|
domains = [ "example.com" "example2.com" ];
|
||||||
rewriteMessageId = true;
|
rewriteMessageId = true;
|
||||||
dkimKeyBits = 1535;
|
dkimKeyBits = 1535;
|
||||||
|
dmarcReporting = {
|
||||||
|
enable = true;
|
||||||
|
domain = "example.com";
|
||||||
|
organizationName = "ACME Corp";
|
||||||
|
};
|
||||||
|
|
||||||
loginAccounts = {
|
loginAccounts = {
|
||||||
"user1@example.com" = {
|
"user1@example.com" = {
|
||||||
@ -345,7 +350,7 @@ pkgs.nixosTest {
|
|||||||
|
|
||||||
# TODO put this blocking into the systemd units?
|
# TODO put this blocking into the systemd units?
|
||||||
server.wait_until_succeeds(
|
server.wait_until_succeeds(
|
||||||
"set +e; timeout 1 ${nodes.server.pkgs.netcat}/bin/nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
"set +e; timeout 1 ${nodes.server.nixpkgs.pkgs.netcat}/bin/nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||||
)
|
)
|
||||||
|
|
||||||
client.execute("cp -p /etc/root/.* ~/")
|
client.execute("cp -p /etc/root/.* ~/")
|
||||||
@ -494,6 +499,10 @@ pkgs.nixosTest {
|
|||||||
# check that Junk is not indexed
|
# check that Junk is not indexed
|
||||||
server.fail("journalctl -u dovecot2 | grep 'indexer-worker' | grep -i 'JUNK' >&2")
|
server.fail("journalctl -u dovecot2 | grep 'indexer-worker' | grep -i 'JUNK' >&2")
|
||||||
|
|
||||||
|
with subtest("dmarc reporting"):
|
||||||
|
server.systemctl("start rspamd-dmarc-reporter.service")
|
||||||
|
server.wait_until_succeeds("journalctl -eu rspamd-dmarc-reporter.service -o cat | grep -q 'No reports for '")
|
||||||
|
|
||||||
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")
|
||||||
|
@ -29,8 +29,8 @@ let
|
|||||||
|
|
||||||
hashPassword = password: pkgs.runCommand
|
hashPassword = password: pkgs.runCommand
|
||||||
"password-${password}-hashed"
|
"password-${password}-hashed"
|
||||||
{ buildInputs = [ pkgs.apacheHttpd ]; } ''
|
{ buildInputs = [ pkgs.mkpasswd ]; inherit password; } ''
|
||||||
htpasswd -nbB "" "${password}" | cut -d: -f2 > $out
|
mkpasswd -sm bcrypt <<<"$password" > $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
hashedPasswordFile = hashPassword "my-password";
|
hashedPasswordFile = hashPassword "my-password";
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
import <nixpkgs/nixos/tests/make-test.nix> {
|
import <nixpkgs/nixos/tests/make-test-python.nix> {
|
||||||
|
|
||||||
machine =
|
nodes.machine =
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@ -26,6 +26,6 @@ import <nixpkgs/nixos/tests/make-test.nix> {
|
|||||||
|
|
||||||
testScript =
|
testScript =
|
||||||
''
|
''
|
||||||
$machine->waitForUnit("multi-user.target");
|
machine.wait_for_unit("multi-user.target");
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
let
|
let
|
||||||
hashPassword = password: pkgs.runCommand
|
hashPassword = password: pkgs.runCommand
|
||||||
"password-${password}-hashed"
|
"password-${password}-hashed"
|
||||||
{ buildInputs = [ pkgs.apacheHttpd ]; }
|
{ buildInputs = [ pkgs.mkpasswd ]; inherit password; }
|
||||||
''
|
''
|
||||||
htpasswd -nbB "" "${password}" | cut -d: -f2 > $out
|
mkpasswd -sm bcrypt <<<"$password" > $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
password = pkgs.writeText "password" "password";
|
password = pkgs.writeText "password" "password";
|
||||||
|
Loading…
Reference in New Issue
Block a user