diff --git a/lib/asserts.nix b/lib/asserts.nix index 8a5f1fb3feb7..9ae357cbc935 100644 --- a/lib/asserts.nix +++ b/lib/asserts.nix @@ -2,35 +2,33 @@ rec { - /* Print a trace message if pred is false. + /* Throw if pred is false, else return pred. Intended to be used to augment asserts with helpful error messages. Example: assertMsg false "nope" - => false - stderr> trace: nope + stderr> error: nope - assert (assertMsg ("foo" == "bar") "foo is not bar, silly"); "" - stderr> trace: foo is not bar, silly - stderr> assert failed at … + assert assertMsg ("foo" == "bar") "foo is not bar, silly"; "" + stderr> error: foo is not bar, silly Type: assertMsg :: Bool -> String -> Bool */ # TODO(Profpatsch): add tests that check stderr assertMsg = pred: msg: - if pred - then true - else builtins.trace msg false; + pred || builtins.throw msg; /* Specialized `assertMsg` for checking if val is one of the elements of a list. Useful for checking enums. Example: - let sslLibrary = "libressl" + let sslLibrary = "libressl"; in assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ] - => false - stderr> trace: sslLibrary must be one of "openssl", "bearssl", but is: "libressl" + stderr> error: sslLibrary must be one of [ + stderr> "openssl" + stderr> "bearssl" + stderr> ], but is: "libressl" Type: assertOneOf :: String -> ComparableVal -> List ComparableVal -> Bool diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index a696d017b312..12a308dfdffb 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -421,6 +421,18 @@ configuration. + + + lib.assertMsg and + lib.assertOneOf no longer return + false if the passed condition is + false, throwing the + given error message instead (which makes the resulting error + message less cluttered). This will not impact the behaviour of + code using these functions as intended, namely as top-level + wrapper for assert conditions. + +
@@ -564,6 +576,14 @@ renamed to linux-firmware. + + + The services.mbpfan module was converted to + a + RFC + 0042 configuration. + + A new module was added for the diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index 92e597ef674b..c816b062557f 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -53,6 +53,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [rstudio-server](https://www.rstudio.com/products/rstudio/#rstudio-server), a browser-based version of the RStudio IDE for the R programming language. Available as [services.rstudio-server](options.html#opt-services.rstudio-server.enable). + + ## Backward Incompatibilities {#sec-release-22.05-incompatibilities} - `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`. @@ -136,6 +138,10 @@ In addition to numerous new and upgraded packages, this release has the followin [settings-style](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration. +- `lib.assertMsg` and `lib.assertOneOf` no longer return `false` if the passed condition is `false`, `throw`ing the given error message instead (which makes the resulting error message less cluttered). This will not impact the behaviour of code using these functions as intended, namely as top-level wrapper for `assert` conditions. + + + ## Other Notable Changes {#sec-release-22.05-notable-changes} - The option [services.redis.servers](#opt-services.redis.servers) was added @@ -198,6 +204,8 @@ In addition to numerous new and upgraded packages, this release has the followin - The `firmwareLinuxNonfree` package has been renamed to `linux-firmware`. +- The `services.mbpfan` module was converted to a [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration. + - A new module was added for the [Starship](https://starship.rs/) shell prompt, providing the options `programs.starship.enable` and `programs.starship.settings`. @@ -211,3 +219,5 @@ In addition to numerous new and upgraded packages, this release has the followin - Renamed option `services.openssh.challengeResponseAuthentication` to `services.openssh.kbdInteractiveAuthentication`. Reason is that the old name has been deprecated upstream. Using the old option name will still work, but produce a warning. + + diff --git a/nixos/modules/programs/tsm-client.nix b/nixos/modules/programs/tsm-client.nix index 65d4db7834ff..28db96253875 100644 --- a/nixos/modules/programs/tsm-client.nix +++ b/nixos/modules/programs/tsm-client.nix @@ -7,7 +7,7 @@ let inherit (lib.modules) mkDefault mkIf; inherit (lib.options) literalExpression mkEnableOption mkOption; inherit (lib.strings) concatStringsSep optionalString toLower; - inherit (lib.types) addCheck attrsOf lines nullOr package path port str strMatching submodule; + inherit (lib.types) addCheck attrsOf lines nonEmptyStr nullOr package path port str strMatching submodule; # Checks if given list of strings contains unique # elements when compared without considering case. @@ -35,7 +35,7 @@ let ''; }; options.server = mkOption { - type = strMatching ".+"; + type = nonEmptyStr; example = "tsmserver.company.com"; description = '' Host/domain name or IP address of the IBM TSM server. @@ -56,7 +56,7 @@ let ''; }; options.node = mkOption { - type = strMatching ".+"; + type = nonEmptyStr; example = "MY-TSM-NODE"; description = '' Target node name on the IBM TSM server. @@ -144,7 +144,7 @@ let }; config.name = mkDefault name; # Client system-options file directives are explained here: - # https://www.ibm.com/support/knowledgecenter/SSEQVQ_8.1.8/client/c_opt_usingopts.html + # https://www.ibm.com/docs/en/spectrum-protect/8.1.13?topic=commands-processing-options config.extraConfig = mapAttrs (lib.trivial.const mkDefault) ( { diff --git a/nixos/modules/services/backup/tsm.nix b/nixos/modules/services/backup/tsm.nix index 6c238745797e..4e690ac6ecda 100644 --- a/nixos/modules/services/backup/tsm.nix +++ b/nixos/modules/services/backup/tsm.nix @@ -5,7 +5,7 @@ let inherit (lib.attrsets) hasAttr; inherit (lib.modules) mkDefault mkIf; inherit (lib.options) mkEnableOption mkOption; - inherit (lib.types) nullOr strMatching; + inherit (lib.types) nonEmptyStr nullOr; options.services.tsmBackup = { enable = mkEnableOption '' @@ -15,7 +15,7 @@ let ''; command = mkOption { - type = strMatching ".+"; + type = nonEmptyStr; default = "backup"; example = "incr"; description = '' @@ -24,7 +24,7 @@ let ''; }; servername = mkOption { - type = strMatching ".+"; + type = nonEmptyStr; example = "mainTsmServer"; description = '' Create a systemd system service @@ -41,7 +41,7 @@ let ''; }; autoTime = mkOption { - type = nullOr (strMatching ".+"); + type = nullOr nonEmptyStr; default = null; example = "12:00"; description = '' @@ -87,16 +87,35 @@ in environment.DSM_LOG = "/var/log/tsm-backup/"; # TSM needs a HOME dir to store certificates. environment.HOME = "/var/lib/tsm-backup"; - # for exit status description see - # https://www.ibm.com/support/knowledgecenter/en/SSEQVQ_8.1.8/client/c_sched_rtncode.html - serviceConfig.SuccessExitStatus = "4 8"; - # The `-se` option must come after the command. - # The `-optfile` option suppresses a `dsm.opt`-not-found warning. - serviceConfig.ExecStart = - "${cfgPrg.wrappedPackage}/bin/dsmc ${cfg.command} -se='${cfg.servername}' -optfile=/dev/null"; - serviceConfig.LogsDirectory = "tsm-backup"; - serviceConfig.StateDirectory = "tsm-backup"; - serviceConfig.StateDirectoryMode = "0750"; + serviceConfig = { + # for exit status description see + # https://www.ibm.com/docs/en/spectrum-protect/8.1.13?topic=clients-client-return-codes + SuccessExitStatus = "4 8"; + # The `-se` option must come after the command. + # The `-optfile` option suppresses a `dsm.opt`-not-found warning. + ExecStart = + "${cfgPrg.wrappedPackage}/bin/dsmc ${cfg.command} -se='${cfg.servername}' -optfile=/dev/null"; + LogsDirectory = "tsm-backup"; + StateDirectory = "tsm-backup"; + StateDirectoryMode = "0750"; + # systemd sandboxing + LockPersonality = true; + NoNewPrivileges = true; + PrivateDevices = true; + #PrivateTmp = true; # would break backup of {/var,}/tmp + #PrivateUsers = true; # would block backup of /home/* + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = "read-only"; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "noaccess"; + ProtectSystem = "strict"; + RestrictNamespaces = true; + RestrictSUIDSGID = true; + }; startAt = mkIf (cfg.autoTime!=null) cfg.autoTime; }; }; diff --git a/nixos/modules/services/misc/mbpfan.nix b/nixos/modules/services/misc/mbpfan.nix index d80b6fafc2cf..d2b0f0da2ad9 100644 --- a/nixos/modules/services/misc/mbpfan.nix +++ b/nixos/modules/services/misc/mbpfan.nix @@ -5,6 +5,8 @@ with lib; let cfg = config.services.mbpfan; verbose = if cfg.verbose then "v" else ""; + settingsFormat = pkgs.formats.ini {}; + settingsFile = settingsFormat.generate "config.conf" cfg.settings; in { options.services.mbpfan = { @@ -19,54 +21,6 @@ in { ''; }; - minFanSpeed = mkOption { - type = types.int; - default = 2000; - description = '' - The minimum fan speed. - ''; - }; - - maxFanSpeed = mkOption { - type = types.int; - default = 6200; - description = '' - The maximum fan speed. - ''; - }; - - lowTemp = mkOption { - type = types.int; - default = 63; - description = '' - The low temperature. - ''; - }; - - highTemp = mkOption { - type = types.int; - default = 66; - description = '' - The high temperature. - ''; - }; - - maxTemp = mkOption { - type = types.int; - default = 86; - description = '' - The maximum temperature. - ''; - }; - - pollingInterval = mkOption { - type = types.int; - default = 7; - description = '' - The polling interval. - ''; - }; - verbose = mkOption { type = types.bool; default = false; @@ -74,23 +28,61 @@ in { If true, sets the log level to verbose. ''; }; + + settings = mkOption { + default = {}; + description = "The INI configuration for Mbpfan."; + type = types.submodule { + freeformType = settingsFormat.type; + + options.general.min_fan1_speed = mkOption { + type = types.int; + default = 2000; + description = "The minimum fan speed."; + }; + options.general.max_fan1_speed = mkOption { + type = types.int; + default = 6199; + description = "The maximum fan speed."; + }; + options.general.low_temp = mkOption { + type = types.int; + default = 55; + description = "The low temperature."; + }; + options.general.high_temp = mkOption { + type = types.int; + default = 58; + description = "The high temperature."; + }; + options.general.max_temp = mkOption { + type = types.int; + default = 86; + description = "The maximum temperature."; + }; + options.general.polling_interval = mkOption { + type = types.int; + default = 1; + description = "The polling interval."; + }; + }; + }; }; + imports = [ + (mkRenamedOptionModule [ "services" "mbpfan" "pollingInterval" ] [ "services" "mbpfan" "settings" "general" "polling_interval" ]) + (mkRenamedOptionModule [ "services" "mbpfan" "maxTemp" ] [ "services" "mbpfan" "settings" "general" "max_temp" ]) + (mkRenamedOptionModule [ "services" "mbpfan" "lowTemp" ] [ "services" "mbpfan" "settings" "general" "low_temp" ]) + (mkRenamedOptionModule [ "services" "mbpfan" "highTemp" ] [ "services" "mbpfan" "settings" "general" "high_temp" ]) + (mkRenamedOptionModule [ "services" "mbpfan" "minFanSpeed" ] [ "services" "mbpfan" "settings" "general" "min_fan1_speed" ]) + (mkRenamedOptionModule [ "services" "mbpfan" "maxFanSpeed" ] [ "services" "mbpfan" "settings" "general" "max_fan1_speed" ]) + ]; + config = mkIf cfg.enable { boot.kernelModules = [ "coretemp" "applesmc" ]; - environment = { - etc."mbpfan.conf".text = '' - [general] - min_fan_speed = ${toString cfg.minFanSpeed} - max_fan_speed = ${toString cfg.maxFanSpeed} - low_temp = ${toString cfg.lowTemp} - high_temp = ${toString cfg.highTemp} - max_temp = ${toString cfg.maxTemp} - polling_interval = ${toString cfg.pollingInterval} - ''; - systemPackages = [ cfg.package ]; - }; + environment.etc."mbpfan.conf".source = settingsFile; + environment.systemPackages = [ cfg.package ]; systemd.services.mbpfan = { description = "A fan manager daemon for MacBook Pro"; diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix index aff4ed8dd608..a01f0049b2c7 100644 --- a/nixos/modules/services/web-apps/keycloak.nix +++ b/nixos/modules/services/web-apps/keycloak.nix @@ -3,299 +3,312 @@ let cfg = config.services.keycloak; opt = options.services.keycloak; + + inherit (lib) types mkOption concatStringsSep mapAttrsToList + escapeShellArg recursiveUpdate optionalAttrs boolToString mkOrder + sort filterAttrs concatMapStringsSep concatStrings mkIf + optionalString optionals mkDefault literalExpression hasSuffix + foldl' isAttrs filter attrNames elem literalDocBook + maintainers; + + inherit (builtins) match typeOf; in { - options.services.keycloak = { - - enable = lib.mkOption { - type = lib.types.bool; - default = false; - example = true; - description = '' - Whether to enable the Keycloak identity and access management - server. - ''; - }; - - bindAddress = lib.mkOption { - type = lib.types.str; - default = "\${jboss.bind.address:0.0.0.0}"; - example = "127.0.0.1"; - description = '' - On which address Keycloak should accept new connections. - - A special syntax can be used to allow command line Java system - properties to override the value: ''${property.name:value} - ''; - }; - - httpPort = lib.mkOption { - type = lib.types.str; - default = "\${jboss.http.port:80}"; - example = "8080"; - description = '' - On which port Keycloak should listen for new HTTP connections. - - A special syntax can be used to allow command line Java system - properties to override the value: ''${property.name:value} - ''; - }; - - httpsPort = lib.mkOption { - type = lib.types.str; - default = "\${jboss.https.port:443}"; - example = "8443"; - description = '' - On which port Keycloak should listen for new HTTPS connections. - - A special syntax can be used to allow command line Java system - properties to override the value: ''${property.name:value} - ''; - }; - - frontendUrl = lib.mkOption { - type = lib.types.str; - apply = x: - if x == "" || lib.hasSuffix "/" x then - x - else - x + "/"; - example = "keycloak.example.com/auth"; - description = '' - The public URL used as base for all frontend requests. Should - normally include a trailing /auth. - - See the - Hostname section of the Keycloak server installation - manual for more information. - ''; - }; - - forceBackendUrlToFrontendUrl = lib.mkOption { - type = lib.types.bool; - default = false; - example = true; - description = '' - Whether Keycloak should force all requests to go through the - frontend URL configured in . By default, - Keycloak allows backend requests to instead use its local - hostname or IP address and may also advertise it to clients - through its OpenID Connect Discovery endpoint. - - See the - Hostname section of the Keycloak server installation - manual for more information. - ''; - }; - - sslCertificate = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - example = "/run/keys/ssl_cert"; - description = '' - The path to a PEM formatted certificate to use for TLS/SSL - connections. - - This should be a string, not a Nix path, since Nix paths are - copied into the world-readable Nix store. - ''; - }; - - sslCertificateKey = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - example = "/run/keys/ssl_key"; - description = '' - The path to a PEM formatted private key to use for TLS/SSL - connections. - - This should be a string, not a Nix path, since Nix paths are - copied into the world-readable Nix store. - ''; - }; - - database = { - type = lib.mkOption { - type = lib.types.enum [ "mysql" "postgresql" ]; - default = "postgresql"; - example = "mysql"; + options.services.keycloak = + let + inherit (types) bool str nullOr attrsOf path enum anything + package port; + in + { + enable = mkOption { + type = bool; + default = false; + example = true; description = '' - The type of database Keycloak should connect to. + Whether to enable the Keycloak identity and access management + server. ''; }; - host = lib.mkOption { - type = lib.types.str; - default = "localhost"; + bindAddress = mkOption { + type = str; + default = "\${jboss.bind.address:0.0.0.0}"; + example = "127.0.0.1"; description = '' - Hostname of the database to connect to. + On which address Keycloak should accept new connections. + + A special syntax can be used to allow command line Java system + properties to override the value: ''${property.name:value} ''; }; - port = - let - dbPorts = { - postgresql = 5432; - mysql = 3306; - }; - in - lib.mkOption { - type = lib.types.port; - default = dbPorts.${cfg.database.type}; - defaultText = lib.literalDocBook "default port of selected database"; - description = '' - Port of the database to connect to. - ''; - }; - - useSSL = lib.mkOption { - type = lib.types.bool; - default = cfg.database.host != "localhost"; - defaultText = lib.literalExpression ''config.${opt.database.host} != "localhost"''; + httpPort = mkOption { + type = str; + default = "\${jboss.http.port:80}"; + example = "8080"; description = '' - Whether the database connection should be secured by SSL / - TLS. + On which port Keycloak should listen for new HTTP connections. + + A special syntax can be used to allow command line Java system + properties to override the value: ''${property.name:value} ''; }; - caCert = lib.mkOption { - type = lib.types.nullOr lib.types.path; + httpsPort = mkOption { + type = str; + default = "\${jboss.https.port:443}"; + example = "8443"; + description = '' + On which port Keycloak should listen for new HTTPS connections. + + A special syntax can be used to allow command line Java system + properties to override the value: ''${property.name:value} + ''; + }; + + frontendUrl = mkOption { + type = str; + apply = x: + if x == "" || hasSuffix "/" x then + x + else + x + "/"; + example = "keycloak.example.com/auth"; + description = '' + The public URL used as base for all frontend requests. Should + normally include a trailing /auth. + + See the + Hostname section of the Keycloak server installation + manual for more information. + ''; + }; + + forceBackendUrlToFrontendUrl = mkOption { + type = bool; + default = false; + example = true; + description = '' + Whether Keycloak should force all requests to go through the + frontend URL configured in . By default, + Keycloak allows backend requests to instead use its local + hostname or IP address and may also advertise it to clients + through its OpenID Connect Discovery endpoint. + + See the + Hostname section of the Keycloak server installation + manual for more information. + ''; + }; + + sslCertificate = mkOption { + type = nullOr path; default = null; + example = "/run/keys/ssl_cert"; description = '' - The SSL / TLS CA certificate that verifies the identity of the - database server. - - Required when PostgreSQL is used and SSL is turned on. - - For MySQL, if left at null, the default - Java keystore is used, which should suffice if the server - certificate is issued by an official CA. - ''; - }; - - createLocally = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Whether a database should be automatically created on the - local host. Set this to false if you plan on provisioning a - local database yourself. This has no effect if - services.keycloak.database.host is customized. - ''; - }; - - username = lib.mkOption { - type = lib.types.str; - default = "keycloak"; - description = '' - Username to use when connecting to an external or manually - provisioned database; has no effect when a local database is - automatically provisioned. - - To use this with a local database, set to - false and create the database and user - manually. The database should be called - keycloak. - ''; - }; - - passwordFile = lib.mkOption { - type = lib.types.path; - example = "/run/keys/db_password"; - description = '' - File containing the database password. + The path to a PEM formatted certificate to use for TLS/SSL + connections. This should be a string, not a Nix path, since Nix paths are copied into the world-readable Nix store. ''; }; - }; - package = lib.mkOption { - type = lib.types.package; - default = pkgs.keycloak; - defaultText = lib.literalExpression "pkgs.keycloak"; - description = '' - Keycloak package to use. - ''; - }; + sslCertificateKey = mkOption { + type = nullOr path; + default = null; + example = "/run/keys/ssl_key"; + description = '' + The path to a PEM formatted private key to use for TLS/SSL + connections. - initialAdminPassword = lib.mkOption { - type = lib.types.str; - default = "changeme"; - description = '' - Initial password set for the admin - user. The password is not stored safely and should be changed - immediately in the admin panel. - ''; - }; + This should be a string, not a Nix path, since Nix paths are + copied into the world-readable Nix store. + ''; + }; - themes = lib.mkOption { - type = lib.types.attrsOf lib.types.package; - default = {}; - description = '' - Additional theme packages for Keycloak. Each theme is linked into - subdirectory with a corresponding attribute name. + database = { + type = mkOption { + type = enum [ "mysql" "postgresql" ]; + default = "postgresql"; + example = "mysql"; + description = '' + The type of database Keycloak should connect to. + ''; + }; - Theme packages consist of several subdirectories which provide - different theme types: for example, account, - login etc. After adding a theme to this option you - can select it by its name in Keycloak administration console. - ''; - }; + host = mkOption { + type = str; + default = "localhost"; + description = '' + Hostname of the database to connect to. + ''; + }; - extraConfig = lib.mkOption { - type = lib.types.attrsOf lib.types.anything; - default = { }; - example = lib.literalExpression '' - { - "subsystem=keycloak-server" = { - "spi=hostname" = { - "provider=default" = null; - "provider=fixed" = { - enabled = true; - properties.hostname = "keycloak.example.com"; - }; - default-provider = "fixed"; + port = + let + dbPorts = { + postgresql = 5432; + mysql = 3306; }; + in + mkOption { + type = port; + default = dbPorts.${cfg.database.type}; + defaultText = literalDocBook "default port of selected database"; + description = '' + Port of the database to connect to. + ''; }; - } - ''; - description = '' - Additional Keycloak configuration options to set in - standalone.xml. - Options are expressed as a Nix attribute set which matches the - structure of the jboss-cli configuration. The configuration is - effectively overlayed on top of the default configuration - shipped with Keycloak. To remove existing nodes and undefine - attributes from the default configuration, set them to - null. + useSSL = mkOption { + type = bool; + default = cfg.database.host != "localhost"; + defaultText = literalExpression ''config.${opt.database.host} != "localhost"''; + description = '' + Whether the database connection should be secured by SSL / + TLS. + ''; + }; - The example configuration does the equivalent of the following - script, which removes the hostname provider - default, adds the deprecated hostname - provider fixed and defines it the default: + caCert = mkOption { + type = nullOr path; + default = null; + description = '' + The SSL / TLS CA certificate that verifies the identity of the + database server. - - /subsystem=keycloak-server/spi=hostname/provider=default:remove() - /subsystem=keycloak-server/spi=hostname/provider=fixed:add(enabled = true, properties = { hostname = "keycloak.example.com" }) - /subsystem=keycloak-server/spi=hostname:write-attribute(name=default-provider, value="fixed") - + Required when PostgreSQL is used and SSL is turned on. + + For MySQL, if left at null, the default + Java keystore is used, which should suffice if the server + certificate is issued by an official CA. + ''; + }; + + createLocally = mkOption { + type = bool; + default = true; + description = '' + Whether a database should be automatically created on the + local host. Set this to false if you plan on provisioning a + local database yourself. This has no effect if + services.keycloak.database.host is customized. + ''; + }; + + username = mkOption { + type = str; + default = "keycloak"; + description = '' + Username to use when connecting to an external or manually + provisioned database; has no effect when a local database is + automatically provisioned. + + To use this with a local database, set to + false and create the database and user + manually. The database should be called + keycloak. + ''; + }; + + passwordFile = mkOption { + type = path; + example = "/run/keys/db_password"; + description = '' + File containing the database password. + + This should be a string, not a Nix path, since Nix paths are + copied into the world-readable Nix store. + ''; + }; + }; + + package = mkOption { + type = package; + default = pkgs.keycloak; + defaultText = literalExpression "pkgs.keycloak"; + description = '' + Keycloak package to use. + ''; + }; + + initialAdminPassword = mkOption { + type = str; + default = "changeme"; + description = '' + Initial password set for the admin + user. The password is not stored safely and should be changed + immediately in the admin panel. + ''; + }; + + themes = mkOption { + type = attrsOf package; + default = { }; + description = '' + Additional theme packages for Keycloak. Each theme is linked into + subdirectory with a corresponding attribute name. + + Theme packages consist of several subdirectories which provide + different theme types: for example, account, + login etc. After adding a theme to this option you + can select it by its name in Keycloak administration console. + ''; + }; + + extraConfig = mkOption { + type = attrsOf anything; + default = { }; + example = literalExpression '' + { + "subsystem=keycloak-server" = { + "spi=hostname" = { + "provider=default" = null; + "provider=fixed" = { + enabled = true; + properties.hostname = "keycloak.example.com"; + }; + default-provider = "fixed"; + }; + }; + } + ''; + description = '' + Additional Keycloak configuration options to set in + standalone.xml. + + Options are expressed as a Nix attribute set which matches the + structure of the jboss-cli configuration. The configuration is + effectively overlayed on top of the default configuration + shipped with Keycloak. To remove existing nodes and undefine + attributes from the default configuration, set them to + null. + + The example configuration does the equivalent of the following + script, which removes the hostname provider + default, adds the deprecated hostname + provider fixed and defines it the default: + + + /subsystem=keycloak-server/spi=hostname/provider=default:remove() + /subsystem=keycloak-server/spi=hostname/provider=fixed:add(enabled = true, properties = { hostname = "keycloak.example.com" }) + /subsystem=keycloak-server/spi=hostname:write-attribute(name=default-provider, value="fixed") + + + You can discover available options by using the jboss-cli.sh + program and by referring to the Keycloak + Server Installation and Configuration Guide. + ''; + }; - You can discover available options by using the jboss-cli.sh - program and by referring to the Keycloak - Server Installation and Configuration Guide. - ''; }; - }; - config = let # We only want to create a database if we're actually going to connect to it. @@ -303,12 +316,12 @@ in createLocalPostgreSQL = databaseActuallyCreateLocally && cfg.database.type == "postgresql"; createLocalMySQL = databaseActuallyCreateLocally && cfg.database.type == "mysql"; - mySqlCaKeystore = pkgs.runCommand "mysql-ca-keystore" {} '' + mySqlCaKeystore = pkgs.runCommand "mysql-ca-keystore" { } '' ${pkgs.jre}/bin/keytool -importcert -trustcacerts -alias MySQLCACert -file ${cfg.database.caCert} -keystore $out -storepass notsosecretpassword -noprompt ''; # Both theme and theme type directories need to be actual directories in one hierarchy to pass Keycloak checks. - themesBundle = pkgs.runCommand "keycloak-themes" {} '' + themesBundle = pkgs.runCommand "keycloak-themes" { } '' linkTheme() { theme="$1" name="$2" @@ -332,28 +345,29 @@ in fi done - ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: theme: "linkTheme ${theme} ${lib.escapeShellArg name}") cfg.themes)} + ${concatStringsSep "\n" (mapAttrsToList (name: theme: "linkTheme ${theme} ${escapeShellArg name}") cfg.themes)} ''; - keycloakConfig' = builtins.foldl' lib.recursiveUpdate { - "interface=public".inet-address = cfg.bindAddress; - "socket-binding-group=standard-sockets"."socket-binding=http".port = cfg.httpPort; - "subsystem=keycloak-server" = { - "spi=hostname"."provider=default" = { - enabled = true; - properties = { - inherit (cfg) frontendUrl forceBackendUrlToFrontendUrl; + keycloakConfig' = foldl' recursiveUpdate + { + "interface=public".inet-address = cfg.bindAddress; + "socket-binding-group=standard-sockets"."socket-binding=http".port = cfg.httpPort; + "subsystem=keycloak-server" = { + "spi=hostname"."provider=default" = { + enabled = true; + properties = { + inherit (cfg) frontendUrl forceBackendUrlToFrontendUrl; + }; }; + "theme=defaults".dir = toString themesBundle; }; - "theme=defaults".dir = toString themesBundle; - }; - "subsystem=datasources"."data-source=KeycloakDS" = { - max-pool-size = "20"; - user-name = if databaseActuallyCreateLocally then "keycloak" else cfg.database.username; - password = "@db-password@"; - }; - } [ - (lib.optionalAttrs (cfg.database.type == "postgresql") { + "subsystem=datasources"."data-source=KeycloakDS" = { + max-pool-size = "20"; + user-name = if databaseActuallyCreateLocally then "keycloak" else cfg.database.username; + password = "@db-password@"; + }; + } [ + (optionalAttrs (cfg.database.type == "postgresql") { "subsystem=datasources" = { "jdbc-driver=postgresql" = { driver-module-name = "org.postgresql"; @@ -361,16 +375,16 @@ in driver-xa-datasource-class-name = "org.postgresql.xa.PGXADataSource"; }; "data-source=KeycloakDS" = { - connection-url = "jdbc:postgresql://${cfg.database.host}:${builtins.toString cfg.database.port}/keycloak"; + connection-url = "jdbc:postgresql://${cfg.database.host}:${toString cfg.database.port}/keycloak"; driver-name = "postgresql"; - "connection-properties=ssl".value = lib.boolToString cfg.database.useSSL; - } // (lib.optionalAttrs (cfg.database.caCert != null) { + "connection-properties=ssl".value = boolToString cfg.database.useSSL; + } // (optionalAttrs (cfg.database.caCert != null) { "connection-properties=sslrootcert".value = cfg.database.caCert; "connection-properties=sslmode".value = "verify-ca"; }); }; }) - (lib.optionalAttrs (cfg.database.type == "mysql") { + (optionalAttrs (cfg.database.type == "mysql") { "subsystem=datasources" = { "jdbc-driver=mysql" = { driver-module-name = "com.mysql"; @@ -378,38 +392,38 @@ in driver-class-name = "com.mysql.jdbc.Driver"; }; "data-source=KeycloakDS" = { - connection-url = "jdbc:mysql://${cfg.database.host}:${builtins.toString cfg.database.port}/keycloak"; + connection-url = "jdbc:mysql://${cfg.database.host}:${toString cfg.database.port}/keycloak"; driver-name = "mysql"; - "connection-properties=useSSL".value = lib.boolToString cfg.database.useSSL; - "connection-properties=requireSSL".value = lib.boolToString cfg.database.useSSL; - "connection-properties=verifyServerCertificate".value = lib.boolToString cfg.database.useSSL; + "connection-properties=useSSL".value = boolToString cfg.database.useSSL; + "connection-properties=requireSSL".value = boolToString cfg.database.useSSL; + "connection-properties=verifyServerCertificate".value = boolToString cfg.database.useSSL; "connection-properties=characterEncoding".value = "UTF-8"; valid-connection-checker-class-name = "org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"; validate-on-match = true; exception-sorter-class-name = "org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"; - } // (lib.optionalAttrs (cfg.database.caCert != null) { + } // (optionalAttrs (cfg.database.caCert != null) { "connection-properties=trustCertificateKeyStoreUrl".value = "file:${mySqlCaKeystore}"; "connection-properties=trustCertificateKeyStorePassword".value = "notsosecretpassword"; }); }; }) - (lib.optionalAttrs (cfg.sslCertificate != null && cfg.sslCertificateKey != null) { + (optionalAttrs (cfg.sslCertificate != null && cfg.sslCertificateKey != null) { "socket-binding-group=standard-sockets"."socket-binding=https".port = cfg.httpsPort; - "subsystem=elytron" = lib.mkOrder 900 { - "key-store=httpsKS" = lib.mkOrder 900 { + "subsystem=elytron" = mkOrder 900 { + "key-store=httpsKS" = mkOrder 900 { path = "/run/keycloak/ssl/certificate_private_key_bundle.p12"; credential-reference.clear-text = "notsosecretpassword"; type = "JKS"; }; - "key-manager=httpsKM" = lib.mkOrder 901 { + "key-manager=httpsKM" = mkOrder 901 { key-store = "httpsKS"; credential-reference.clear-text = "notsosecretpassword"; }; - "server-ssl-context=httpsSSC" = lib.mkOrder 902 { + "server-ssl-context=httpsSSC" = mkOrder 902 { key-manager = "httpsKM"; }; }; - "subsystem=undertow" = lib.mkOrder 901 { + "subsystem=undertow" = mkOrder 901 { "server=default-server"."https-listener=https".ssl-context = "httpsSSC"; }; }) @@ -500,41 +514,42 @@ in # with `expression` to evaluate. prefixExpression = string: let - matchResult = builtins.match ''"\$\{.*}"'' string; + matchResult = match ''"\$\{.*}"'' string; in - if matchResult != null then - "expression " + string - else - string; + if matchResult != null then + "expression " + string + else + string; writeAttribute = attribute: value: let - type = builtins.typeOf value; + type = typeOf value; in - if type == "set" then - let - names = builtins.attrNames value; - in - builtins.foldl' (text: name: text + (writeAttribute "${attribute}.${name}" value.${name})) "" names - else if value == null then '' - if (outcome == success) of ${path}:read-attribute(name="${attribute}") - ${path}:undefine-attribute(name="${attribute}") + if type == "set" then + let + names = attrNames value; + in + foldl' (text: name: text + (writeAttribute "${attribute}.${name}" value.${name})) "" names + else if value == null then '' + if (outcome == success) of ${path}:read-attribute(name="${attribute}") + ${path}:undefine-attribute(name="${attribute}") + end-if + '' + else if elem type [ "string" "path" "bool" ] then + let + value' = if type == "bool" then boolToString value else ''"${value}"''; + in + '' + if (result != ${prefixExpression value'}) of ${path}:read-attribute(name="${attribute}") + ${path}:write-attribute(name=${attribute}, value=${value'}) end-if '' - else if builtins.elem type [ "string" "path" "bool" ] then - let - value' = if type == "bool" then lib.boolToString value else ''"${value}"''; - in '' - if (result != ${prefixExpression value'}) of ${path}:read-attribute(name="${attribute}") - ${path}:write-attribute(name=${attribute}, value=${value'}) - end-if - '' - else throw "Unsupported type '${type}' for path '${path}'!"; + else throw "Unsupported type '${type}' for path '${path}'!"; in - lib.concatStrings - (lib.mapAttrsToList - (attribute: value: (writeAttribute attribute value)) - set); + concatStrings + (mapAttrsToList + (attribute: value: (writeAttribute attribute value)) + set); /* Produces an argument list for the JBoss `add()` function, @@ -557,19 +572,19 @@ in let makeArg = attribute: value: let - type = builtins.typeOf value; + type = typeOf value; in - if type == "set" then - "${attribute} = { " + (makeArgList value) + " }" - else if builtins.elem type [ "string" "path" "bool" ] then - "${attribute} = ${if type == "bool" then lib.boolToString value else ''"${value}"''}" - else if value == null then - "" - else - throw "Unsupported type '${type}' for attribute '${attribute}'!"; + if type == "set" then + "${attribute} = { " + (makeArgList value) + " }" + else if elem type [ "string" "path" "bool" ] then + "${attribute} = ${if type == "bool" then boolToString value else ''"${value}"''}" + else if value == null then + "" + else + throw "Unsupported type '${type}' for attribute '${attribute}'!"; in - lib.concatStringsSep ", " (lib.mapAttrsToList makeArg set); + concatStringsSep ", " (mapAttrsToList makeArg set); /* Recurses into the `nodeValue` attrset. Only subattrsets that @@ -579,7 +594,7 @@ in recurse = nodePath: nodeValue: let nodeContent = - if builtins.isAttrs nodeValue && nodeValue._type or "" == "order" then + if isAttrs nodeValue && nodeValue._type or "" == "order" then nodeValue.content else nodeValue; @@ -587,21 +602,23 @@ in let value = nodeContent.${name}; in - if (builtins.match ".*([=]).*" name) == [ "=" ] then - if builtins.isAttrs value || value == null then - true - else - throw "Parsing path '${lib.concatStringsSep "." (nodePath ++ [ name ])}' failed: JBoss attributes cannot contain '='!" + if (match ".*([=]).*" name) == [ "=" ] then + if isAttrs value || value == null then + true else - false; - jbossPath = "/" + lib.concatStringsSep "/" nodePath; - children = if !builtins.isAttrs nodeContent then {} else nodeContent; - subPaths = builtins.filter isPath (builtins.attrNames children); + throw "Parsing path '${concatStringsSep "." (nodePath ++ [ name ])}' failed: JBoss attributes cannot contain '='!" + else + false; + jbossPath = "/" + concatStringsSep "/" nodePath; + children = if !isAttrs nodeContent then { } else nodeContent; + subPaths = filter isPath (attrNames children); getPriority = name: - let value = children.${name}; - in if value._type or "" == "order" then value.priority else 1000; - orderedSubPaths = lib.sort (a: b: getPriority a < getPriority b) subPaths; - jbossAttrs = lib.filterAttrs (name: _: !(isPath name)) children; + let + value = children.${name}; + in + if value._type or "" == "order" then value.priority else 1000; + orderedSubPaths = sort (a: b: getPriority a < getPriority b) subPaths; + jbossAttrs = filterAttrs (name: _: !(isPath name)) children; text = if nodeContent != null then '' @@ -615,45 +632,48 @@ in ${jbossPath}:remove() end-if ''; - in text + lib.concatMapStringsSep "\n" (name: recurse (nodePath ++ [name]) children.${name}) orderedSubPaths; + in + text + concatMapStringsSep "\n" (name: recurse (nodePath ++ [ name ]) children.${name}) orderedSubPaths; in - recurse [] attrs; + recurse [ ] attrs; jbossCliScript = pkgs.writeText "jboss-cli-script" (mkJbossScript keycloakConfig'); - keycloakConfig = pkgs.runCommand "keycloak-config" { - nativeBuildInputs = [ cfg.package ]; - } '' - export JBOSS_BASE_DIR="$(pwd -P)"; - export JBOSS_MODULEPATH="${cfg.package}/modules"; - export JBOSS_LOG_DIR="$JBOSS_BASE_DIR/log"; + keycloakConfig = pkgs.runCommand "keycloak-config" + { + nativeBuildInputs = [ cfg.package ]; + } + '' + export JBOSS_BASE_DIR="$(pwd -P)"; + export JBOSS_MODULEPATH="${cfg.package}/modules"; + export JBOSS_LOG_DIR="$JBOSS_BASE_DIR/log"; - cp -r ${cfg.package}/standalone/configuration . - chmod -R u+rwX ./configuration + cp -r ${cfg.package}/standalone/configuration . + chmod -R u+rwX ./configuration - mkdir -p {deployments,ssl} + mkdir -p {deployments,ssl} - standalone.sh& + standalone.sh& - attempt=1 - max_attempts=30 - while ! jboss-cli.sh --connect ':read-attribute(name=server-state)'; do - if [[ "$attempt" == "$max_attempts" ]]; then - echo "ERROR: Could not connect to Keycloak after $attempt attempts! Failing.." >&2 - exit 1 - fi - echo "Keycloak not fully started yet, retrying.. ($attempt/$max_attempts)" - sleep 1 - (( attempt++ )) - done + attempt=1 + max_attempts=30 + while ! jboss-cli.sh --connect ':read-attribute(name=server-state)'; do + if [[ "$attempt" == "$max_attempts" ]]; then + echo "ERROR: Could not connect to Keycloak after $attempt attempts! Failing.." >&2 + exit 1 + fi + echo "Keycloak not fully started yet, retrying.. ($attempt/$max_attempts)" + sleep 1 + (( attempt++ )) + done - jboss-cli.sh --connect --file=${jbossCliScript} --echo-command + jboss-cli.sh --connect --file=${jbossCliScript} --echo-command - cp configuration/standalone.xml $out - ''; + cp configuration/standalone.xml $out + ''; in - lib.mkIf cfg.enable { - + mkIf cfg.enable + { assertions = [ { assertion = (cfg.database.useSSL && cfg.database.type == "postgresql") -> (cfg.database.caCert != null); @@ -663,7 +683,7 @@ in environment.systemPackages = [ cfg.package ]; - systemd.services.keycloakPostgreSQLInit = lib.mkIf createLocalPostgreSQL { + systemd.services.keycloakPostgreSQLInit = mkIf createLocalPostgreSQL { after = [ "postgresql.service" ]; before = [ "keycloak.service" ]; bindsTo = [ "postgresql.service" ]; @@ -687,7 +707,7 @@ in ''; }; - systemd.services.keycloakMySQLInit = lib.mkIf createLocalMySQL { + systemd.services.keycloakMySQLInit = mkIf createLocalMySQL { after = [ "mysql.service" ]; before = [ "keycloak.service" ]; bindsTo = [ "mysql.service" ]; @@ -714,13 +734,16 @@ in let databaseServices = if createLocalPostgreSQL then [ - "keycloakPostgreSQLInit.service" "postgresql.service" + "keycloakPostgreSQLInit.service" + "postgresql.service" ] else if createLocalMySQL then [ - "keycloakMySQLInit.service" "mysql.service" + "keycloakMySQLInit.service" + "mysql.service" ] else [ ]; - in { + in + { after = databaseServices; bindsTo = databaseServices; wantedBy = [ "multi-user.target" ]; @@ -735,52 +758,16 @@ in JBOSS_MODULEPATH = "${cfg.package}/modules"; }; serviceConfig = { - ExecStartPre = let - startPreFullPrivileges = '' - set -o errexit -o pipefail -o nounset -o errtrace - shopt -s inherit_errexit - - umask u=rwx,g=,o= - - install -T -m 0400 -o keycloak -g keycloak '${cfg.database.passwordFile}' /run/keycloak/secrets/db_password - '' + lib.optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' - install -T -m 0400 -o keycloak -g keycloak '${cfg.sslCertificate}' /run/keycloak/secrets/ssl_cert - install -T -m 0400 -o keycloak -g keycloak '${cfg.sslCertificateKey}' /run/keycloak/secrets/ssl_key - ''; - startPre = '' - set -o errexit -o pipefail -o nounset -o errtrace - shopt -s inherit_errexit - - umask u=rwx,g=,o= - - install -m 0600 ${cfg.package}/standalone/configuration/*.properties /run/keycloak/configuration - install -T -m 0600 ${keycloakConfig} /run/keycloak/configuration/standalone.xml - - replace-secret '@db-password@' '/run/keycloak/secrets/db_password' /run/keycloak/configuration/standalone.xml - - export JAVA_OPTS=-Djboss.server.config.user.dir=/run/keycloak/configuration - add-user-keycloak.sh -u admin -p '${cfg.initialAdminPassword}' - '' + lib.optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' - pushd /run/keycloak/ssl/ - cat /run/keycloak/secrets/ssl_cert <(echo) \ - /run/keycloak/secrets/ssl_key <(echo) \ - /etc/ssl/certs/ca-certificates.crt \ - > allcerts.pem - openssl pkcs12 -export -in /run/keycloak/secrets/ssl_cert -inkey /run/keycloak/secrets/ssl_key -chain \ - -name "${cfg.frontendUrl}" -out certificate_private_key_bundle.p12 \ - -CAfile allcerts.pem -passout pass:notsosecretpassword - popd - ''; - in [ - "+${pkgs.writeShellScript "keycloak-start-pre-full-privileges" startPreFullPrivileges}" - "${pkgs.writeShellScript "keycloak-start-pre" startPre}" + LoadCredential = [ + "db_password:${cfg.database.passwordFile}" + ] ++ optionals (cfg.sslCertificate != null && cfg.sslCertificateKey != null) [ + "ssl_cert:${cfg.sslCertificate}" + "ssl_key:${cfg.sslCertificateKey}" ]; - ExecStart = "${cfg.package}/bin/standalone.sh"; User = "keycloak"; Group = "keycloak"; DynamicUser = true; RuntimeDirectory = map (p: "keycloak/" + p) [ - "secrets" "configuration" "deployments" "data" @@ -792,13 +779,39 @@ in LogsDirectory = "keycloak"; AmbientCapabilities = "CAP_NET_BIND_SERVICE"; }; + script = '' + set -o errexit -o pipefail -o nounset -o errtrace + shopt -s inherit_errexit + + umask u=rwx,g=,o= + + install -m 0600 ${cfg.package}/standalone/configuration/*.properties /run/keycloak/configuration + install -T -m 0600 ${keycloakConfig} /run/keycloak/configuration/standalone.xml + + replace-secret '@db-password@' "$CREDENTIALS_DIRECTORY/db_password" /run/keycloak/configuration/standalone.xml + + export JAVA_OPTS=-Djboss.server.config.user.dir=/run/keycloak/configuration + add-user-keycloak.sh -u admin -p '${cfg.initialAdminPassword}' + '' + optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' + pushd /run/keycloak/ssl/ + cat "$CREDENTIALS_DIRECTORY/ssl_cert" <(echo) \ + "$CREDENTIALS_DIRECTORY/ssl_key" <(echo) \ + /etc/ssl/certs/ca-certificates.crt \ + > allcerts.pem + openssl pkcs12 -export -in "$CREDENTIALS_DIRECTORY/ssl_cert" -inkey "$CREDENTIALS_DIRECTORY/ssl_key" -chain \ + -name "${cfg.frontendUrl}" -out certificate_private_key_bundle.p12 \ + -CAfile allcerts.pem -passout pass:notsosecretpassword + popd + '' + '' + ${cfg.package}/bin/standalone.sh + ''; }; - services.postgresql.enable = lib.mkDefault createLocalPostgreSQL; - services.mysql.enable = lib.mkDefault createLocalMySQL; - services.mysql.package = lib.mkIf createLocalMySQL pkgs.mariadb; + services.postgresql.enable = mkDefault createLocalPostgreSQL; + services.mysql.enable = mkDefault createLocalMySQL; + services.mysql.package = mkIf createLocalMySQL pkgs.mariadb; }; meta.doc = ./keycloak.xml; - meta.maintainers = [ lib.maintainers.talyz ]; + meta.maintainers = [ maintainers.talyz ]; } diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 2bc34d6fd786..bbf6de7b6cfd 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -490,6 +490,7 @@ in trezord = handleTest ./trezord.nix {}; trickster = handleTest ./trickster.nix {}; trilium-server = handleTestOn ["x86_64-linux"] ./trilium-server.nix {}; + tsm-client-gui = handleTest ./tsm-client-gui.nix {}; txredisapi = handleTest ./txredisapi.nix {}; tuptime = handleTest ./tuptime.nix {}; turbovnc-headless-server = handleTest ./turbovnc-headless-server.nix {}; diff --git a/nixos/tests/tsm-client-gui.nix b/nixos/tests/tsm-client-gui.nix new file mode 100644 index 000000000000..e4bcd344a895 --- /dev/null +++ b/nixos/tests/tsm-client-gui.nix @@ -0,0 +1,57 @@ +# The tsm-client GUI first tries to connect to a server. +# We can't simulate a server, so we just check if +# it reports the correct connection failure error. +# After that the test persuades the GUI +# to show its main application window +# and verifies some configuration information. + +import ./make-test-python.nix ({ lib, pkgs, ... }: { + name = "tsm-client"; + + enableOCR = true; + + machine = { pkgs, ... }: { + imports = [ ./common/x11.nix ]; + programs.tsmClient = { + enable = true; + package = pkgs.tsm-client-withGui; + defaultServername = "testserver"; + servers.testserver = { + # 192.0.0.8 is a "dummy address" according to RFC 7600 + server = "192.0.0.8"; + node = "SOME-NODE"; + passwdDir = "/tmp"; + }; + }; + }; + + testScript = '' + machine.succeed("which dsmj") # fail early if this is missing + machine.wait_for_x() + machine.execute("DSM_LOG=/tmp dsmj -optfile=/dev/null >&2 &") + + # does it report the "TCP/IP connection failure" error code? + machine.wait_for_window("IBM Spectrum Protect") + machine.wait_for_text("ANS2610S") + machine.send_key("esc") + + # it asks to continue to restore a local backupset now; + # "yes" (return) leads to the main application window + machine.wait_for_text("backupset") + machine.send_key("ret") + + # main window: navigate to "Connection Information" + machine.wait_for_text("Welcome") + machine.send_key("alt-f") # "File" menu + machine.send_key("c") # "Connection Information" + + # "Connection Information" dialog box + machine.wait_for_window("Connection Information") + machine.wait_for_text("SOME-NODE") + machine.wait_for_text("${pkgs.tsm-client.passthru.unwrapped.version}") + + machine.shutdown() + ''; + + meta.maintainers = [ lib.maintainers.yarny ]; +}) diff --git a/pkgs/applications/audio/bespokesynth/default.nix b/pkgs/applications/audio/bespokesynth/default.nix index e8d2ada38783..a5ef585969e6 100644 --- a/pkgs/applications/audio/bespokesynth/default.nix +++ b/pkgs/applications/audio/bespokesynth/default.nix @@ -1,40 +1,46 @@ -{ lib, stdenv, fetchFromGitHub, pkg-config, fetchzip -, libjack2, alsa-lib, freetype, libX11, libXrandr, libXinerama, libXext, libXcursor -, libGL, python3, ncurses, libusb1 -, gtk3, webkitgtk, curl, xvfb-run, makeWrapper - # "Debug", or "Release" -, buildType ? "Release" +{ lib +, stdenv +, fetchFromGitHub +, fetchzip +, cmake +, pkg-config +, ninja +, makeWrapper +, libjack2 +, alsa-lib +, alsa-tools +, freetype +, libusb1 +, libX11 +, libXrandr +, libXinerama +, libXext +, libXcursor +, libXScrnSaver +, libGL +, libxcb +, xcbutil +, libxkbcommon +, xcbutilkeysyms +, xcb-util-cursor +, gtk3 +, webkitgtk +, python3 +, curl +, pcre +, mount +, gnome +, Cocoa +, WebKit +, CoreServices +, CoreAudioKit + # It is not allowed to distribute binaries with the VST2 SDK plugin without a license + # (the author of Bespoke has such a licence but not Nix). VST3 should work out of the box. + # Read more in https://github.com/NixOS/nixpkgs/issues/145607 +, enableVST2 ? false }: let - projucer = stdenv.mkDerivation rec { - pname = "projucer"; - version = "5.4.7"; - - src = fetchFromGitHub { - owner = "juce-framework"; - repo = "JUCE"; - rev = version; - sha256= "0qpiqfwwpcghk7ij6w4vy9ywr3ryg7ppg77bmd7783kxg6zbhj8h"; - }; - - nativeBuildInputs = [ pkg-config ]; - buildInputs = [ - freetype libX11 libXrandr libXinerama libXext gtk3 webkitgtk - libjack2 curl - ]; - preBuild = '' - cd extras/Projucer/Builds/LinuxMakefile - ''; - makeFlags = [ "CONFIG=${buildType}" ]; - enableParallelBuilding = true; - - installPhase = '' - mkdir -p $out/bin - cp -a build/Projucer $out/bin/Projucer - ''; - }; - # equal to vst-sdk in ../oxefmsynth/default.nix vst-sdk = stdenv.mkDerivation rec { name = "vstsdk3610_11_06_2018_build_37"; @@ -50,70 +56,92 @@ let in stdenv.mkDerivation rec { pname = "bespokesynth"; - version = "1.0.0"; + version = "1.1.0"; src = fetchFromGitHub { - owner = "awwbees"; + owner = "BespokeSynth"; repo = pname; rev = "v${version}"; - sha256 = "04b2m40jszphslkd4850jcb8qwls392lwy3lc6vlj01h4izvapqk"; + sha256 = "sha256-PN0Q6/gI1PeMaF/8EZFGJdLR8JVHQZfWunAhOIQxkHw="; + fetchSubmodules = true; }; - configurePhase = '' - runHook preConfigure + cmakeBuildType = "Release"; - export HOME=$(mktemp -d) - xvfb-run sh -e < + #include ++#include + #include "util/list.h" + #include "util/rwlock.h" + #include "ac_gpu_info.h" +diff --git a/src/gallium/drivers/freedreno/freedreno_util.h b/src/gallium/drivers/freedreno/freedreno_util.h +index 22f99c41909..2f3195926be 100644 +--- a/src/gallium/drivers/freedreno/freedreno_util.h ++++ b/src/gallium/drivers/freedreno/freedreno_util.h +@@ -108,6 +108,8 @@ extern bool fd_binning_enabled; + #include + #include + ++#define gettid() ((pid_t)syscall(SYS_gettid)) ++ + #define DBG(fmt, ...) \ + do { \ + if (FD_DBG(MSGS)) \ +diff --git a/src/gallium/frontends/nine/nine_debug.c b/src/gallium/frontends/nine/nine_debug.c +index f3a6a945025..f4a6c41a612 100644 +--- a/src/gallium/frontends/nine/nine_debug.c ++++ b/src/gallium/frontends/nine/nine_debug.c +@@ -65,7 +65,7 @@ _nine_debug_printf( unsigned long flag, + { + static boolean first = TRUE; + static unsigned long dbg_flags = DBG_ERROR | DBG_WARN; +- unsigned long tid = 0; ++ pthread_t tid = 0; + + if (first) { + first = FALSE; +@@ -74,7 +74,7 @@ _nine_debug_printf( unsigned long flag, + + #if defined(HAVE_PTHREAD) + if (dbg_flags & DBG_TID) +- tid = (unsigned long)pthread_self(); ++ tid = pthread_self(); + #endif + + if (dbg_flags & flag) { +diff --git a/src/util/rand_xor.c b/src/util/rand_xor.c +index 81b64f1ea71..56ebd2eccdf 100644 +--- a/src/util/rand_xor.c ++++ b/src/util/rand_xor.c +@@ -28,6 +28,7 @@ + #if defined(HAVE_GETRANDOM) + #include + #endif ++#include /* size_t, ssize_t */ + #include + #include + #endif diff --git a/pkgs/development/python-modules/flask-gravatar/default.nix b/pkgs/development/python-modules/flask-gravatar/default.nix new file mode 100644 index 000000000000..c0bbf7d01467 --- /dev/null +++ b/pkgs/development/python-modules/flask-gravatar/default.nix @@ -0,0 +1,47 @@ +{ lib +, buildPythonPackage +, fetchPypi +, flask +, pytestCheckHook +, pygments +}: + +buildPythonPackage rec { + pname = "flask-gravatar"; + version = "0.5.0"; + + src = fetchPypi { + pname = "Flask-Gravatar"; + inherit version; + sha256 = "YGZfMcLGEokdto/4Aek+06CIHGyOw0arxk0qmSP1YuE="; + }; + + postPatch = '' + sed -i setup.py \ + -e "s|tests_require=tests_require,||g" \ + -e "s|extras_require=extras_require,||g" \ + -e "s|setup_requires=setup_requires,||g" + # pep8 is deprecated and cov not needed + substituteInPlace pytest.ini \ + --replace "--pep8" "" \ + --replace "--cov=flask_gravatar --cov-report=term-missing" "" + ''; + + propagatedBuildInputs = [ + flask + ]; + + checkInputs = [ + pytestCheckHook + pygments + ]; + + pythonImportsCheck = [ "flask_gravatar" ]; + + meta = with lib; { + homepage = "https://github.com/zzzsochi/Flask-Gravatar"; + description = "Small and simple integration of gravatar into flask"; + license = licenses.bsd3; + maintainers = with maintainers; [ gador ]; + }; +} diff --git a/pkgs/development/python-modules/flask-paranoid/default.nix b/pkgs/development/python-modules/flask-paranoid/default.nix new file mode 100644 index 000000000000..787b34a93b37 --- /dev/null +++ b/pkgs/development/python-modules/flask-paranoid/default.nix @@ -0,0 +1,40 @@ +{ lib +, buildPythonPackage +, fetchFromGitHub +, flask +, pytestCheckHook +}: + +buildPythonPackage rec { + pname = "flask-paranoid"; + version = "0.2"; + + src = fetchFromGitHub { + owner = "miguelgrinberg"; + repo = pname; + rev = "v${version}"; + sha256 = "0WWc/ktAOuTk4A75xI1jCj/aef2+1TjLKBA9+PRfJO0="; + }; + + postPatch = '' + # tests have a typo in one of the assertions + substituteInPlace tests/test_paranoid.py --replace "01-Jan-1970" "01 Jan 1970" + ''; + + propagatedBuildInputs = [ + flask + ]; + + checkInputs = [ + pytestCheckHook + ]; + + pythonImportsCheck = [ "flask_paranoid" ]; + + meta = with lib; { + homepage = "https://github.com/miguelgrinberg/flask-paranoid/"; + description = "Simple user session protection"; + license = licenses.mit; + maintainers = with maintainers; [ gador ]; + }; +} diff --git a/pkgs/development/python-modules/flask-security-too/default.nix b/pkgs/development/python-modules/flask-security-too/default.nix new file mode 100644 index 000000000000..ddf5aa05c493 --- /dev/null +++ b/pkgs/development/python-modules/flask-security-too/default.nix @@ -0,0 +1,76 @@ +{ lib +, buildPythonPackage +, fetchPypi +, flask +, blinker +, setuptools +, itsdangerous +, flask_principal +, passlib +, email_validator +, flask_wtf +, flask_login +, pytestCheckHook +, flask_mail +, sqlalchemy +, flask_sqlalchemy +, flask-mongoengine +, peewee +, pony +, zxcvbn +, mongoengine +, cryptography +, pyqrcode +, phonenumbers +, bleach +, mongomock +}: + +buildPythonPackage rec { + pname = "flask-security-too"; + version = "4.1.2"; + + src = fetchPypi { + pname = "Flask-Security-Too"; + inherit version; + sha256 = "16ws5n08vm7wsa2f7lrkxvc7jl3ah1xfylhhyzb4vvqmlk7x9hw8"; + }; + + propagatedBuildInputs = [ + flask + flask_login + flask_principal + flask_wtf + email_validator + itsdangerous + passlib + blinker + setuptools + ]; + + checkInputs = [ + pytestCheckHook + flask_mail + sqlalchemy + flask_sqlalchemy + flask-mongoengine + peewee + pony + zxcvbn + mongoengine + cryptography + pyqrcode + phonenumbers + bleach + mongomock + ]; + + pythonImportsCheck = [ "flask_security" ]; + + meta = with lib; { + homepage = "https://pypi.org/project/Flask-Security-Too/"; + description = "Simple security for Flask apps (fork)"; + license = licenses.mit; + maintainers = with maintainers; [ gador ]; + }; +} diff --git a/pkgs/development/python-modules/httpagentparser/default.nix b/pkgs/development/python-modules/httpagentparser/default.nix new file mode 100644 index 000000000000..e0c9dd09bcba --- /dev/null +++ b/pkgs/development/python-modules/httpagentparser/default.nix @@ -0,0 +1,26 @@ +{ lib +, buildPythonPackage +, fetchPypi +}: + +buildPythonPackage rec { + pname = "httpagentparser"; + version = "1.9.1"; + + src = fetchPypi { + inherit pname version; + sha256 = "73Y9MZk912GCWs7myLNL4yuVzxZ10cc8PNNfnlKDGyY="; + }; + + # PyPi version does not include test directory + doCheck = false; + + pythonImportsCheck = [ "httpagentparser" ]; + + meta = with lib; { + homepage = "https://github.com/shon/httpagentparser"; + description = "Extracts OS Browser etc information from http user agent string"; + license = licenses.mit; + maintainers = with maintainers; [ gador ]; + }; +} diff --git a/pkgs/development/python-modules/matrix-common/default.nix b/pkgs/development/python-modules/matrix-common/default.nix new file mode 100644 index 000000000000..44d37b988a7d --- /dev/null +++ b/pkgs/development/python-modules/matrix-common/default.nix @@ -0,0 +1,27 @@ +{ stdenv +, lib +, buildPythonPackage +, fetchPypi +, attrs +}: + +buildPythonPackage rec { + pname = "matrix_common"; + version = "1.0.0"; + format = "pyproject"; + + src = fetchPypi { + inherit pname version; + sha256 = "sha256-ZmiKRoJ8hv1USuJBDzV2U1uIFt2lRxmT+iAOqOShJK4="; + }; + + propagatedBuildInputs = [ attrs ]; + pythonImportsCheck = [ "matrix_common" ]; + + meta = with lib; { + description = "Common utilities for Synapse, Sydent and Sygnal"; + homepage = "https://github.com/matrix-org/matrix-python-common"; + license = licenses.asl20; + maintainers = with maintainers; [ sumnerevans ]; + }; +} diff --git a/pkgs/development/python-modules/mongomock/default.nix b/pkgs/development/python-modules/mongomock/default.nix new file mode 100644 index 000000000000..0f2f305c97c3 --- /dev/null +++ b/pkgs/development/python-modules/mongomock/default.nix @@ -0,0 +1,40 @@ +{ lib +, buildPythonPackage +, fetchPypi +, pbr +, sentinels +, six +, pytestCheckHook +}: + +buildPythonPackage rec { + pname = "mongomock"; + version = "3.23.0"; + + src = fetchPypi { + inherit pname version; + sha256 = "1pdh4pj5n6dsaqy98q40wig5y6imfs1p043cgkaaw8f2hxy5x56r"; + }; + + nativeBuildInputs = [ + pbr + ]; + + propagatedBuildInputs = [ + sentinels + six + ]; + + checkInputs = [ + pytestCheckHook + ]; + + pythonImportsCheck = [ "mongomock" ]; + + meta = with lib; { + homepage = "https://github.com/mongomock/mongomock"; + description = "Fake pymongo stub for testing simple MongoDB-dependent code"; + license = licenses.bsd3; + maintainers = with maintainers; [ gador ]; + }; +} diff --git a/pkgs/development/python-modules/sentinels/default.nix b/pkgs/development/python-modules/sentinels/default.nix new file mode 100644 index 000000000000..17c2c94a30ff --- /dev/null +++ b/pkgs/development/python-modules/sentinels/default.nix @@ -0,0 +1,36 @@ +{ lib +, buildPythonPackage +, pythonOlder +, fetchPypi +, setuptools +, pytestCheckHook +}: + +buildPythonPackage rec { + pname = "sentinels"; + version = "1.0.0"; + + disabled = pythonOlder "3.5"; + + src = fetchPypi { + inherit pname version; + sha256 = "1cglkxph47pki4db4kjx5g4ikxp2milqdlcjgqwmx4p1gx6p1q3v"; + }; + + propagatedBuildInputs = [ + setuptools + ]; + + checkInputs = [ + pytestCheckHook + ]; + + pythonImportsCheck = [ "sentinels" ]; + + meta = with lib; { + homepage = "https://github.com/vmalloc/sentinels/"; + description = "Various objects to denote special meanings in python"; + license = licenses.bsd3; + maintainers = with maintainers; [ gador ]; + }; +} diff --git a/pkgs/development/python-modules/speaklater3/default.nix b/pkgs/development/python-modules/speaklater3/default.nix new file mode 100644 index 000000000000..60c4c99fd3a2 --- /dev/null +++ b/pkgs/development/python-modules/speaklater3/default.nix @@ -0,0 +1,23 @@ +{ lib +, buildPythonPackage +, fetchPypi +}: + +buildPythonPackage rec { + pname = "speaklater3"; + version = "1.4"; + + src = fetchPypi { + inherit pname version; + sha256 = "ySYdS2taMEZyMS0esImb4Cj6yRdgGQqA/szTHTo7UEI="; + }; + + pythonImportsCheck = [ "speaklater" ]; + + meta = with lib; { + description = "Implements a lazy string for python useful for use with gettext"; + homepage = "https://github.com/mitsuhiko/speaklater"; + license = licenses.bsd0; + maintainers = with maintainers; [ gador ]; + }; +} diff --git a/pkgs/development/tools/analysis/checkov/default.nix b/pkgs/development/tools/analysis/checkov/default.nix index 3ddde0c282f9..1a4b29671875 100644 --- a/pkgs/development/tools/analysis/checkov/default.nix +++ b/pkgs/development/tools/analysis/checkov/default.nix @@ -22,13 +22,13 @@ with py.pkgs; buildPythonApplication rec { pname = "checkov"; - version = "2.0.712"; + version = "2.0.727"; src = fetchFromGitHub { owner = "bridgecrewio"; repo = pname; rev = version; - hash = "sha256-iUplSd4/OcJtfby2bn7b6GwCbXnBMqUSuLjkkh+7W9Y="; + hash = "sha256-hegbkmM8ZN6zO2iANGRr2QRW3ErdtwYaTo618uELev0="; }; nativeBuildInputs = with py.pkgs; [ @@ -81,6 +81,7 @@ buildPythonApplication rec { postPatch = '' substituteInPlace setup.py \ + --replace "cyclonedx-python-lib>=0.11.0,<1.0.0" "cyclonedx-python-lib>=0.11.0" \ --replace "jsonschema==3.0.2" "jsonschema>=3.0.2" ''; diff --git a/pkgs/development/tools/analysis/rizin/cutter.nix b/pkgs/development/tools/analysis/rizin/cutter.nix index 698f9e8231d0..a6ac4fbce12f 100644 --- a/pkgs/development/tools/analysis/rizin/cutter.nix +++ b/pkgs/development/tools/analysis/rizin/cutter.nix @@ -11,13 +11,13 @@ mkDerivation rec { pname = "cutter"; - version = "2.0.4"; + version = "2.0.5"; src = fetchFromGitHub { owner = "rizinorg"; repo = "cutter"; rev = "v${version}"; - sha256 = "sha256-Z5mqLkeA7AZnvKdpdRzaYfNMsGUI7i7wPTXVyIRYwxI="; + sha256 = "sha256-ljws9S7ZxZK/Ou8jgGSoR++vtzFTEBywHMhCC/UOLEs="; fetchSubmodules = true; }; diff --git a/pkgs/development/tools/analysis/rizin/default.nix b/pkgs/development/tools/analysis/rizin/default.nix index c316ef970f88..c4cdf85a7d8a 100644 --- a/pkgs/development/tools/analysis/rizin/default.nix +++ b/pkgs/development/tools/analysis/rizin/default.nix @@ -23,11 +23,11 @@ stdenv.mkDerivation rec { pname = "rizin"; - version = "0.3.2"; + version = "0.3.4"; src = fetchurl { url = "https://github.com/rizinorg/rizin/releases/download/v${version}/rizin-src-v${version}.tar.xz"; - sha256 = "sha256-T65gm1tfRD7dZSL8qZKMTAbQ65Lx/ecidFc9T1b7cig="; + sha256 = "sha256-7qSbOWOHwJ0ZcFqrAqYXzbFWgvymfxAf8rJ+75SnEOk="; }; mesonFlags = [ diff --git a/pkgs/games/tlauncher/default.nix b/pkgs/games/tlauncher/default.nix deleted file mode 100644 index 48cfac1f582c..000000000000 --- a/pkgs/games/tlauncher/default.nix +++ /dev/null @@ -1,100 +0,0 @@ -{ lib -, stdenv -, openjdk8 -, buildFHSUserEnv -, fetchzip -, fetchurl -, copyDesktopItems -, makeDesktopItem -}: -let - version = "2.839"; - src = stdenv.mkDerivation { - pname = "tlauncher"; - inherit version; - src = fetchzip { - name = "tlauncher.zip"; - url = "https://dl2.tlauncher.org/f.php?f=files%2FTLauncher-${version}.zip"; - sha256 = "sha256-KphpNuTucpuJhXspKxqDyYQN6vbpY0XCB3GAd5YCGbc="; - stripRoot = false; - }; - installPhase = '' - cp $src/*.jar $out - ''; - }; - fhs = buildFHSUserEnv { - name = "tlauncher"; - runScript = '' - ${openjdk8}/bin/java -jar "${src}" "$@" - ''; - targetPkgs = pkgs: with pkgs; [ - alsa-lib - cpio - cups - file - fontconfig - freetype - giflib - glib - gnome2.GConf - gnome2.gnome_vfs - gtk2 - libjpeg - libGL - openjdk8-bootstrap - perl - which - xorg.libICE - xorg.libX11 - xorg.libXcursor - xorg.libXext - xorg.libXi - xorg.libXinerama - xorg.libXrandr - xorg.xrandr - xorg.libXrender - xorg.libXt - xorg.libXtst - xorg.libXtst - xorg.libXxf86vm - zip - zlib - ]; - }; - desktopItem = makeDesktopItem { - name = "tlauncher"; - exec = "tlauncher"; - icon = fetchurl { - url = "https://styles.redditmedia.com/t5_2o8oax/styles/communityIcon_gu5r5v8eaiq51.png"; - sha256 = "sha256-ma8zxaUxdAw5VYfOK8i8s1kjwMgs80Eomq43Cb0HZWw="; - }; - comment = "Minecraft launcher"; - desktopName = "TLauncher"; - categories = "Game;"; - }; -in stdenv.mkDerivation { - pname = "tlauncher-wrapper"; - inherit version; - - dontUnpack = true; - - installPhase = '' - runHook preInstall - - mkdir $out/{bin,share/applications} -p - install ${fhs}/bin/tlauncher $out/bin - - runHook postInstall - ''; - - nativeBuildInputs = [ copyDesktopItems ]; - desktopItems = [ desktopItem ]; - - meta = with lib; { - description = "Minecraft launcher that already deal with forge, optifine and mods"; - homepage = "https://tlauncher.org/"; - maintainers = with maintainers; [ lucasew ]; - license = licenses.unfree; - platforms = openjdk8.meta.platforms; - }; -} diff --git a/pkgs/servers/matrix-synapse/default.nix b/pkgs/servers/matrix-synapse/default.nix index dbb6fbc84f50..e8a887fa93c1 100644 --- a/pkgs/servers/matrix-synapse/default.nix +++ b/pkgs/servers/matrix-synapse/default.nix @@ -11,11 +11,11 @@ in with python3.pkgs; buildPythonApplication rec { pname = "matrix-synapse"; - version = "1.49.2"; + version = "1.50.1"; src = fetchPypi { inherit pname version; - sha256 = "7b795ecfc36e3f57eb7cffbc5ef9da1745b777536416c31509b3e6220c39ca4d"; + sha256 = "sha256-fdO+HJ1+fk+s65jLkPDiG+Ei89x5Fbkh9BUUFQ3NJ3M="; }; buildInputs = [ openssl ]; @@ -31,6 +31,7 @@ buildPythonApplication rec { jinja2 jsonschema lxml + matrix-common msgpack netaddr phonenumbers diff --git a/pkgs/tools/backup/tsm-client/default.nix b/pkgs/tools/backup/tsm-client/default.nix index e298751facab..c684b34ec4e5 100644 --- a/pkgs/tools/backup/tsm-client/default.nix +++ b/pkgs/tools/backup/tsm-client/default.nix @@ -1,15 +1,20 @@ { lib +, callPackage +, nixosTests , stdenv -, autoPatchelfHook -, buildEnv , fetchurl -, makeWrapper -, procps +, autoPatchelfHook +, rpmextract +, openssl , zlib -# optional packages that enable certain features -, acl ? null # EXT2/EXT3/XFS ACL support -, jdk8 ? null # Java GUI -, lvm2 ? null # LVM image backup and restore functions +, lvm2 # LVM image backup and restore functions (optional) +, acl # EXT2/EXT3/XFS ACL support (optional) +, gnugrep +, procps +, jdk8 # Java GUI (needed for `enableGui`) +, buildEnv +, makeWrapper +, enableGui ? false # enables Java GUI `dsmj` # path to `dsm.sys` configuration files , dsmSysCli ? "/etc/tsm-client/cli.dsm.sys" , dsmSysApi ? "/etc/tsm-client/api.dsm.sys" @@ -18,7 +23,7 @@ # For an explanation of optional packages # (features provided by them, version limits), see -# https://www-01.ibm.com/support/docview.wss?uid=swg21052223#Version%208.1 +# https://www.ibm.com/support/pages/node/660813#Version%208.1 # IBM Tivoli Storage Manager Client uses a system-wide @@ -40,22 +45,33 @@ # point to this derivations `/dsmi_dir` directory symlink. # Other environment variables might be necessary, # depending on local configuration or usage; see: -# https://www.ibm.com/support/knowledgecenter/en/SSEQVQ_8.1.8/client/c_cfg_sapiunix.html +# https://www.ibm.com/docs/en/spectrum-protect/8.1.13?topic=solaris-set-api-environment-variables -# The newest version of TSM client should be discoverable -# by going the the `downloadPage` (see `meta` below), -# there to "Client Latest Downloads", -# "IBM Spectrum Protect Client Downloads and READMEs", -# then to "Linux x86_64 Ubuntu client" (as of 2019-07-15). +# The newest version of TSM client should be discoverable by +# going to the `downloadPage` (see `meta` below). +# Find the "Backup-archive client" table on that page. +# Look for "Download Documents" of the latest release. +# Here, two links must be checked: +# * "IBM Spectrum Protect Client ... Downloads and READMEs": +# In the table at the page's bottom, +# check the date of the "Linux x86_64 client" +# * "IBM Spectrum Protect BA client ... interim fix downloads" +# Look for the "Linux x86_64 client" rows +# in the table # at the bottom of each page. +# Follow the "HTTPS" link of the row with the latest date stamp. +# In the directory listing to show up, pick the big `.tar` file. +# +# (as of 2021-12-18) let meta = { - homepage = "https://www.ibm.com/us-en/marketplace/data-protection-and-recovery"; - downloadPage = "https://www-01.ibm.com/support/docview.wss?uid=swg21239415"; + homepage = "https://www.ibm.com/products/data-protection-and-recovery"; + downloadPage = "https://www.ibm.com/support/pages/ibm-spectrum-protect-downloads-latest-fix-packs-and-interim-fixes"; platforms = [ "x86_64-linux" ]; + mainProgram = "dsmc"; license = lib.licenses.unfree; maintainers = [ lib.maintainers.yarny ]; description = "IBM Spectrum Protect (Tivoli Storage Manager) CLI and API"; @@ -74,34 +90,53 @@ let ''; }; + passthru.tests = { + test-cli = callPackage ./test-cli.nix {}; + test-gui = nixosTests.tsm-client-gui; + }; + + mkSrcUrl = version: + let + major = lib.versions.major version; + minor = lib.versions.minor version; + patch = lib.versions.patch version; + fixup = lib.lists.elemAt (lib.versions.splitVersion version) 3; + in + "https://public.dhe.ibm.com/storage/tivoli-storage-management/${if fixup=="0" then "maintenance" else "patches"}/client/v${major}r${minor}/Linux/LinuxX86/BA/v${major}${minor}${patch}/${version}-TIV-TSMBAC-LinuxX86.tar"; + unwrapped = stdenv.mkDerivation rec { name = "tsm-client-${version}-unwrapped"; - version = "8.1.8.0"; + version = "8.1.13.3"; src = fetchurl { - url = "ftp://public.dhe.ibm.com/storage/tivoli-storage-management/maintenance/client/v8r1/Linux/LinuxX86_DEB/BA/v818/${version}-TIV-TSMBAC-LinuxX86_DEB.tar"; - sha256 = "0c1d0jm0i7qjd314nhj2vj8fs7sncm1x2n4d6dg4049jniyvjhpk"; + url = mkSrcUrl version; + sha256 = "1dwczf236drdaf4jcfzz5154vdwvxf5zraxhrhiddl6n80hnvbcd"; }; - inherit meta; + inherit meta passthru; nativeBuildInputs = [ autoPatchelfHook + rpmextract ]; buildInputs = [ + openssl stdenv.cc.cc zlib ]; runtimeDependencies = [ - lvm2 + (lib.attrsets.getLib lvm2) ]; sourceRoot = "."; postUnpack = '' - for debfile in *.deb - do - ar -x "$debfile" - tar --xz --extract --file=data.tar.xz - rm data.tar.xz - done + rpmextract TIVsm-API64.x86_64.rpm + rpmextract TIVsm-APIcit.x86_64.rpm + rpmextract TIVsm-BA.x86_64.rpm + rpmextract TIVsm-BAcit.x86_64.rpm + rpmextract TIVsm-BAhdw.x86_64.rpm + rpmextract TIVsm-JBB.x86_64.rpm + # use globbing so that version updates don't break the build: + rpmextract gskcrypt64-*.linux.x86_64.rpm + rpmextract gskssl64-*.linux.x86_64.rpm ''; installPhase = '' @@ -113,7 +148,7 @@ let # Fix relative symlinks after `/usr` was moved up one level preFixup = '' - for link in $out/lib/* $out/bin/* + for link in $out/lib{,64}/* $out/bin/* do target=$(readlink "$link") if [ "$(cut -b -6 <<< "$target")" != "../../" ] @@ -126,14 +161,19 @@ let ''; }; + binPath = lib.makeBinPath ([ acl gnugrep procps ] + ++ lib.optional enableGui jdk8); + in buildEnv { name = "tsm-client-${unwrapped.version}"; - inherit meta; - passthru = { inherit unwrapped; }; + meta = meta // lib.attrsets.optionalAttrs enableGui { + mainProgram = "dsmj"; + }; + passthru = passthru // { inherit unwrapped; }; paths = [ unwrapped ]; - buildInputs = [ makeWrapper ]; + nativeBuildInputs = [ makeWrapper ]; pathsToLink = [ "/" "/bin" @@ -144,7 +184,7 @@ buildEnv { # to the so-called "installation directories" # * Add symlinks to the "installation directories" # that point to the `dsm.sys` configuration files - # * Drop the Java GUI executable unless `jdk` is present + # * Drop the Java GUI executable unless `enableGui` is set # * Create wrappers for the command-line interface to # prepare `PATH` and `DSM_DIR` environment variables postBuild = '' @@ -152,13 +192,13 @@ buildEnv { ln --symbolic --no-target-directory opt/tivoli/tsm/client/api/bin64 $out/dsmi_dir ln --symbolic --no-target-directory "${dsmSysCli}" $out/dsm_dir/dsm.sys ln --symbolic --no-target-directory "${dsmSysApi}" $out/dsmi_dir/dsm.sys - ${lib.optionalString (jdk8==null) "rm $out/bin/dsmj"} + ${lib.optionalString (!enableGui) "rm $out/bin/dsmj"} for bin in $out/bin/* do target=$(readlink "$bin") rm "$bin" makeWrapper "$target" "$bin" \ - --prefix PATH : "$out/dsm_dir:${lib.strings.makeBinPath [ procps acl jdk8 ]}" \ + --prefix PATH : "$out/dsm_dir:${binPath}" \ --set DSM_DIR $out/dsm_dir done ''; diff --git a/pkgs/tools/backup/tsm-client/test-cli.nix b/pkgs/tools/backup/tsm-client/test-cli.nix new file mode 100644 index 000000000000..0858083c9f90 --- /dev/null +++ b/pkgs/tools/backup/tsm-client/test-cli.nix @@ -0,0 +1,58 @@ +{ lib +, writeText +, runCommand +, tsm-client +}: + +# Let the client try to connect to a server. +# We can't simulate a server, so there's no more to test. + +let + + # 192.0.0.8 is a "dummy address" according to RFC 7600 + dsmSysCli = writeText "cli.dsm.sys" '' + defaultserver testserver + server testserver + commmethod v6tcpip + tcpserveraddress 192.0.0.8 + nodename ARBITRARYNODENAME + ''; + + tsm-client_ = tsm-client.override { inherit dsmSysCli; }; + + env.nativeBuildInputs = [ tsm-client_ ]; + + versionString = + let + inherit (tsm-client_.passthru.unwrapped) version; + major = lib.versions.major version; + minor = lib.versions.minor version; + patch = lib.versions.patch version; + fixup = lib.lists.elemAt (lib.versions.splitVersion version) 3; + in + "Client Version ${major}, Release ${minor}, Level ${patch}.${fixup}"; + +in + +runCommand "${tsm-client.name}-test-cli" env '' + set -o nounset + set -o pipefail + + export DSM_LOG=$(mktemp -d ./dsm_log.XXXXXXXXXXX) + + { dsmc -optfile=/dev/null || true; } | tee dsmc-stdout + + # does it report the correct version? + grep --fixed-strings '${versionString}' dsmc-stdout + + # does it use the provided dsm.sys config file? + # if it does, it states the node's name + grep ARBITRARYNODENAME dsmc-stdout + + # does it try (and fail) to connect to the server? + # if it does, it reports the "TCP/IP connection failure" error code + grep ANS1017E dsmc-stdout + grep ANS1017E $DSM_LOG/dsmerror.log + + touch $out +'' diff --git a/pkgs/tools/misc/nncp/default.nix b/pkgs/tools/misc/nncp/default.nix index 8470837278b0..9024ddb64390 100644 --- a/pkgs/tools/misc/nncp/default.nix +++ b/pkgs/tools/misc/nncp/default.nix @@ -3,12 +3,12 @@ stdenv.mkDerivation rec { pname = "nncp"; - version = "8.0.2"; + version = "8.1.0"; outputs = [ "out" "doc" "info" ]; src = fetchurl { url = "http://www.nncpgo.org/download/${pname}-${version}.tar.xz"; - sha256 = "sha256-hMb7bAdk3xFcUe5CTu9LnIR3VSJDUKbMSE86s8d5udM="; + sha256 = "sha256-d3U233dedtZrBWRdb0QElNOd/L1+Ut4CWvkZo5TPU+w="; }; nativeBuildInputs = [ go redo-apenwarr ]; diff --git a/pkgs/tools/misc/pferd/default.nix b/pkgs/tools/misc/pferd/default.nix index 5c88ea2349f7..76df2a688273 100644 --- a/pkgs/tools/misc/pferd/default.nix +++ b/pkgs/tools/misc/pferd/default.nix @@ -5,14 +5,14 @@ python3Packages.buildPythonApplication rec { pname = "pferd"; - version = "3.2.0"; + version = "3.3.1"; format = "pyproject"; src = fetchFromGitHub { owner = "Garmelon"; repo = "PFERD"; rev = "v${version}"; - sha256 = "0r75a128r8ghrccc1flmpxblfrab5kg6fypzrlfmv2aqhkqg1brb"; + sha256 = "162s966kmpngmp0h55x185qxsy96q2kxz2dd8w0zyh0n2hbap3lh"; }; propagatedBuildInputs = with python3Packages; [ diff --git a/pkgs/tools/text/mdcat/default.nix b/pkgs/tools/text/mdcat/default.nix index 6cdd90f2be3d..fdf05fe20011 100644 --- a/pkgs/tools/text/mdcat/default.nix +++ b/pkgs/tools/text/mdcat/default.nix @@ -12,20 +12,20 @@ rustPlatform.buildRustPackage rec { pname = "mdcat"; - version = "0.25.0"; + version = "0.25.1"; src = fetchFromGitHub { owner = "lunaryorn"; repo = pname; rev = "mdcat-${version}"; - sha256 = "sha256-wrtvVFOSqpNBWLRGPL+08WBS4ltQyZwRE3/dqqT6IXg="; + sha256 = "sha256-deG2VjyjFs0LFeTXfPYy3zzjj0rpVjxE0DhkpD5PzSQ="; }; nativeBuildInputs = [ pkg-config asciidoctor installShellFiles ]; buildInputs = [ openssl ] ++ lib.optional stdenv.isDarwin Security; - cargoSha256 = "sha256-9I6/lt5VXfZp2/W6EoXtagcNj2kfxB5ZT2GkWgsUyM8="; + cargoSha256 = "sha256-bPGSdXooBZMye3yj00f3rWIiW4wfg2B4meH44hpkXTY="; checkInputs = [ ansi2html ]; # Skip tests that use the network and that include files. diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 0118bd5473bf..e003e62f8ba2 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -782,6 +782,7 @@ mapAliases ({ pgtap = postgresqlPackages.pgtap; plv8 = postgresqlPackages.plv8; timescaledb = postgresqlPackages.timescaledb; + tlauncher = throw "tlauncher has been removed because there questionable practices and legality concerns"; tsearch_extras = postgresqlPackages.tsearch_extras; cstore_fdw = postgresqlPackages.cstore_fdw; pg_hll = postgresqlPackages.pg_hll; diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index a98511a18b17..98fba934e326 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -4936,8 +4936,8 @@ with pkgs; timeline = callPackage ../applications/office/timeline { }; - tsm-client = callPackage ../tools/backup/tsm-client { jdk8 = null; }; - tsm-client-withGui = callPackage ../tools/backup/tsm-client { }; + tsm-client = callPackage ../tools/backup/tsm-client { }; + tsm-client-withGui = callPackage ../tools/backup/tsm-client { enableGui = true; }; tracker = callPackage ../development/libraries/tracker { }; @@ -24467,7 +24467,13 @@ with pkgs; berry = callPackage ../applications/window-managers/berry { }; - bespokesynth = callPackage ../applications/audio/bespokesynth { }; + bespokesynth = callPackage ../applications/audio/bespokesynth { + inherit (darwin.apple_sdk.frameworks) Cocoa WebKit CoreServices CoreAudioKit; + }; + + bespokesynth-with-vst2 = bespokesynth.override { + enableVST2 = true; + }; bevelbar = callPackage ../applications/window-managers/bevelbar { }; @@ -30949,8 +30955,6 @@ with pkgs; portmod = callPackage ../games/portmod { }; - tlauncher = callPackage ../games/tlauncher { }; - tr-patcher = callPackage ../games/tr-patcher { }; tes3cmd = callPackage ../games/tes3cmd { }; diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 20752391cf3b..dbe6c9bdf382 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -2888,6 +2888,8 @@ in { flask_elastic = callPackage ../development/python-modules/flask-elastic { }; + flask-gravatar = callPackage ../development/python-modules/flask-gravatar { }; + flask-httpauth = callPackage ../development/python-modules/flask-httpauth { }; flask-jwt-extended = callPackage ../development/python-modules/flask-jwt-extended { }; @@ -2908,6 +2910,8 @@ in { flask-paginate = callPackage ../development/python-modules/flask-paginate { }; + flask-paranoid = callPackage ../development/python-modules/flask-paranoid { }; + flask_principal = callPackage ../development/python-modules/flask-principal { }; flask-pymongo = callPackage ../development/python-modules/Flask-PyMongo { }; @@ -2926,6 +2930,8 @@ in { flask-session = callPackage ../development/python-modules/flask-session { }; + flask-security-too = callPackage ../development/python-modules/flask-security-too { }; + flask-silk = callPackage ../development/python-modules/flask-silk { }; flask-socketio = callPackage ../development/python-modules/flask-socketio { }; @@ -3731,6 +3737,8 @@ in { httmock = callPackage ../development/python-modules/httmock { }; + httpagentparser = callPackage ../development/python-modules/httpagentparser { }; + httpauth = callPackage ../development/python-modules/httpauth { }; httpbin = callPackage ../development/python-modules/httpbin { }; @@ -4869,6 +4877,8 @@ in { matrix-client = callPackage ../development/python-modules/matrix-client { }; + matrix-common = callPackage ../development/python-modules/matrix-common { }; + matrix-nio = callPackage ../development/python-modules/matrix-nio { }; mattermostdriver = callPackage ../development/python-modules/mattermostdriver { }; @@ -5062,6 +5072,8 @@ in { mohawk = callPackage ../development/python-modules/mohawk { }; + mongomock = callPackage ../development/python-modules/mongomock { }; + mongodict = callPackage ../development/python-modules/mongodict { }; mongoengine = callPackage ../development/python-modules/mongoengine { }; @@ -8841,6 +8853,8 @@ in { sentinel = callPackage ../development/python-modules/sentinel { }; + sentinels = callPackage ../development/python-modules/sentinels { }; + sentry-sdk = callPackage ../development/python-modules/sentry-sdk { }; sepaxml = callPackage ../development/python-modules/sepaxml { }; @@ -9158,6 +9172,8 @@ in { speaklater = callPackage ../development/python-modules/speaklater { }; + speaklater3 = callPackage ../development/python-modules/speaklater3 { }; + spectral-cube = callPackage ../development/python-modules/spectral-cube { }; speedtest-cli = callPackage ../development/python-modules/speedtest-cli { };