From 436dc9facd462c6ca51e59c331b1c6aba2ce60ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Sat, 11 Oct 2025 21:11:41 +0200 Subject: [PATCH 1/4] nixos/zammad: clean up --- nixos/modules/services/development/zammad.nix | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/nixos/modules/services/development/zammad.nix b/nixos/modules/services/development/zammad.nix index b0917b6b8893..2893b1168c6b 100644 --- a/nixos/modules/services/development/zammad.nix +++ b/nixos/modules/services/development/zammad.nix @@ -32,7 +32,6 @@ let }; in { - options = { services.zammad = { enable = lib.mkEnableOption "Zammad, a web-based, open source user support/ticketing solution"; @@ -245,21 +244,23 @@ in } ]; - services.postgresql = lib.optionalAttrs (cfg.database.createLocally) { - enable = true; - ensureDatabases = [ cfg.database.name ]; - ensureUsers = [ - { - name = cfg.database.user; - ensureDBOwnership = true; - } - ]; - }; - - services.redis = lib.optionalAttrs cfg.redis.createLocally { - servers."${cfg.redis.name}" = { + services = { + postgresql = lib.optionalAttrs cfg.database.createLocally { enable = true; - port = cfg.redis.port; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [ + { + name = cfg.database.user; + ensureDBOwnership = true; + } + ]; + }; + + redis = lib.optionalAttrs cfg.redis.createLocally { + servers."${cfg.redis.name}" = { + enable = true; + port = cfg.redis.port; + }; }; }; @@ -273,13 +274,13 @@ in "network.target" "systemd-tmpfiles-setup.service" ] - ++ lib.optionals (cfg.database.createLocally) [ + ++ lib.optionals cfg.database.createLocally [ "postgresql.target" ] ++ lib.optionals cfg.redis.createLocally [ "redis-${cfg.redis.name}.service" ]; - requires = lib.optionals (cfg.database.createLocally) [ + requires = lib.optionals cfg.database.createLocally [ "postgresql.target" ]; description = "Zammad web"; From ee70666d6dd1dcca9e29bea5842b30aedf2ae4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Sat, 11 Oct 2025 21:12:04 +0200 Subject: [PATCH 2/4] nixos/zammad: remove openPorts option, add options to configure nginx --- nixos/modules/services/development/zammad.nix | 65 +++++++++++++++---- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/nixos/modules/services/development/zammad.nix b/nixos/modules/services/development/zammad.nix index 2893b1168c6b..d269f8773077 100644 --- a/nixos/modules/services/development/zammad.nix +++ b/nixos/modules/services/development/zammad.nix @@ -69,12 +69,6 @@ in description = "Host address."; }; - openPorts = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Whether to open firewall ports for Zammad"; - }; - port = lib.mkOption { type = lib.types.port; default = 3000; @@ -176,6 +170,19 @@ in }; }; + nginx = { + configure = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to configure a local nginx for Zammad."; + }; + + domain = lib.mkOption { + type = lib.types.str; + description = "The domain under which zammad will be reachable."; + }; + }; + secretKeyBaseFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; @@ -202,6 +209,14 @@ in }; }; + imports = [ + (lib.mkRemovedOptionModule [ + "services" + "zammad" + "openPorts" + ] "The openPorts option was removed in favor of the nginx.configure option.") + ]; + config = lib.mkIf cfg.enable { services.zammad.database.settings = { production = lib.mapAttrs (_: v: lib.mkDefault v) (filterNull { @@ -216,11 +231,6 @@ in }); }; - networking.firewall.allowedTCPPorts = lib.mkIf cfg.openPorts [ - config.services.zammad.port - config.services.zammad.websocketPort - ]; - users.users.${cfg.user} = { group = "${cfg.group}"; isSystemUser = true; @@ -245,6 +255,39 @@ in ]; services = { + nginx = lib.mkIf cfg.nginx.configure { + enable = true; + virtualHosts."${cfg.nginx.domain}" = { + forceSSL = true; + locations = { + "/" = { + proxyPass = "http://127.0.0.1:${toString config.services.zammad.port}"; + root = "${config.services.zammad.package}/public/"; + extraConfig = # nginx + '' + proxy_set_header CLIENT_IP $remote_addr; + ''; + }; + "/cable" = { + proxyPass = "http://127.0.0.1:${toString config.services.zammad.port}"; + proxyWebsockets = true; + extraConfig = # nginx + '' + proxy_set_header CLIENT_IP $remote_addr; + ''; + }; + "/ws" = { + proxyPass = "http://127.0.0.1:${toString config.services.zammad.websocketPort}"; + proxyWebsockets = true; + extraConfig = # nginx + '' + proxy_set_header CLIENT_IP $remote_addr; + ''; + }; + }; + }; + }; + postgresql = lib.optionalAttrs cfg.database.createLocally { enable = true; ensureDatabases = [ cfg.database.name ]; From d96a9d762b494a3fb55c905633788b1385611897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Sat, 11 Oct 2025 21:18:14 +0200 Subject: [PATCH 3/4] nixos/zammad: add zammad wrapper --- nixos/modules/services/development/zammad.nix | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/nixos/modules/services/development/zammad.nix b/nixos/modules/services/development/zammad.nix index d269f8773077..89875f07abca 100644 --- a/nixos/modules/services/development/zammad.nix +++ b/nixos/modules/services/development/zammad.nix @@ -218,6 +218,23 @@ in ]; config = lib.mkIf cfg.enable { + environment.systemPackages = [ + # we try to eumulate parts of the pkgr script that are relevant to NixOS + (pkgs.writeShellScriptBin "zammad" '' + if [[ ''${1:-} != run ]]; then + echo "This script only supports the run subcommand". + exit 1 + fi + shift + + prog="$1" + shift + sudo -u ${cfg.user} -- env ${ + lib.concatMapAttrsStringSep " " (n: v: "${n}=${v}") environment + } bash -c "cd ${cfg.package}; ${cfg.package}/bin/$prog $(printf " %q" "$@")" + '') + ]; + services.zammad.database.settings = { production = lib.mapAttrs (_: v: lib.mkDefault v) (filterNull { adapter = "postgresql"; From 4cf52fc3bf20b906c448b90f00fb56aa7d4b01cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Fri, 17 Oct 2025 00:53:57 +0200 Subject: [PATCH 4/4] zammad: fix using filesystem as attachment storage --- nixos/modules/services/development/zammad.nix | 5 +++-- pkgs/by-name/za/zammad/package.nix | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/nixos/modules/services/development/zammad.nix b/nixos/modules/services/development/zammad.nix index 89875f07abca..6b91626c07da 100644 --- a/nixos/modules/services/development/zammad.nix +++ b/nixos/modules/services/development/zammad.nix @@ -368,7 +368,7 @@ in # cleanup state directory from module before refactoring in # https://github.com/NixOS/nixpkgs/pull/277456 if [[ -e ${cfg.dataDir}/node_modules ]]; then - rm -rf ${cfg.dataDir}/!("tmp"|"config"|"log"|"state_dir_migrated"|"db_seeded") + rm -rf ${cfg.dataDir}/!("tmp"|"config"|"log"|"state_dir_migrated"|"db_seeded"|"storage") rm -rf ${cfg.dataDir}/config/!("database.yml"|"secrets.yml") # state directory cleanup required --> zammad was already installed --> do not seed db echo true > ${cfg.dataDir}/db_seeded @@ -392,8 +392,9 @@ in systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -" "d ${cfg.dataDir}/config 0750 ${cfg.user} ${cfg.group} - -" - "d ${cfg.dataDir}/tmp 0750 ${cfg.user} ${cfg.group} - -" "d ${cfg.dataDir}/log 0750 ${cfg.user} ${cfg.group} - -" + "d ${cfg.dataDir}/storage 0750 ${cfg.user} ${cfg.group} - -" + "d ${cfg.dataDir}/tmp 0750 ${cfg.user} ${cfg.group} - -" "f ${cfg.dataDir}/config/secrets.yml 0640 ${cfg.user} ${cfg.group} - -" "f ${cfg.dataDir}/config/database.yml 0640 ${cfg.user} ${cfg.group} - -" "f ${cfg.dataDir}/db_seeded 0640 ${cfg.user} ${cfg.group} - -" diff --git a/pkgs/by-name/za/zammad/package.nix b/pkgs/by-name/za/zammad/package.nix index 5ccf3bff026d..c38c37a4f85b 100644 --- a/pkgs/by-name/za/zammad/package.nix +++ b/pkgs/by-name/za/zammad/package.nix @@ -108,11 +108,12 @@ stdenvNoCC.mkDerivation { installPhase = '' cp -R . $out rm -rf $out/config/database.yml $out/config/secrets.yml $out/tmp $out/log - # dataDir will be set in the module, and the package gets overriden there + # dataDir will be set in the module, and the package gets overridden there ln -s ${dataDir}/config/database.yml $out/config/database.yml ln -s ${dataDir}/config/secrets.yml $out/config/secrets.yml - ln -s ${dataDir}/tmp $out/tmp ln -s ${dataDir}/log $out/log + ln -s ${dataDir}/storage $out/storage + ln -s ${dataDir}/tmp $out/tmp ''; passthru = {