From a68c330cd8d29c5e07549cd6bb811866b3ba1bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Fri, 9 Aug 2024 00:18:53 +0200 Subject: [PATCH] nixos/automx2: init --- nixos/modules/module-list.nix | 1 + nixos/modules/services/mail/automx2.nix | 108 ++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 nixos/modules/services/mail/automx2.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 11b0b2dbb9be..a58de6d0ca1c 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -651,6 +651,7 @@ ./services/logging/syslogd.nix ./services/logging/vector.nix ./services/logging/ulogd.nix + ./services/mail/automx2.nix ./services/mail/clamsmtp.nix ./services/mail/davmail.nix ./services/mail/dkimproxy-out.nix diff --git a/nixos/modules/services/mail/automx2.nix b/nixos/modules/services/mail/automx2.nix new file mode 100644 index 000000000000..2cfb5f491341 --- /dev/null +++ b/nixos/modules/services/mail/automx2.nix @@ -0,0 +1,108 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.automx2; + format = pkgs.formats.json { }; +in +{ + options = { + services.automx2 = { + enable = lib.mkEnableOption "automx2"; + + package = lib.mkPackageOption pkgs [ + "python3Packages" + "automx2" + ] { }; + + domain = lib.mkOption { + type = lib.types.str; + example = "example.com"; + description = '' + E-Mail-Domain for which mail client autoconfig/autoconfigure should be set up. + The `autoconfig` and `autodiscover` subdomains are automatically prepended and set up with ACME. + The names of those domains are hardcoded in the mail clients and are not configurable. + ''; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 4243; + description = "Port used by automx2."; + }; + + settings = lib.mkOption { + inherit (format) type; + description = '' + Bootstrap json to populate database. + See [docs](https://rseichter.github.io/automx2/#_sqlite) for details. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + services.nginx = { + enable = true; + virtualHosts = { + "autoconfig.${cfg.domain}" = { + enableACME = true; + forceSSL = true; + serverAliases = [ "autodiscover.${cfg.domain}" ]; + locations = { + "/".proxyPass = "http://127.0.0.1:${toString cfg.port}/"; + "/initdb".extraConfig = '' + # Limit access to clients connecting from localhost + allow 127.0.0.1; + deny all; + ''; + }; + }; + }; + }; + + systemd.services.automx2 = { + after = [ "network.target" ]; + postStart = '' + sleep 3 + ${lib.getExe pkgs.curl} -X POST --json @${format.generate "automx2.json" cfg.settings} http://127.0.0.1:${toString cfg.port}/initdb/ + ''; + serviceConfig = { + Environment = [ + "AUTOMX2_CONF=${pkgs.writeText "automx2-conf" '' + [automx2] + loglevel = WARNING + db_uri = sqlite:///:memory: + proxy_count = 1 + ''}" + "FLASK_APP=automx2.server:app" + "FLASK_CONFIG=production" + ]; + ExecStart = "${ + pkgs.python3.buildEnv.override { extraLibs = [ cfg.package ]; } + }/bin/flask run --host=127.0.0.1 --port=${toString cfg.port}"; + Restart = "always"; + StateDirectory = "automx2"; + User = "automx2"; + WorkingDirectory = "/var/lib/automx2"; + }; + unitConfig = { + Description = "MUA configuration service"; + Documentation = "https://rseichter.github.io/automx2/"; + }; + wantedBy = [ "multi-user.target" ]; + }; + + users = { + groups.automx2 = { }; + users.automx2 = { + group = "automx2"; + isSystemUser = true; + }; + }; + }; +}