Merge pull request #137260 from onny/maddy
This commit is contained in:
commit
29671bc365
@ -273,6 +273,13 @@
|
||||
<link xlink:href="options.html#opt-services.peertube.enable">services.peertube</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://maddy.email">maddy</link>, a
|
||||
composable all-in-one mail server. Available as
|
||||
<link xlink:href="options.html#opt-services.maddy.enable">services.maddy</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://sr.ht">sourcehut</link>, a
|
||||
|
@ -74,6 +74,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- [PeerTube](https://joinpeertube.org/), developed by Framasoft, is the free and decentralized alternative to video platforms. Available at [services.peertube](options.html#opt-services.peertube.enable).
|
||||
|
||||
- [maddy](https://maddy.email), a composable all-in-one mail server. Available as [services.maddy](options.html#opt-services.maddy.enable).
|
||||
|
||||
- [sourcehut](https://sr.ht), a collection of tools useful for software development. Available as [services.sourcehut](options.html#opt-services.sourcehut.enable).
|
||||
|
||||
- [ucarp](https://download.pureftpd.org/pub/ucarp/README), an userspace implementation of the Common Address Redundancy Protocol (CARP). Available as [networking.ucarp](options.html#opt-networking.ucarp.enable).
|
||||
|
@ -467,6 +467,7 @@
|
||||
./services/mail/dovecot.nix
|
||||
./services/mail/dspam.nix
|
||||
./services/mail/exim.nix
|
||||
./services/mail/maddy.nix
|
||||
./services/mail/mail.nix
|
||||
./services/mail/mailcatcher.nix
|
||||
./services/mail/mailhog.nix
|
||||
|
247
nixos/modules/services/mail/maddy.nix
Normal file
247
nixos/modules/services/mail/maddy.nix
Normal file
@ -0,0 +1,247 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
name = "maddy";
|
||||
cfg = config.services.maddy;
|
||||
defaultConfig = ''
|
||||
tls off
|
||||
|
||||
auth.pass_table local_authdb {
|
||||
table sql_table {
|
||||
driver sqlite3
|
||||
dsn credentials.db
|
||||
table_name passwords
|
||||
}
|
||||
}
|
||||
|
||||
storage.imapsql local_mailboxes {
|
||||
driver sqlite3
|
||||
dsn imapsql.db
|
||||
}
|
||||
|
||||
table.chain local_rewrites {
|
||||
optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3"
|
||||
optional_step static {
|
||||
entry postmaster postmaster@$(primary_domain)
|
||||
}
|
||||
optional_step file /etc/maddy/aliases
|
||||
}
|
||||
msgpipeline local_routing {
|
||||
destination postmaster $(local_domains) {
|
||||
modify {
|
||||
replace_rcpt &local_rewrites
|
||||
}
|
||||
deliver_to &local_mailboxes
|
||||
}
|
||||
default_destination {
|
||||
reject 550 5.1.1 "User doesn't exist"
|
||||
}
|
||||
}
|
||||
|
||||
smtp tcp://0.0.0.0:25 {
|
||||
limits {
|
||||
all rate 20 1s
|
||||
all concurrency 10
|
||||
}
|
||||
dmarc yes
|
||||
check {
|
||||
require_mx_record
|
||||
dkim
|
||||
spf
|
||||
}
|
||||
source $(local_domains) {
|
||||
reject 501 5.1.8 "Use Submission for outgoing SMTP"
|
||||
}
|
||||
default_source {
|
||||
destination postmaster $(local_domains) {
|
||||
deliver_to &local_routing
|
||||
}
|
||||
default_destination {
|
||||
reject 550 5.1.1 "User doesn't exist"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
submission tcp://0.0.0.0:587 {
|
||||
limits {
|
||||
all rate 50 1s
|
||||
}
|
||||
auth &local_authdb
|
||||
source $(local_domains) {
|
||||
check {
|
||||
authorize_sender {
|
||||
prepare_email &local_rewrites
|
||||
user_to_email identity
|
||||
}
|
||||
}
|
||||
destination postmaster $(local_domains) {
|
||||
deliver_to &local_routing
|
||||
}
|
||||
default_destination {
|
||||
modify {
|
||||
dkim $(primary_domain) $(local_domains) default
|
||||
}
|
||||
deliver_to &remote_queue
|
||||
}
|
||||
}
|
||||
default_source {
|
||||
reject 501 5.1.8 "Non-local sender domain"
|
||||
}
|
||||
}
|
||||
|
||||
target.remote outbound_delivery {
|
||||
limits {
|
||||
destination rate 20 1s
|
||||
destination concurrency 10
|
||||
}
|
||||
mx_auth {
|
||||
dane
|
||||
mtasts {
|
||||
cache fs
|
||||
fs_dir mtasts_cache/
|
||||
}
|
||||
local_policy {
|
||||
min_tls_level encrypted
|
||||
min_mx_level none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target.queue remote_queue {
|
||||
target &outbound_delivery
|
||||
autogenerated_msg_domain $(primary_domain)
|
||||
bounce {
|
||||
destination postmaster $(local_domains) {
|
||||
deliver_to &local_routing
|
||||
}
|
||||
default_destination {
|
||||
reject 550 5.0.0 "Refusing to send DSNs to non-local addresses"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imap tcp://0.0.0.0:143 {
|
||||
auth &local_authdb
|
||||
storage &local_mailboxes
|
||||
}
|
||||
'';
|
||||
|
||||
in {
|
||||
options = {
|
||||
services.maddy = {
|
||||
enable = mkEnableOption "Maddy, a free an open source mail server";
|
||||
|
||||
user = mkOption {
|
||||
default = "maddy";
|
||||
type = with types; uniq string;
|
||||
description = ''
|
||||
Name of the user under which maddy will run. If not specified, a
|
||||
default user will be created.
|
||||
'';
|
||||
};
|
||||
group = mkOption {
|
||||
default = "maddy";
|
||||
type = with types; uniq string;
|
||||
description = ''
|
||||
Name of the group under which maddy will run. If not specified, a
|
||||
default group will be created.
|
||||
'';
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
default = "localhost";
|
||||
type = with types; uniq string;
|
||||
example = ''example.com'';
|
||||
description = ''
|
||||
Hostname to use. It should be FQDN.
|
||||
'';
|
||||
};
|
||||
primaryDomain = mkOption {
|
||||
default = "localhost";
|
||||
type = with types; uniq string;
|
||||
example = ''mail.example.com'';
|
||||
description = ''
|
||||
Primary MX domain to use. It should be FQDN.
|
||||
'';
|
||||
};
|
||||
localDomains = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = ["$(primary_domain)"];
|
||||
example = [
|
||||
"$(primary_domain)"
|
||||
"example.com"
|
||||
"other.example.com"
|
||||
];
|
||||
description = ''
|
||||
Define list of allowed domains.
|
||||
'';
|
||||
};
|
||||
config = mkOption {
|
||||
type = with types; nullOr lines;
|
||||
default = defaultConfig;
|
||||
description = ''
|
||||
Server configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Open the configured incoming and outgoing mail server ports.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
systemd = {
|
||||
packages = [ pkgs.maddy ];
|
||||
services.maddy = {
|
||||
serviceConfig = {
|
||||
User = "${cfg.user}";
|
||||
Group = "${cfg.group}";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."maddy/maddy.conf" = {
|
||||
text = ''
|
||||
$(hostname) = ${cfg.hostname}
|
||||
$(primary_domain) = ${cfg.primaryDomain}
|
||||
$(local_domains) = ${toString cfg.localDomains}
|
||||
hostname ${cfg.hostname}
|
||||
${cfg.config}
|
||||
'';
|
||||
};
|
||||
|
||||
users.users = optionalAttrs (cfg.user == "maddy") {
|
||||
maddy = {
|
||||
description = "Maddy service user";
|
||||
group = cfg.group;
|
||||
home = "/var/lib/maddy";
|
||||
createHome = true;
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
|
||||
users.groups = mkIf (cfg.group == "maddy") {
|
||||
maddy = pkgs.lib.mkForce {
|
||||
name = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ 25 143 587 ];
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.maddy
|
||||
];
|
||||
};
|
||||
}
|
@ -247,6 +247,7 @@ in
|
||||
lxd-image-server = handleTest ./lxd-image-server.nix {};
|
||||
#logstash = handleTest ./logstash.nix {};
|
||||
lorri = handleTest ./lorri/default.nix {};
|
||||
maddy = handleTest ./maddy.nix {};
|
||||
magic-wormhole-mailbox-server = handleTest ./magic-wormhole-mailbox-server.nix {};
|
||||
magnetico = handleTest ./magnetico.nix {};
|
||||
mailcatcher = handleTest ./mailcatcher.nix {};
|
||||
|
58
nixos/tests/maddy.nix
Normal file
58
nixos/tests/maddy.nix
Normal file
@ -0,0 +1,58 @@
|
||||
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||
name = "maddy";
|
||||
meta = with pkgs.lib.maintainers; { maintainers = [ onny ]; };
|
||||
|
||||
nodes = {
|
||||
server = { ... }: {
|
||||
services.maddy = {
|
||||
enable = true;
|
||||
hostname = "server";
|
||||
primaryDomain = "server";
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
|
||||
client = { ... }: {
|
||||
environment.systemPackages = [
|
||||
(pkgs.writers.writePython3Bin "send-testmail" { } ''
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
msg = MIMEText("Hello World")
|
||||
msg['Subject'] = 'Test'
|
||||
msg['From'] = "postmaster@server"
|
||||
msg['To'] = "postmaster@server"
|
||||
with smtplib.SMTP('server', 587) as smtp:
|
||||
smtp.login('postmaster@server', 'test')
|
||||
smtp.sendmail('postmaster@server', 'postmaster@server', msg.as_string())
|
||||
'')
|
||||
(pkgs.writers.writePython3Bin "test-imap" { } ''
|
||||
import imaplib
|
||||
|
||||
with imaplib.IMAP4('server') as imap:
|
||||
imap.login('postmaster@server', 'test')
|
||||
imap.select()
|
||||
status, refs = imap.search(None, 'ALL')
|
||||
assert status == 'OK'
|
||||
assert len(refs) == 1
|
||||
status, msg = imap.fetch(refs[0], 'BODY[TEXT]')
|
||||
assert status == 'OK'
|
||||
assert msg[0][1].strip() == b"Hello World"
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
server.wait_for_unit("maddy.service")
|
||||
server.wait_for_open_port(143)
|
||||
server.wait_for_open_port(587)
|
||||
|
||||
server.succeed("echo test | maddyctl creds create postmaster@server")
|
||||
server.succeed("maddyctl imap-acct create postmaster@server")
|
||||
|
||||
client.succeed("send-testmail")
|
||||
client.succeed("test-imap")
|
||||
'';
|
||||
})
|
@ -1,4 +1,4 @@
|
||||
{ lib, buildGoModule, fetchFromGitHub, coreutils, installShellFiles, scdoc }:
|
||||
{ lib, buildGoModule, fetchFromGitHub, coreutils, installShellFiles, scdoc, nixosTests }:
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "maddy";
|
||||
@ -37,6 +37,8 @@ buildGoModule rec {
|
||||
--replace "/bin/kill" "${coreutils}/bin/kill"
|
||||
'';
|
||||
|
||||
passthru.tests.nixos = nixosTests.maddy;
|
||||
|
||||
meta = with lib; {
|
||||
description = "Composable all-in-one mail server";
|
||||
homepage = "https://maddy.email";
|
||||
|
Loading…
Reference in New Issue
Block a user