1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.services.automx2;
10 format = pkgs.formats.json { };
11in
12{
13 options = {
14 services.automx2 = {
15 enable = lib.mkEnableOption "automx2";
16
17 package = lib.mkPackageOption pkgs [
18 "python3Packages"
19 "automx2"
20 ] { };
21
22 domain = lib.mkOption {
23 type = lib.types.str;
24 example = "example.com";
25 description = ''
26 E-Mail-Domain for which mail client autoconfig/autoconfigure should be set up.
27 The `autoconfig` and `autodiscover` subdomains are automatically prepended and set up with ACME.
28 The names of those domains are hardcoded in the mail clients and are not configurable.
29 '';
30 };
31
32 port = lib.mkOption {
33 type = lib.types.port;
34 default = 4243;
35 description = "Port used by automx2.";
36 };
37
38 settings = lib.mkOption {
39 inherit (format) type;
40 description = ''
41 Bootstrap json to populate database.
42 See [docs](https://rseichter.github.io/automx2/#_sqlite) for details.
43 '';
44 };
45 };
46 };
47
48 config = lib.mkIf cfg.enable {
49 services.nginx = {
50 enable = true;
51 virtualHosts = {
52 "autoconfig.${cfg.domain}" = {
53 enableACME = true;
54 forceSSL = true;
55 serverAliases = [ "autodiscover.${cfg.domain}" ];
56 locations = {
57 "/".proxyPass = "http://127.0.0.1:${toString cfg.port}/";
58 "/initdb".extraConfig = ''
59 # Limit access to clients connecting from localhost
60 allow 127.0.0.1;
61 deny all;
62 '';
63 };
64 };
65 };
66 };
67
68 systemd.services.automx2 = {
69 after = [ "network.target" ];
70 postStart = ''
71 sleep 3
72 ${lib.getExe pkgs.curl} -X POST --json @${format.generate "automx2.json" cfg.settings} http://127.0.0.1:${toString cfg.port}/initdb/
73 '';
74 serviceConfig = {
75 Environment = [
76 "AUTOMX2_CONF=${pkgs.writeText "automx2-conf" ''
77 [automx2]
78 loglevel = WARNING
79 db_uri = sqlite:///:memory:
80 proxy_count = 1
81 ''}"
82 "FLASK_APP=automx2.server:app"
83 "FLASK_CONFIG=production"
84 ];
85 ExecStart = "${
86 pkgs.python3.buildEnv.override { extraLibs = [ cfg.package ]; }
87 }/bin/flask run --host=127.0.0.1 --port=${toString cfg.port}";
88 Restart = "always";
89 StateDirectory = "automx2";
90 User = "automx2";
91 WorkingDirectory = "/var/lib/automx2";
92 };
93 unitConfig = {
94 Description = "MUA configuration service";
95 Documentation = "https://rseichter.github.io/automx2/";
96 };
97 wantedBy = [ "multi-user.target" ];
98 };
99
100 users = {
101 groups.automx2 = { };
102 users.automx2 = {
103 group = "automx2";
104 isSystemUser = true;
105 };
106 };
107 };
108}