From cb4b7e370dc2b4a444c8ff4b125e51498c6b1767 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Mon, 21 Jul 2025 20:28:06 -0400 Subject: [PATCH] WiP mail --- clients/quadraticserver/caddy.nix | 21 ++- clients/quadraticserver/mail/automx2.nix | 47 ++++++ .../quadraticserver/{ => mail}/bridges.nix | 0 clients/quadraticserver/mail/mailserver.nix | 37 +++++ clients/quadraticserver/mail/sogo.nix | 122 ++++++++++++++ flake.lock | 153 ++++++++++++++++-- flake.nix | 8 + modules/graphical/librewolf/default.nix | 1 + 8 files changed, 366 insertions(+), 23 deletions(-) create mode 100644 clients/quadraticserver/mail/automx2.nix rename clients/quadraticserver/{ => mail}/bridges.nix (100%) create mode 100644 clients/quadraticserver/mail/mailserver.nix create mode 100644 clients/quadraticserver/mail/sogo.nix diff --git a/clients/quadraticserver/caddy.nix b/clients/quadraticserver/caddy.nix index 4cdad67..058f470 100644 --- a/clients/quadraticserver/caddy.nix +++ b/clients/quadraticserver/caddy.nix @@ -1,12 +1,19 @@ -{pkgs, ...}: { +{ + pkgs, + lib, + ... +}: { networking.firewall.allowedTCPPorts = [443]; - services.caddy = { - enable = true; - email = "henry@henryhiles.com"; + services = { + nginx.enable = lib.mkForce false; + caddy = { + enable = true; + email = "hen" + "ry@he" + "nryhi" + "les.c" + "om"; - package = pkgs.caddy.withPlugins { - plugins = ["github.com/ggicci/caddy-jwt@v1.1.0"]; - hash = "sha256-sdhX/dAQ7lIxBo/ZW6XYX8SRuacLO9HobtIVKD/cw0o="; + package = pkgs.caddy.withPlugins { + plugins = ["github.com/ggicci/caddy-jwt@v1.1.0"]; + hash = "sha256-sdhX/dAQ7lIxBo/ZW6XYX8SRuacLO9HobtIVKD/cw0o="; + }; }; }; } diff --git a/clients/quadraticserver/mail/automx2.nix b/clients/quadraticserver/mail/automx2.nix new file mode 100644 index 0000000..9421b1e --- /dev/null +++ b/clients/quadraticserver/mail/automx2.nix @@ -0,0 +1,47 @@ +{ + lib, + config, + ... +}: { + services = let + domain = lib.head config.mailserver.domains; + fqdn = config.mailserver.fqdn; + in { + caddy.virtualHosts = { + "autoconfig.${domain}" = { + serverAliases = ["autodiscover.${domain}"]; + extraConfig = let + proxy = "reverse_proxy 127.0.0.1:${toString config.services.automx2.port}"; + in '' + route { + handle_path /initdb* { + @not_local not remote_ip 127.0.0.1 + abort @not_local + ${proxy} + } + + ${proxy} + } + ''; + }; + }; + automx2 = { + enable = true; + inherit domain; + settings = { + provider = "Federated Nexus"; + domains = [domain]; + servers = [ + { + type = "imap"; + name = fqdn; + } + { + type = "smtp"; + name = fqdn; + } + ]; + }; + }; + }; +} diff --git a/clients/quadraticserver/bridges.nix b/clients/quadraticserver/mail/bridges.nix similarity index 100% rename from clients/quadraticserver/bridges.nix rename to clients/quadraticserver/mail/bridges.nix diff --git a/clients/quadraticserver/mail/mailserver.nix b/clients/quadraticserver/mail/mailserver.nix new file mode 100644 index 0000000..c4bbe46 --- /dev/null +++ b/clients/quadraticserver/mail/mailserver.nix @@ -0,0 +1,37 @@ +{ + config, + inputs, + ... +}: let + domain = "federated.nexus"; + fqdn = "mail.${domain}"; + certDir = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${fqdn}"; +in { + imports = [inputs.mailserver.nixosModule]; + mailserver = { + enable = true; + stateVersion = 3; + + inherit fqdn; + domains = [domain]; + + localDnsResolver = false; + + certificateScheme = "manual"; + certificateFile = "${certDir}/${fqdn}.crt"; + keyFile = "${certDir}/${fqdn}.key"; + + oauth2 = let + auth = "https://auth.federated.nexus"; + in { + enable = true; + introspection = { + url = "${auth}/introspect"; + mode = "post"; + }; + oidc.configuration_url = "${auth}/.well-known/openid-configuration"; + }; + }; + + services.dovecot2.group = config.services.caddy.group; +} diff --git a/clients/quadraticserver/mail/sogo.nix b/clients/quadraticserver/mail/sogo.nix new file mode 100644 index 0000000..3613973 --- /dev/null +++ b/clients/quadraticserver/mail/sogo.nix @@ -0,0 +1,122 @@ +{ + lib, + pkgs, + config, + ... +}: { + nixpkgs.overlays = [ + (final: prev: { + sogo = prev.sogo.overrideAttrs (old: { + buildInputs = old.buildInputs ++ [prev.postgresql.lib]; + NIX_LDFLAGS = (old.NIX_LDFLAGS or "") + " -lpq"; + }); + }) + ]; + + services = let + domain = "mail.federated.nexus"; + in { + memcached = { + enable = true; + user = "sogo"; + enableUnixSocket = true; + extraOptions = [ + "-a" + "0600" + ]; + }; + + postgresql = { + enable = true; + enableTCPIP = true; + + ensureDatabases = ["sogo"]; + ensureUsers = [ + { + name = "sogo"; + ensureDBOwnership = true; + } + ]; + }; + + sogo = { + enable = true; + timezone = config.time.timeZone; + extraConfig = let + db = "postgresql://sogo@127.0.0.1/sogo"; + in '' + SOGoMailDomain = "federated.nexus"; + SOGoMemcachedHost = "/run/memcached/memcached.sock"; + + SOGoAuthenticationType = "openid"; + SOGoOpenIdConfigUrl = "https://auth.federated.nexus/.well-known/openid-configuration"; + SOGoOpenIdClient = "Federated Nexus Auth"; + SOGoOpenIdClientSecret = ""; + SOGoOpenIdScope = ""; + SOGoOpenIdTokenCheckInterval = 600; + + SOGoSMTPServer = "smtp://localhost"; + SOGoSMTPAuthenticationType = "xoauth2"; + + SOGoIMAPServer = "imap://localhost"; + NGImap4AuthMechanism = "xoauth2"; + + SOGoPageTitle = "Federated Nexus Mail"; + SOGoZipPath = "${lib.getExe pkgs.zip}"; + + OCSSessionsFolderURL = "${db}/sogo_sessions_folder"; + OCSFolderInfoURL = "${db}/sogo_folder_info"; + OCSOpenIdURL = "${db}/sogo_openid"; + MySQL4Encoding = "utf8mb4"; + ''; + }; + + caddy.virtualHosts."${domain}".extraConfig = '' + # Redirect root to /SOGo + @root path / + redir @root https://{host}/SOGo + + # Redirect /principals/ to /SOGo/dav + @principals path /principals/* + redir @principals https://{host}/SOGo/dav + + # Static assets for SOGo + handle_path /SOGo.woa/WebServerResources/* { + root * ${pkgs.sogo}/lib/GNUstep/SOGo/WebServerResources/ + file_server + } + + handle_path /SOGo/WebServerResources/* { + root * ${pkgs.sogo}/lib/GNUstep/SOGo/ + file_server + } + + # Regex match: ControlPanel products + @resources1 path_regexp resources1 ^/SOGo/so/ControlPanel/Products/([^/]*)/Resources/(.*)$ + handle @resources1 { + root * ${pkgs.sogo}/lib/GNUstep/SOGo/{http.regexp.resources1.1}.SOGo/Resources/ + rewrite * /{http.regexp.resources1.2} + file_server + } + + # Regex match: ControlPanel UI resources + @resources2 path_regexp resources2 ^/SOGo/so/ControlPanel/Products/([^/]*)UI/Resources/(.*\.(jpg|png|gif|css|js))$ + handle @resources2 { + root * ${pkgs.sogo}/lib/GNUstep/SOGo/{http.regexp.resources2.1}UI.SOGo/Resources/ + rewrite * /{http.regexp.resources2.2} + file_server + } + + # SOGo app proxy + handle_path /SOGo* { + reverse_proxy 127.0.0.1:20000 { + header_up x-webobjects-server-protocol HTTP/1.0 + header_up x-webobjects-remote-host 127.0.0.1 + header_up x-webobjects-server-port {server_port} + header_up x-webobjects-server-name {host} + header_up x-webobjects-server-url {scheme}://{host} + } + } + ''; + }; +} diff --git a/flake.lock b/flake.lock index 14f2281..a4a8d48 100644 --- a/flake.lock +++ b/flake.lock @@ -233,6 +233,22 @@ "type": "github" } }, + "blobs": { + "flake": false, + "locked": { + "lastModified": 1604995301, + "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=", + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "type": "gitlab" + } + }, "cachix": { "inputs": { "devenv": [ @@ -730,6 +746,22 @@ } }, "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { "flake": false, "locked": { "lastModified": 1641205782, @@ -745,7 +777,7 @@ "type": "github" } }, - "flake-compat_5": { + "flake-compat_6": { "flake": false, "locked": { "lastModified": 1747046372, @@ -1034,6 +1066,32 @@ "type": "github" } }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "mailserver", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "mailserver", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750779888, + "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "git-hooks-nix": { "inputs": { "flake-compat": [ @@ -1063,6 +1121,28 @@ "type": "github" } }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "mailserver", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "gitignore-nix": { "inputs": { "nixpkgs": [ @@ -1419,6 +1499,30 @@ "type": "github" } }, + "mailserver": { + "inputs": { + "blobs": "blobs", + "flake-compat": "flake-compat_4", + "git-hooks": "git-hooks", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-25_05": "nixpkgs-25_05" + }, + "locked": { + "lastModified": 1753026197, + "narHash": "sha256-v8uYdWXzPPatsK5LerstRhtG9h9PV9b2oUqCvqySqvk=", + "ref": "refs/heads/pr-oauth2", + "rev": "57e1944ff77ffdb5a1a4bd5ba6aea2b361103e88", + "revCount": 774, + "type": "git", + "url": "file:///home/quadradical/Documents/Code/nixos-mailserver" + }, + "original": { + "type": "git", + "url": "file:///home/quadradical/Documents/Code/nixos-mailserver" + } + }, "matrixoidc": { "inputs": { "flake-parts": "flake-parts_3", @@ -1427,11 +1531,11 @@ ] }, "locked": { - "lastModified": 1750620651, - "narHash": "sha256-MqmzdsKUrOTN8NhjuldA1GHMgVsWsBmtMgHzpiSWnn0=", + "lastModified": 1753043463, + "narHash": "sha256-YLzOivNTm8Ho2z5Gt3v95T3uF3ujKxyTGDiDpH5oUiw=", "ref": "refs/heads/main", - "rev": "13a469ba6dfbb1ef6431570b952fb4a78471e63f", - "revCount": 28, + "rev": "43ad7937f9be93c93379d5adb0878b8e98cdfd3f", + "revCount": 33, "type": "git", "url": "https://git.federated.nexus/Henry-Hiles/matrixoidc" }, @@ -1859,7 +1963,7 @@ "nix-matrix-appservices": { "inputs": { "devshell": "devshell", - "flake-compat": "flake-compat_4", + "flake-compat": "flake-compat_5", "nixlib": "nixlib", "nixpkgs": [ "nixpkgs" @@ -2116,6 +2220,22 @@ "type": "github" } }, + "nixpkgs-25_05": { + "locked": { + "lastModified": 1751741127, + "narHash": "sha256-t75Shs76NgxjZSgvvZZ9qOmz5zuBE8buUaYD28BMTxg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "29e290002bfff26af1db6f64d070698019460302", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs-alsa-ucm-conf": { "locked": { "lastModified": 1749323015, @@ -2260,11 +2380,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1752687322, - "narHash": "sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo=", + "lastModified": 1752950548, + "narHash": "sha256-NS6BLD0lxOrnCiEOcvQCDVPXafX1/ek1dfJHX1nUIzc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "6e987485eb2c77e5dcc5af4e3c70843711ef9251", + "rev": "c87b95e25065c028d31a94f06a62927d18763fdf", "type": "github" }, "original": { @@ -2521,11 +2641,11 @@ "utils": "utils" }, "locked": { - "lastModified": 1752921952, - "narHash": "sha256-Sb1nAoC99Uw25hBbGorQRnwaGv1mhmPZOoPzT39nX4w=", + "lastModified": 1753038291, + "narHash": "sha256-lURYdS0bLEpd0CatDK2IYTKVqp75vzgJUi5yCej1k/A=", "owner": "wamserma", "repo": "flake-programs-sqlite", - "rev": "709ad5fe9db09825a9b0933b9ab2096071ee6cfe", + "rev": "c8ce0a0e0b95a201f2f931f441c58edf628a532a", "type": "github" }, "original": { @@ -2561,6 +2681,7 @@ "gnome-mobile": "gnome-mobile", "grapevine": "grapevine", "home-manager": "home-manager_2", + "mailserver": "mailserver", "matrixoidc": "matrixoidc", "nix-matrix-appservices": "nix-matrix-appservices", "nixpkgs": "nixpkgs_2", @@ -2688,7 +2809,7 @@ "disko": "disko_2", "emacs-overlay": "emacs-overlay", "fenix": "fenix_2", - "flake-compat": "flake-compat_5", + "flake-compat": "flake-compat_6", "flake-parts": "flake-parts_4", "flake-schemas": "flake-schemas", "flake-utils": "flake-utils_4", @@ -2798,11 +2919,11 @@ "tinted-zed": "tinted-zed" }, "locked": { - "lastModified": 1752947709, - "narHash": "sha256-dtyj+wJs/t8hf1Xd2RMS5Zu7RjwZfAZJ1R4qsQ9vSrM=", + "lastModified": 1753009241, + "narHash": "sha256-puhWbjjrOtOlYYV0R2J99V905vUjF+NqyK5N+kiVZXg=", "owner": "danth", "repo": "stylix", - "rev": "24499b0049881959bd4e159b6fe4e96e4c03db25", + "rev": "9242b3ec8e0d253f32614778ed4996af7aaf9438", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index c68f0c1..7f83872 100755 --- a/flake.nix +++ b/flake.nix @@ -9,6 +9,14 @@ url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; + # mailserver = { + # url = "gitlab:simple-nixos-mailserver/nixos-mailserver"; + # inputs.nixpkgs.follows = "nixpkgs"; + # }; + mailserver = { + url = "git+file:///home/quadradical/Documents/Code/nixos-mailserver"; + inputs.nixpkgs.follows = "nixpkgs"; + }; run0-sudo-shim = { url = "github:lordgrimmauld/run0-sudo-shim"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/modules/graphical/librewolf/default.nix b/modules/graphical/librewolf/default.nix index 97b2158..7b15e71 100644 --- a/modules/graphical/librewolf/default.nix +++ b/modules/graphical/librewolf/default.nix @@ -165,6 +165,7 @@ Alias = "nw"; } ]; + Remove = ["Bing"]; }; }; };