From f41f218e0df5119c8c4e610185123bc1ded08233 Mon Sep 17 00:00:00 2001 From: netali Date: Fri, 29 Dec 2023 04:21:13 +0100 Subject: [PATCH] nixos/zammad: refactor module --- .../manual/release-notes/rl-2505.section.md | 2 + nixos/modules/services/development/zammad.nix | 127 +++++++++--------- 2 files changed, 63 insertions(+), 66 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 10645d55e838..07e72f6d5f46 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -30,6 +30,8 @@ - Support for CUDA 10 has been dropped, as announced in the 24.11 release notes. +- `zammad` has had its support for MySQL removed, since it was never working correctly and is now deprecated upstream. Check the [migration guide](https://docs.zammad.org/en/latest/appendix/migrate-to-postgresql.html) for how to convert your database to PostgreSQL. + - `kanata` was updated to v1.7.0, which introduces several breaking changes. See the release notes of [v1.7.0](https://github.com/jtroo/kanata/releases/tag/v1.7.0) diff --git a/nixos/modules/services/development/zammad.nix b/nixos/modules/services/development/zammad.nix index 43ae9a34b404..6e0be83aa384 100644 --- a/nixos/modules/services/development/zammad.nix +++ b/nixos/modules/services/development/zammad.nix @@ -1,4 +1,5 @@ { config, lib, pkgs, ... }: + let cfg = config.services.zammad; settingsFormat = pkgs.formats.yaml { }; @@ -7,11 +8,11 @@ let Type = "simple"; Restart = "always"; - User = "zammad"; - Group = "zammad"; + User = cfg.user; + Group = cfg.group; PrivateTmp = true; StateDirectory = "zammad"; - WorkingDirectory = cfg.dataDir; + WorkingDirectory = package; }; environment = { RAILS_ENV = "production"; @@ -21,6 +22,9 @@ let REDIS_URL = "redis://${cfg.redis.host}:${toString cfg.redis.port}"; }; databaseConfig = settingsFormat.generate "database.yml" cfg.database.settings; + package = cfg.package.override { + dataDir = cfg.dataDir; + }; in { @@ -30,6 +34,22 @@ in package = lib.mkPackageOption pkgs "zammad" { }; + user = lib.mkOption { + type = lib.types.str; + default = "zammad"; + description = '' + Name of the Zammad user. + ''; + }; + + group = lib.mkOption { + type = lib.types.str; + default = "zammad"; + description = '' + Name of the Zammad group. + ''; + }; + dataDir = lib.mkOption { type = lib.types.path; default = "/var/lib/zammad"; @@ -94,25 +114,9 @@ in }; database = { - type = lib.mkOption { - type = lib.types.enum [ "PostgreSQL" "MySQL" ]; - default = "PostgreSQL"; - example = "MySQL"; - description = "Database engine to use."; - }; - host = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = { - PostgreSQL = "/run/postgresql"; - MySQL = "localhost"; - }.${cfg.database.type}; - defaultText = lib.literalExpression '' - { - PostgreSQL = "/run/postgresql"; - MySQL = "localhost"; - }.''${config.services.zammad.database.type}; - ''; + type = lib.types.str; + default = "/run/postgresql"; description = '' Database host address. ''; @@ -195,13 +199,9 @@ in }; config = lib.mkIf cfg.enable { - services.zammad.database.settings = { production = lib.mapAttrs (_: v: lib.mkDefault v) (filterNull { - adapter = { - PostgreSQL = "postgresql"; - MySQL = "mysql2"; - }.${cfg.database.type}; + adapter = "postgresql"; database = cfg.database.name; pool = 50; timeout = 5000; @@ -217,13 +217,12 @@ in config.services.zammad.websocketPort ]; - users.users.zammad = { + users.users.${cfg.user} = { + group = "${cfg.group}"; isSystemUser = true; - home = cfg.dataDir; - group = "zammad"; }; - users.groups.zammad = { }; + users.groups.${cfg.group} = { }; assertions = [ { @@ -240,19 +239,7 @@ in } ]; - services.mysql = lib.optionalAttrs (cfg.database.createLocally && cfg.database.type == "MySQL") { - enable = true; - package = lib.mkDefault pkgs.mariadb; - ensureDatabases = [ cfg.database.name ]; - ensureUsers = [ - { - name = cfg.database.user; - ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; }; - } - ]; - }; - - services.postgresql = lib.optionalAttrs (cfg.database.createLocally && cfg.database.type == "PostgreSQL") { + services.postgresql = lib.optionalAttrs (cfg.database.createLocally) { enable = true; ensureDatabases = [ cfg.database.name ]; ensureUsers = [ @@ -278,54 +265,52 @@ in }; after = [ "network.target" + "systemd-tmpfiles-setup.service" + ] ++ lib.optionals (cfg.database.createLocally) [ "postgresql.service" ] ++ lib.optionals cfg.redis.createLocally [ "redis-${cfg.redis.name}.service" ]; - requires = [ + requires = lib.optionals (cfg.database.createLocally) [ "postgresql.service" ]; description = "Zammad web"; wantedBy = [ "multi-user.target" ]; preStart = '' - # Blindly copy the whole project here. - chmod -R +w . - rm -rf ./public/assets/ - rm -rf ./tmp/* - rm -rf ./log/* - cp -r --no-preserve=owner ${cfg.package}/* . - chmod -R +w . # config file - cp ${databaseConfig} ./config/database.yml - chmod -R +w . + cat ${databaseConfig} > ${cfg.dataDir}/config/database.yml ${lib.optionalString (cfg.database.passwordFile != null) '' { echo -n " password: " cat ${cfg.database.passwordFile} - } >> ./config/database.yml + } >> ${cfg.dataDir}/config/database.yml ''} ${lib.optionalString (cfg.secretKeyBaseFile != null) '' { echo "production: " echo -n " secret_key_base: " cat ${cfg.secretKeyBaseFile} - } > ./config/secrets.yml + } > ${cfg.dataDir}/config/secrets.yml ''} - if [ `${config.services.postgresql.package}/bin/psql \ - --host ${cfg.database.host} \ - ${lib.optionalString - (cfg.database.port != null) - "--port ${toString cfg.database.port}"} \ - --username ${cfg.database.user} \ - --dbname ${cfg.database.name} \ - --command "SELECT COUNT(*) FROM pg_class c \ - JOIN pg_namespace s ON s.oid = c.relnamespace \ - WHERE s.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema') \ - AND s.nspname NOT LIKE 'pg_temp%';" | sed -n 3p` -eq 0 ]; then + # needed for cleanup + shopt -s extglob + + # 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}/config/!("database.yml"|"secrets.yml") + # state directory cleanup required --> zammad was already installed --> do not seed db + echo true > ${cfg.dataDir}/db_seeded + fi + + SEEDED=$(cat ${cfg.dataDir}/db_seeded) + if [[ $SEEDED != "true" ]]; then echo "Initialize database" ./bin/rake --no-system db:migrate ./bin/rake --no-system db:seed + echo true > ${cfg.dataDir}/db_seeded else echo "Migrate database" ./bin/rake --no-system db:migrate @@ -335,6 +320,16 @@ in script = "./script/rails server -b ${cfg.host} -p ${toString cfg.port}"; }; + 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} - -" + "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} - -" + ]; + systemd.services.zammad-websocket = { inherit serviceConfig environment; after = [ "zammad-web.service" ];