mirror of
https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git
synced 2024-12-25 06:26:27 +01:00
Compare commits
13 commits
abfa87b792
...
92a1729f36
Author | SHA1 | Date | |
---|---|---|---|
|
92a1729f36 | ||
|
63209b1def | ||
|
26a56d0a8f | ||
|
c43d8c4a3c | ||
|
6db6c0dc72 | ||
|
e4aabd3de6 | ||
|
1cf6d01989 | ||
|
0a801316cd | ||
|
9919033068 | ||
|
e901c56849 | ||
|
3a082011dc | ||
|
1861e82add | ||
|
14cc97446d |
15 changed files with 235 additions and 40 deletions
|
@ -32,8 +32,8 @@ let
|
|||
|
||||
desc = prJobsets // {
|
||||
"master" = mkFlakeJobset "master";
|
||||
"nixos-23.11" = mkFlakeJobset "nixos-23.11";
|
||||
"nixos-24.05" = mkFlakeJobset "nixos-24.05";
|
||||
"nixos-24.11" = mkFlakeJobset "nixos-24.11";
|
||||
};
|
||||
|
||||
log = {
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
For each NixOS release, we publish a branch. You then have to use the
|
||||
SNM branch corresponding to your NixOS version.
|
||||
|
||||
* For NixOS 24.11
|
||||
- Use the [SNM branch `nixos-24.11`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/nixos-24.11)
|
||||
- [Documentation](https://nixos-mailserver.readthedocs.io/en/nixos-24.11/)
|
||||
- [Release notes](https://nixos-mailserver.readthedocs.io/en/nixos-24.11/release-notes.html#nixos-24-11)
|
||||
* For NixOS 24.05
|
||||
- Use the [SNM branch `nixos-24.05`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/nixos-24.05)
|
||||
- [Documentation](https://nixos-mailserver.readthedocs.io/en/nixos-24.05/)
|
||||
- [Release notes](https://nixos-mailserver.readthedocs.io/en/nixos-24.05/release-notes.html#nixos-24-05)
|
||||
* For NixOS 23.11
|
||||
- Use the [SNM branch `nixos-23.11`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/nixos-23.11)
|
||||
- [Documentation](https://nixos-mailserver.readthedocs.io/en/nixos-23.11/)
|
||||
- [Release notes](https://nixos-mailserver.readthedocs.io/en/nixos-23.11/release-notes.html#nixos-23-11)
|
||||
* For NixOS unstable
|
||||
- Use the [SNM branch `master`](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/tree/master)
|
||||
- [Documentation](https://nixos-mailserver.readthedocs.io/en/latest/)
|
||||
|
|
|
@ -278,7 +278,7 @@ in
|
|||
dovecot = {
|
||||
userAttrs = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "";
|
||||
default = null;
|
||||
description = ''
|
||||
LDAP attributes to be retrieved during userdb lookups.
|
||||
|
||||
|
@ -506,7 +506,7 @@ in
|
|||
|
||||
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.
|
||||
|
@ -1298,6 +1298,7 @@ in
|
|||
|
||||
imports = [
|
||||
./mail-server/assertions.nix
|
||||
./mail-server/autoconfig
|
||||
./mail-server/borgbackup.nix
|
||||
./mail-server/debug.nix
|
||||
./mail-server/rsnapshot.nix
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
Release Notes
|
||||
=============
|
||||
|
||||
NixOS 24.11
|
||||
-----------
|
||||
|
||||
- No new feature, only bug fixes and documentation improvements
|
||||
|
||||
NixOS 24.05
|
||||
-----------
|
||||
|
||||
|
|
|
@ -20,25 +20,30 @@ an up and running mail server. Once the server is deployed, we could
|
|||
then set all DNS entries required to send and receive mails on this
|
||||
server.
|
||||
|
||||
Setup DNS A record for server
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Setup DNS A/AAAA records for server
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Add a DNS record to the domain ``example.com`` with the following
|
||||
Add DNS records to the domain ``example.com`` with the following
|
||||
entries
|
||||
|
||||
==================== ===== ==== =============
|
||||
Name (Subdomain) TTL Type Value
|
||||
==================== ===== ==== =============
|
||||
``mail.example.com`` 10800 A ``1.2.3.4``
|
||||
``mail.example.com`` 10800 AAAA ``2001::1``
|
||||
==================== ===== ==== =============
|
||||
|
||||
If your server does not have an IPv6 address, you must skip the `AAAA` record.
|
||||
|
||||
You can check this with
|
||||
|
||||
::
|
||||
|
||||
$ ping mail.example.com
|
||||
64 bytes from mail.example.com (1.2.3.4): icmp_seq=1 ttl=46 time=21.3 ms
|
||||
...
|
||||
$ nix-shell -p bind --command "host -t A mail.example.com"
|
||||
mail.example.com has address 1.2.3.4
|
||||
|
||||
$ nix-shell -p bind --command "host -t AAAA mail.example.com"
|
||||
mail.example.com has address 2001::1
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated. This
|
||||
DNS entry is required for the Let's Encrypt certificate generation
|
||||
|
@ -58,9 +63,9 @@ common ones.
|
|||
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-23.05/nixos-mailserver-nixos-23.05.tar.gz";
|
||||
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-24.11/nixos-mailserver-nixos-24.11.tar.gz";
|
||||
# To get the sha256 of the nixos-mailserver tarball, we can use the nix-prefetch-url command:
|
||||
# release="nixos-23.05"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
|
||||
# release="nixos-24.11"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
|
||||
sha256 = "0000000000000000000000000000000000000000000000000000";
|
||||
})
|
||||
];
|
||||
|
@ -98,8 +103,11 @@ Set rDNS (reverse DNS) entry for server
|
|||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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``
|
||||
to ``mail.example.com``.
|
||||
DNS entries for the IP’s you own:
|
||||
|
||||
- Add an entry resolving IPv4 address ``1.2.3.4`` to ``mail.example.com``.
|
||||
- Add an entry resolving IPv6 ``2001::1`` to ``mail.example.com``. Again, this
|
||||
must be skipped if your server does not have an IPv6 address.
|
||||
|
||||
.. warning::
|
||||
|
||||
|
@ -115,6 +123,9 @@ You can check this with
|
|||
$ nix-shell -p bind --command "host 1.2.3.4"
|
||||
4.3.2.1.in-addr.arpa domain name pointer mail.example.com.
|
||||
|
||||
$ nix-shell -p bind --command "host 2001::1"
|
||||
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.2.ip6.arpa domain name pointer mail.example.com.
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated.
|
||||
|
||||
Set a ``MX`` record
|
||||
|
|
18
flake.lock
18
flake.lock
|
@ -34,11 +34,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1717602782,
|
||||
"narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=",
|
||||
"lastModified": 1732014248,
|
||||
"narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6",
|
||||
"rev": "23e89b7da85c3640bbc2173fe04f4bd114342367",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -47,18 +47,18 @@
|
|||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-24_05": {
|
||||
"nixpkgs-24_11": {
|
||||
"locked": {
|
||||
"lastModified": 1717144377,
|
||||
"narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=",
|
||||
"lastModified": 1734083684,
|
||||
"narHash": "sha256-5fNndbndxSx5d+C/D0p/VF32xDiJCJzyOqorOYW4JEo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "805a384895c696f802a9bf5bf4720f37385df547",
|
||||
"rev": "314e12ba369ccdb9b352a4db26ff419f7c49fa84",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-24.05",
|
||||
"ref": "nixos-24.11",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
|
@ -67,7 +67,7 @@
|
|||
"blobs": "blobs",
|
||||
"flake-compat": "flake-compat",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-24_05": "nixpkgs-24_05"
|
||||
"nixpkgs-24_11": "nixpkgs-24_11"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
flake = false;
|
||||
};
|
||||
nixpkgs.url = "flake:nixpkgs/nixos-unstable";
|
||||
nixpkgs-24_05.url = "flake:nixpkgs/nixos-24.05";
|
||||
nixpkgs-24_11.url = "flake:nixpkgs/nixos-24.11";
|
||||
blobs = {
|
||||
url = "gitlab:simple-nixos-mailserver/blobs";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, blobs, nixpkgs, nixpkgs-24_05, ... }: let
|
||||
outputs = { self, blobs, nixpkgs, nixpkgs-24_11, ... }: let
|
||||
lib = nixpkgs.lib;
|
||||
system = "x86_64-linux";
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
|
@ -24,8 +24,8 @@
|
|||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
}
|
||||
{
|
||||
name = "24.05";
|
||||
pkgs = nixpkgs-24_05.legacyPackages.${system};
|
||||
name = "24.11";
|
||||
pkgs = nixpkgs-24_11.legacyPackages.${system};
|
||||
}
|
||||
];
|
||||
testNames = [
|
||||
|
|
100
mail-server/autoconfig/default.nix
Normal file
100
mail-server/autoconfig/default.nix
Normal file
|
@ -0,0 +1,100 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
ms = config.mailserver;
|
||||
cfg = ms.autoconfig;
|
||||
in
|
||||
{
|
||||
imports = [ ./webroot.nix ];
|
||||
|
||||
options.mailserver.autoconfig = mkOption {
|
||||
description = ''
|
||||
Generate a simple static Mozilla-style autoconfig.
|
||||
|
||||
See
|
||||
https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration
|
||||
for further information on the file format.
|
||||
|
||||
Note that for each domain in `domains`, this will generate a
|
||||
nginx `virtualHost` for the `autoconfig` subdomain of that
|
||||
domain.
|
||||
|
||||
In order for autoconfig to work, those domains must be
|
||||
accessible (i.e. have DNS records).
|
||||
'';
|
||||
type = types.submodule {
|
||||
options = {
|
||||
enable = mkEnableOption "Mozilla-style autoconfig (requires nginx)";
|
||||
|
||||
emailProviderId = mkOption {
|
||||
type = types.str;
|
||||
example = "example.com";
|
||||
default = ms.fqdn;
|
||||
defaultText = "config.mailserver.fqdn";
|
||||
description = ''
|
||||
An ID for the email provider.
|
||||
'';
|
||||
};
|
||||
|
||||
domains = mkOption {
|
||||
type = types.listOf types.str;
|
||||
example = [ "example.com" "example.net" ];
|
||||
default = ms.domains;
|
||||
defaultText = "config.mailserver.domains";
|
||||
description = ''
|
||||
A list of domains for which to enable autoconfig.
|
||||
'';
|
||||
};
|
||||
|
||||
displayName = mkOption {
|
||||
type = types.str;
|
||||
example = "Joe's Email Provider";
|
||||
default = cfg.emailProviderId;
|
||||
defaultText = "config.mailserver.autoconfig.id";
|
||||
description = ''
|
||||
A user-readable name for the email provider.
|
||||
'';
|
||||
};
|
||||
|
||||
displayShortName = mkOption {
|
||||
type = types.str;
|
||||
example = "JoeMail";
|
||||
default = cfg.displayName;
|
||||
defaultText = "config.mailserver.autoconfig.displayName";
|
||||
description = ''
|
||||
A "short" user-readable name for the email provider.
|
||||
'';
|
||||
};
|
||||
|
||||
templateFile = mkOption {
|
||||
type = types.path;
|
||||
example = "/path/to/template.xml";
|
||||
default = ./template.xml;
|
||||
description = ''
|
||||
A path to a template file to use.
|
||||
'';
|
||||
};
|
||||
|
||||
extraEmailProvider = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra XML to be embedded at the end of the <emailProvider> element.
|
||||
'';
|
||||
};
|
||||
|
||||
webRoot = mkOption {
|
||||
type = types.path;
|
||||
visible = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.mailserver.autoconfig.enable {
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts = mkMerge (map (domain: {
|
||||
"autoconfig.${domain}".root = cfg.webRoot;
|
||||
}) cfg.domains);
|
||||
};
|
||||
}
|
28
mail-server/autoconfig/template.xml
Normal file
28
mail-server/autoconfig/template.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<clientConfig version="1.1">
|
||||
<emailProvider id="@emailProviderId@">
|
||||
@domains@
|
||||
<displayName>@displayName@</displayName>
|
||||
<displayShortName>@displayShortName</displayShortName>
|
||||
@imapSslServer@
|
||||
@imapServer@
|
||||
@pop3SslServer@
|
||||
@pop3Server@
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>@fqdn@</hostname>
|
||||
<port>587</port>
|
||||
<socketType>STARTTLS</socketType>
|
||||
<authentication>password-cleartext</authentication>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
</outgoingServer>
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>@fqdn@</hostname>
|
||||
<port>25</port>
|
||||
<socketType>STARTTLS</socketType>
|
||||
<authentication>password-cleartext</authentication>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
</outgoingServer>
|
||||
@extraEmailProvider@
|
||||
</emailProvider>
|
||||
</clientConfig>
|
49
mail-server/autoconfig/webroot.nix
Normal file
49
mail-server/autoconfig/webroot.nix
Normal file
|
@ -0,0 +1,49 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
ms = config.mailserver;
|
||||
cfg = ms.autoconfig;
|
||||
|
||||
# none of the available parameters are configurable in
|
||||
# simple-mailserver so these templates aren't configurable either
|
||||
incomingServer = enable: port: socketType: optionalString enable ''
|
||||
<incomingServer type="imap">
|
||||
<hostname>${ms.fqdn}</hostname>
|
||||
<port>${builtins.toString port}</port>
|
||||
<socketType>${socketType}</socketType>
|
||||
<authentication>password-cleartext</authentication>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
</incomingServer>
|
||||
'';
|
||||
|
||||
# we currently only support STARTTLS for outgoing servers
|
||||
outgoingServer = port: ''
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>${ms.fqdn}</hostname>
|
||||
<port>${builtins.toString port}</port>
|
||||
<socketType>STARTTLS</socketType>
|
||||
<authentication>password-cleartext</authentication>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
</outgoingServer>
|
||||
'';
|
||||
in {
|
||||
mailserver.autoconfig.webRoot = pkgs.substituteAll ({
|
||||
name = "config-v1.1.xml";
|
||||
dir = "mail";
|
||||
src = cfg.templateFile;
|
||||
} // {
|
||||
hostname = ms.fqdn;
|
||||
inherit (cfg)
|
||||
emailProviderId displayName displayShortName extraEmailProvider;
|
||||
imapSslServer = incomingServer ms.enableImapSsl 993 "SSL";
|
||||
imapServer = incomingServer ms.enableImapSsl 143 "STARTTLS";
|
||||
pop3SslServer = incomingServer ms.enablePop3Ssl 995 "SSL";
|
||||
pop3Server = incomingServer ms.enablePop3 110 "STARTTLS";
|
||||
smtpServer = outgoingServer 25;
|
||||
submissionServer = outgoingServer 587;
|
||||
domains = concatMapStringsSep
|
||||
"\n "
|
||||
(x: "<domain>${x}</domain>")
|
||||
cfg.domains;
|
||||
});
|
||||
}
|
|
@ -62,7 +62,7 @@ in
|
|||
|
||||
cat ${file} > ${destination}
|
||||
echo -n '${prefix}' >> ${destination}
|
||||
cat ${passwordFile} >> ${destination}
|
||||
cat ${passwordFile} | tr -d '\n' >> ${destination}
|
||||
echo -n '${suffix}' >> ${destination}
|
||||
chmod 600 ${destination}
|
||||
'';
|
||||
|
|
|
@ -5,6 +5,7 @@ import uuid
|
|||
import imaplib
|
||||
from datetime import datetime, timedelta
|
||||
import email
|
||||
import email.utils
|
||||
import time
|
||||
|
||||
RETRY = 100
|
||||
|
@ -15,11 +16,16 @@ def _send_mail(smtp_host, smtp_port, smtp_username, from_addr, from_pwd, to_addr
|
|||
"From: {from_addr}",
|
||||
"To: {to_addr}",
|
||||
"Subject: {subject}",
|
||||
"Message-ID: {random}@mail-check.py",
|
||||
"Date: {date}",
|
||||
"",
|
||||
"This validates our mail server can send to Gmail :/"]).format(
|
||||
from_addr=from_addr,
|
||||
to_addr=to_addr,
|
||||
subject=subject)
|
||||
subject=subject,
|
||||
random=str(uuid.uuid4()),
|
||||
date=email.utils.formatdate(),
|
||||
)
|
||||
|
||||
|
||||
retry = RETRY
|
||||
|
|
|
@ -505,7 +505,7 @@ pkgs.nixosTest {
|
|||
with subtest("no warnings or errors"):
|
||||
server.fail("journalctl -u postfix | grep -i error >&2")
|
||||
server.fail("journalctl -u postfix | grep -i warning >&2")
|
||||
server.fail("journalctl -u dovecot2 | grep -i error >&2")
|
||||
server.fail("journalctl -u dovecot2 | grep -v 'imap-login: Debug: SSL error: Connection closed' | grep -i error >&2")
|
||||
# harmless ? https://dovecot.org/pipermail/dovecot/2020-August/119575.html
|
||||
server.fail(
|
||||
"journalctl -u dovecot2 |grep -v 'Expunged message reappeared, giving a new UID'| grep -v 'FTS Xapian: Box is empty' | grep -i warning >&2"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
security.dhparams.defaultBitSize = 1024; # minimum size required by dovecot
|
||||
security.dhparams.defaultBitSize = 2048; # minimum size required by dovecot
|
||||
}
|
||||
|
|
|
@ -30,12 +30,7 @@ let
|
|||
};
|
||||
services.dnsmasq = {
|
||||
enable = true;
|
||||
# Fixme: once nixos-22.11 has been removed, could be replaced by
|
||||
# settings.mx-host = [ "domain1.com,domain1,10" "domain2.com,domain2,10" ];
|
||||
extraConfig = ''
|
||||
mx-host=domain1.com,domain1,10
|
||||
mx-host=domain2.com,domain2,10
|
||||
'';
|
||||
settings.mx-host = [ "domain1.com,domain1,10" "domain2.com,domain2,10" ];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue