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 { };