diff --git a/hosts/flora-6/README.md b/hosts/flora-6/README.md new file mode 100644 index 00000000..df71140c --- /dev/null +++ b/hosts/flora-6/README.md @@ -0,0 +1,16 @@ +# Mailman on NixOS docs + +- add reverse DNS record for IP + +Manual setup done for mailman, adapted from https://nixos.wiki/wiki/Mailman: + +``` +# Add DNS records in infra repo using terraform: +# https://git.pub.solar/pub-solar/infra/commit/db234cdb5b55758a3d74387ada0760e06e166b9d + +# Generate initial postfix_domains.db and postfix_lmtp.db databases for Postfix +sudo -u mailman mailman aliases +# Create a django superuser account +sudo -u mailman-web mailman-web createsuperuser +# Followed outlined steps in web UI +``` diff --git a/hosts/flora-6/caddy.nix b/hosts/flora-6/caddy.nix index 75746bc7..145c534c 100644 --- a/hosts/flora-6/caddy.nix +++ b/hosts/flora-6/caddy.nix @@ -5,6 +5,11 @@ self, ... }: { + # Changing the Caddyfile should only trigger a reload, not a restart + systemd.services.caddy.reloadTriggers = [ + config.services.caddy.configFile + ]; + services.caddy = { enable = lib.mkForce true; group = "hakkonaut"; @@ -77,7 +82,12 @@ output discard ''; extraConfig = '' - reverse_proxy :${services.sourcehut.lists.port} + handle_path /static/* { + root * /var/lib/mailman-web-static + file_server + } + + reverse_proxy :18507 ''; }; "obs-portal.pub.solar" = { diff --git a/hosts/flora-6/mailman.nix b/hosts/flora-6/mailman.nix index 90840234..2b423a77 100644 --- a/hosts/flora-6/mailman.nix +++ b/hosts/flora-6/mailman.nix @@ -5,53 +5,16 @@ self, ... }: let - postfixConfig = pkgs.writeTextFile { - name = "main.cf"; - text = builtins.readFile ./postfix/main.cf; - }; + # Source: https://github.com/NixOS/nixpkgs/blob/nixos-22.11/nixos/modules/services/mail/mailman.nix#L9C10-L10 + # webEnv is required by the mailman-uwsgi systemd service + inherit (pkgs.mailmanPackages.buildEnvs {}) webEnv; in { - system.activationScripts.mkMailmanNet = let - docker = config.virtualisation.oci-containers.backend; - dockerBin = "${pkgs.${docker}}/bin/${docker}"; - in '' - ${dockerBin} network inspect mailman-net >/dev/null 2>&1 || ${dockerBin} network create mailman-net --subnet 172.20.1.0/24 - ''; - - users.users.mailman = { - description = "Mailman Service"; - home = "/var/lib/mailman"; - useDefaultShell = true; - uid = 993; - # Group hakkonaut so caddy can serve the static files from mailman-web directly - group = "hakkonaut"; - isSystemUser = true; - }; - - systemd.tmpfiles.rules = [ - "d '/var/lib/mailman' 0750 mailman hakkonaut - -" - ]; - - age.secrets.mailman-core-secrets = { - file = "${self}/secrets/mailman-core-secrets.age"; - mode = "600"; - owner = "mailman"; - }; - - age.secrets.mailman-web-secrets = { - file = "${self}/secrets/mailman-web-secrets.age"; - mode = "600"; - owner = "mailman"; - }; - - age.secrets.mailman-db-secrets = { - file = "${self}/secrets/mailman-db-secrets.age"; - mode = "600"; - owner = "mailman"; - }; + networking.firewall.allowedTCPPorts = [25]; services.postfix = { enable = true; relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"]; + # FIXME: get TLS certs for list.pub.solar from caddy #sslCert = config.security.acme.certs."lists.example.org".directory + "/full.pem"; #sslKey = config.security.acme.certs."lists.example.org".directory + "/key.pem"; config = { @@ -59,114 +22,39 @@ in { local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"]; }; }; + services.mailman = { enable = true; + # We use caddy instead of nginx #serve.enable = true; hyperkitty.enable = true; webHosts = ["list.pub.solar"]; siteOwner = "admins@pub.solar"; }; - #virtualisation = { - # docker = { - # enable = true; - # }; - - # oci-containers = { - # backend = "docker"; - # containers."mailman-core" = { - # image = "maxking/mailman-core:0.4"; - # autoStart = true; - # #user = "993"; - # volumes = [ - # "/var/lib/mailman/core:/opt/mailman/" - # ]; - # extraOptions = [ - # "--network=mailman-net" - # ]; - # environment = { - # DATABASE_TYPE = "postgres"; - # DATABASE_CLASS = "mailman.database.postgresql.PostgreSQLDatabase"; - # MTA = "postfix"; - # }; - # environmentFiles = [ - # config.age.secrets.mailman-core-secrets.path - # ]; - # ports = [ - # "127.0.0.1:8001:8001" # API - # "127.0.0.1:8024:8024" # LMTP - incoming emails - # ]; - # }; - - # containers."mailman-web" = { - # image = "maxking/mailman-web:0.4"; - # autoStart = true; - # #user = "993:992"; - # volumes = [ - # "/var/lib/mailman/web:/opt/mailman-web-data" - # ]; - # extraOptions = [ - # "--network=mailman-net" - # ]; - # environment = { - # DATABASE_TYPE = "postgres"; - # SERVE_FROM_DOMAIN = "list.pub.solar"; - # MAILMAN_ADMIN_USER = "admin"; - # MAILMAN_ADMIN_EMAIL = "admins@pub.solar"; - # }; - # environmentFiles = [ - # config.age.secrets.mailman-web-secrets.path - # ]; - # ports = [ - # "127.0.0.1:8000:8000" # HTTP - # # "127.0.0.1:8080:8080" # uwsgi - # ]; - # }; - - # containers."mailman-db" = { - # image = "postgres:14-alpine"; - # autoStart = true; - # user = "993"; - # extraOptions = [ - # "--network=mailman-net" - # ]; - # volumes = [ - # "/var/lib/mailman/database:/var/lib/postgresql/data" - # ]; - # environmentFiles = [ - # config.age.secrets.mailman-db-secrets.path - # ]; - # }; - - # containers."mailman-postfix" = { - # image = "mailu/postfix:1.9.46"; - # autoStart = true; - # #user = "993"; - # extraOptions = [ - # "--hostname=list.pub.solar" - # "--network=mailman-net" - # ]; - # environment = { - # HOSTNAMES = "list.pub.solar"; - # FRONT_ADDRESS = "localhost"; - # ADMIN_ADDRESS = "localhost"; - # ANTISPAM_MILTER_ADDRESS = "localhost:11332"; - # LMTP_ADDRESS = "localhost:2525"; - # }; - # volumes = [ - # # https://mailu.io/1.9/faq.html#how-can-i-override-settings - # # Docs contain the wrong path to override main.cf, this one works - # "${postfixConfig}:/overrides/postfix.cf" - # # Configured in main.cf - # "/var/lib/mailman/postfix/mailqueue:/var/spool/postfix" - # "/var/lib/mailman/postfix/data:/var/lib/postfix" - # # Contains postfix transport_maps generated by mailman-core - # "/var/lib/mailman/core:/var/lib/mailman/core" - # ]; - # environmentFiles = [ - # config.age.secrets.mailman-db-secrets.path - # ]; - # }; - # }; - #}; + systemd.services.mailman-uwsgi = let + uwsgiConfig.uwsgi = { + type = "normal"; + plugins = ["python3"]; + home = webEnv; + manage-script-name = true; + mount = "/=mailman_web.wsgi:application"; + http = "127.0.0.1:18507"; + }; + uwsgiConfigFile = pkgs.writeText "uwsgi-mailman.json" (builtins.toJSON uwsgiConfig); + in { + wantedBy = ["multi-user.target"]; + after = ["postgresql.service"]; + requires = ["mailman-web-setup.service" "postgresql.service"]; + restartTriggers = [config.environment.etc."mailman3/settings.py".source]; + serviceConfig = { + # Since the mailman-web settings.py obstinately creates a logs + # dir in the cwd, change to the (writable) runtime directory before + # starting uwsgi. + ExecStart = "${pkgs.coreutils}/bin/env -C $RUNTIME_DIRECTORY ${pkgs.uwsgi.override {plugins = ["python3"];}}/bin/uwsgi --json ${uwsgiConfigFile}"; + User = "mailman-web"; + Group = "mailman"; + RuntimeDirectory = "mailman-uwsgi"; + }; + }; }