nixos/zammad: remove openPorts option, add options to configure nginx, add zammad wrapper, fix filesystem storage (#451208)

This commit is contained in:
Sandro
2025-12-03 00:20:08 +00:00
committed by GitHub
2 changed files with 95 additions and 32 deletions
+92 -30
View File
@@ -32,7 +32,6 @@ let
};
in
{
options = {
services.zammad = {
enable = lib.mkEnableOption "Zammad, a web-based, open source user support/ticketing solution";
@@ -70,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;
@@ -177,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;
@@ -203,7 +209,32 @@ in
};
};
imports = [
(lib.mkRemovedOptionModule [
"services"
"zammad"
"openPorts"
] "The openPorts option was removed in favor of the nginx.configure option.")
];
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";
@@ -217,11 +248,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,21 +271,56 @@ 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 = {
nginx = lib.mkIf cfg.nginx.configure {
enable = true;
port = cfg.redis.port;
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 ];
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 +334,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";
@@ -307,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
@@ -331,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} - -"
+3 -2
View File
@@ -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 = {