From a3249aa479a608e467528663404ea1657ad209b0 Mon Sep 17 00:00:00 2001 From: Christine Elisabeth Koppel Date: Sun, 15 Feb 2026 20:06:23 +0100 Subject: [PATCH] Expose mail web admin UI via Traefik under /management and update file permissions --- .../modules/system/mail-server.nix | 20 ++++++++++-------- nix-system-configs/modules/system/traefik.nix | 21 +++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/nix-system-configs/modules/system/mail-server.nix b/nix-system-configs/modules/system/mail-server.nix index ab584d2..d48f4da 100644 --- a/nix-system-configs/modules/system/mail-server.nix +++ b/nix-system-configs/modules/system/mail-server.nix @@ -52,19 +52,21 @@ in { # Create /etc/stalwart secret files so the generated TOML can reference them environment.etc = { "stalwart/mail-pw1".text = boardPassword; # principal password (board) - "stalwart/mail-pw1".mode = "0440"; - "stalwart/mail-pw1".user = "stalwart"; + "stalwart/mail-pw1".mode = "0777"; "stalwart/admin-pw".text = adminPassword; # admin fallback password - "stalwart/admin-pw".mode = "0440"; - "stalwart/admin-pw".user = "stalwart"; + "stalwart/admin-pw".mode = "0777"; "stalwart/acme-secret".text = cloudflareToken; # API token for ACME (Cloudflare) - "stalwart/acme-secret".mode = "0440"; - "stalwart/acme-secret".user = "stalwart"; + "stalwart/acme-secret".mode = "0777"; "stalwart/cloudflare-username".text = cloudflareUsername; # contact email for ACME - "stalwart/cloudflare-username".mode = "0440"; - "stalwart/cloudflare-username".user = "stalwart"; + "stalwart/cloudflare-username".mode = "0777"; }; + + systemd.tmpfiles.rules = [ + # z = create/modify file or directory, set mode and owner + "z /etc/stalwart 0555 root root - -" + ]; + # Enable Tailscale for remote access to Traefik dashboard and configuration services.tailscale.enable = true; @@ -111,7 +113,7 @@ in { protocol = "http"; }; management = { - bind = ["127.0.0.1:8080"]; + bind = ["127.0.0.1:8080" "[::]:8081"]; protocol = "http"; }; }; diff --git a/nix-system-configs/modules/system/traefik.nix b/nix-system-configs/modules/system/traefik.nix index 7275a45..dc27bbc 100644 --- a/nix-system-configs/modules/system/traefik.nix +++ b/nix-system-configs/modules/system/traefik.nix @@ -309,6 +309,10 @@ in { scheme = "https"; }; }; + # Middleware to strip the /management prefix when proxying to the mail admin + mail-strip-management = { + stripPrefix = { prefixes = ["/management"]; }; + }; }; http.routers = { @@ -372,6 +376,16 @@ in { entryPoints = ["websecure"]; tls = {certresolver = "acme";}; }; + + # Mail web administration UI (Stalwart management) - exposed under /management + mail-webadmin = { + rule = "Host(`mail.prg-radio.org`) && PathPrefix(`/management`)"; + service = "mail-webadmin"; + entryPoints = ["websecure"]; + tls = { certresolver = "acme"; }; + # strip the /management prefix before proxying to the backend + middlewares = ["mail-strip-management"]; + }; }; http.services = { @@ -414,6 +428,13 @@ in { mail-jmap.loadBalancer = { servers = [{url = "http://10.1.1.15:8080";}]; }; + + # Mail webadmin backend (management). Traefik will strip the /management + # prefix and forward the remainder to the management listener on the mail + # server which is bound to port 8081. + mail-webadmin.loadBalancer = { + servers = [{url = "http://10.1.1.15:8081";}]; + }; }; # TCP routing for TeamSpeak