Merge master into staging-next
This commit is contained in:
@@ -5467,6 +5467,12 @@
|
||||
githubId = 8735102;
|
||||
name = "John Ramsden";
|
||||
};
|
||||
johnrichardrinehart = {
|
||||
email = "johnrichardrinehart@gmail.com";
|
||||
github = "johnrichardrinehart";
|
||||
githubId = 6321578;
|
||||
name = "John Rinehart";
|
||||
};
|
||||
johntitor = {
|
||||
email = "huyuumi.dev@gmail.com";
|
||||
github = "JohnTitor";
|
||||
|
||||
@@ -344,6 +344,13 @@
|
||||
controller support.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/opensvc/multipath-tools">multipath</link>,
|
||||
the device mapper multipath (DM-MP) daemon. Available as
|
||||
<link linkend="opt-services.multipath.enable">services.multipath</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-21.11-incompatibilities">
|
||||
|
||||
@@ -105,6 +105,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- [joycond](https://github.com/DanielOgorchock/joycond), a service that uses `hid-nintendo` to provide nintendo joycond pairing and better nintendo switch pro controller support.
|
||||
|
||||
- [multipath](https://github.com/opensvc/multipath-tools), the device mapper multipath (DM-MP) daemon. Available as [services.multipath](#opt-services.multipath.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
|
||||
|
||||
- The `services.wakeonlan` option was removed, and replaced with `networking.interfaces.<name>.wakeOnLan`.
|
||||
|
||||
@@ -779,6 +779,7 @@
|
||||
./services/networking/mstpd.nix
|
||||
./services/networking/mtprotoproxy.nix
|
||||
./services/networking/mullvad-vpn.nix
|
||||
./services/networking/multipath.nix
|
||||
./services/networking/murmur.nix
|
||||
./services/networking/mxisd.nix
|
||||
./services/networking/namecoind.nix
|
||||
|
||||
@@ -64,6 +64,12 @@ in
|
||||
default = false;
|
||||
};
|
||||
|
||||
extraIscsiCommands = mkOption {
|
||||
description = "Extra iscsi commands to run in the initrd.";
|
||||
default = "";
|
||||
type = lines;
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
description = "Extra lines to append to /etc/iscsid.conf";
|
||||
default = null;
|
||||
@@ -162,6 +168,9 @@ in
|
||||
'' else ''
|
||||
iscsiadm --mode node --targetname ${escapeShellArg cfg.target} --login
|
||||
''}
|
||||
|
||||
${cfg.extraIscsiCommands}
|
||||
|
||||
pkill -9 iscsid
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -0,0 +1,572 @@
|
||||
{ config, lib, pkgs, ... }: with lib;
|
||||
|
||||
# See http://christophe.varoqui.free.fr/usage.html and
|
||||
# https://github.com/opensvc/multipath-tools/blob/master/multipath/multipath.conf.5
|
||||
|
||||
let
|
||||
cfg = config.services.multipath;
|
||||
|
||||
indentLines = n: str: concatStringsSep "\n" (
|
||||
map (line: "${fixedWidthString n " " " "}${line}") (
|
||||
filter ( x: x != "" ) ( splitString "\n" str )
|
||||
)
|
||||
);
|
||||
|
||||
addCheckDesc = desc: elemType: check: types.addCheck elemType check
|
||||
// { description = "${elemType.description} (with check: ${desc})"; };
|
||||
hexChars = stringToCharacters "0123456789abcdef";
|
||||
isHexString = s: all (c: elem c hexChars) (stringToCharacters (toLower s));
|
||||
hexStr = addCheckDesc "hexadecimal string" types.str isHexString;
|
||||
|
||||
in {
|
||||
|
||||
options.services.multipath = with types; {
|
||||
|
||||
enable = mkEnableOption "the device mapper multipath (DM-MP) daemon";
|
||||
|
||||
package = mkOption {
|
||||
type = package;
|
||||
description = "multipath-tools package to use";
|
||||
default = pkgs.multipath-tools;
|
||||
defaultText = "pkgs.multipath-tools";
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
default = [ ];
|
||||
example = literalExpression ''
|
||||
[
|
||||
{
|
||||
vendor = "\"COMPELNT\"";
|
||||
product = "\"Compellent Vol\"";
|
||||
path_checker = "tur";
|
||||
no_path_retry = "queue";
|
||||
max_sectors_kb = 256;
|
||||
}, ...
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
This option allows you to define arrays for use in multipath
|
||||
groups.
|
||||
'';
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
|
||||
vendor = mkOption {
|
||||
type = str;
|
||||
example = "COMPELNT";
|
||||
description = "Regular expression to match the vendor name";
|
||||
};
|
||||
|
||||
product = mkOption {
|
||||
type = str;
|
||||
example = "Compellent Vol";
|
||||
description = "Regular expression to match the product name";
|
||||
};
|
||||
|
||||
revision = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Regular expression to match the product revision";
|
||||
};
|
||||
|
||||
product_blacklist = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Products with the given vendor matching this string are blacklisted";
|
||||
};
|
||||
|
||||
alias_prefix = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "The user_friendly_names prefix to use for this device type, instead of the default mpath";
|
||||
};
|
||||
|
||||
vpd_vendor = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "The vendor specific vpd page information, using the vpd page abbreviation";
|
||||
};
|
||||
|
||||
hardware_handler = mkOption {
|
||||
type = nullOr (enum [ "emc" "rdac" "hp_sw" "alua" "ana" ]);
|
||||
default = null;
|
||||
description = "The hardware handler to use for this device type";
|
||||
};
|
||||
|
||||
# Optional arguments
|
||||
path_grouping_policy = mkOption {
|
||||
type = nullOr (enum [ "failover" "multibus" "group_by_serial" "group_by_prio" "group_by_node_name" ]);
|
||||
default = null; # real default: "failover"
|
||||
description = "The default path grouping policy to apply to unspecified multipaths";
|
||||
};
|
||||
|
||||
uid_attribute = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "The udev attribute providing a unique path identifier (WWID)";
|
||||
};
|
||||
|
||||
getuid_callout = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
(Superseded by uid_attribute) The default program and args to callout
|
||||
to obtain a unique path identifier. Should be specified with an absolute path.
|
||||
'';
|
||||
};
|
||||
|
||||
path_selector = mkOption {
|
||||
type = nullOr (enum [
|
||||
''"round-robin 0"''
|
||||
''"queue-length 0"''
|
||||
''"service-time 0"''
|
||||
''"historical-service-time 0"''
|
||||
]);
|
||||
default = null; # real default: "service-time 0"
|
||||
description = "The default path selector algorithm to use; they are offered by the kernel multipath target";
|
||||
};
|
||||
|
||||
path_checker = mkOption {
|
||||
type = enum [ "readsector0" "tur" "emc_clariion" "hp_sw" "rdac" "directio" "cciss_tur" "none" ];
|
||||
default = "tur";
|
||||
description = "The default method used to determine the paths state";
|
||||
};
|
||||
|
||||
prio = mkOption {
|
||||
type = nullOr (enum [
|
||||
"none" "const" "sysfs" "emc" "alua" "ontap" "rdac" "hp_sw" "hds"
|
||||
"random" "weightedpath" "path_latency" "ana" "datacore" "iet"
|
||||
]);
|
||||
default = null; # real default: "const"
|
||||
description = "The name of the path priority routine";
|
||||
};
|
||||
|
||||
prio_args = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Arguments to pass to to the prio function";
|
||||
};
|
||||
|
||||
features = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Specify any device-mapper features to be used";
|
||||
};
|
||||
|
||||
failback = mkOption {
|
||||
type = nullOr str;
|
||||
default = null; # real default: "manual"
|
||||
description = "Tell multipathd how to manage path group failback. Quote integers as strings";
|
||||
};
|
||||
|
||||
rr_weight = mkOption {
|
||||
type = nullOr (enum [ "priorities" "uniform" ]);
|
||||
default = null; # real default: "uniform"
|
||||
description = ''
|
||||
If set to priorities the multipath configurator will assign path weights
|
||||
as "path prio * rr_min_io".
|
||||
'';
|
||||
};
|
||||
|
||||
no_path_retry = mkOption {
|
||||
type = nullOr str;
|
||||
default = null; # real default: "fail"
|
||||
description = "Specify what to do when all paths are down. Quote integers as strings";
|
||||
};
|
||||
|
||||
rr_min_io = mkOption {
|
||||
type = nullOr int;
|
||||
default = null; # real default: 1000
|
||||
description = ''
|
||||
Number of I/O requests to route to a path before switching to the next in the
|
||||
same path group. This is only for Block I/O (BIO) based multipath and
|
||||
only apply to round-robin path_selector.
|
||||
'';
|
||||
};
|
||||
|
||||
rr_min_io_rq = mkOption {
|
||||
type = nullOr int;
|
||||
default = null; # real default: 1
|
||||
description = ''
|
||||
Number of I/O requests to route to a path before switching to the next in the
|
||||
same path group. This is only for Request based multipath and
|
||||
only apply to round-robin path_selector.
|
||||
'';
|
||||
};
|
||||
|
||||
fast_io_fail_tmo = mkOption {
|
||||
type = nullOr str;
|
||||
default = null; # real default: 5
|
||||
description = ''
|
||||
Specify the number of seconds the SCSI layer will wait after a problem has been
|
||||
detected on a FC remote port before failing I/O to devices on that remote port.
|
||||
This should be smaller than dev_loss_tmo. Setting this to "off" will disable
|
||||
the timeout. Quote integers as strings.
|
||||
'';
|
||||
};
|
||||
|
||||
dev_loss_tmo = mkOption {
|
||||
type = nullOr str;
|
||||
default = null; # real default: 600
|
||||
description = ''
|
||||
Specify the number of seconds the SCSI layer will wait after a problem has
|
||||
been detected on a FC remote port before removing it from the system. This
|
||||
can be set to "infinity" which sets it to the max value of 2147483647
|
||||
seconds, or 68 years. It will be automatically adjusted to the overall
|
||||
retry interval no_path_retry * polling_interval
|
||||
if a number of retries is given with no_path_retry and the
|
||||
overall retry interval is longer than the specified dev_loss_tmo value.
|
||||
The Linux kernel will cap this value to 600 if fast_io_fail_tmo
|
||||
is not set.
|
||||
'';
|
||||
};
|
||||
|
||||
flush_on_last_del = mkOption {
|
||||
type = nullOr (enum [ "yes" "no" ]);
|
||||
default = null; # real default: "no"
|
||||
description = ''
|
||||
If set to "yes" multipathd will disable queueing when the last path to a
|
||||
device has been deleted.
|
||||
'';
|
||||
};
|
||||
|
||||
user_friendly_names = mkOption {
|
||||
type = nullOr (enum [ "yes" "no" ]);
|
||||
default = null; # real default: "no"
|
||||
description = ''
|
||||
If set to "yes", using the bindings file /etc/multipath/bindings
|
||||
to assign a persistent and unique alias to the multipath, in the
|
||||
form of mpath. If set to "no" use the WWID as the alias. In either
|
||||
case this be will be overridden by any specific aliases in the
|
||||
multipaths section.
|
||||
'';
|
||||
};
|
||||
|
||||
retain_attached_hw_handler = mkOption {
|
||||
type = nullOr (enum [ "yes" "no" ]);
|
||||
default = null; # real default: "yes"
|
||||
description = ''
|
||||
(Obsolete for kernels >= 4.3) If set to "yes" and the SCSI layer has
|
||||
already attached a hardware_handler to the device, multipath will not
|
||||
force the device to use the hardware_handler specified by mutipath.conf.
|
||||
If the SCSI layer has not attached a hardware handler, multipath will
|
||||
continue to use its configured hardware handler.
|
||||
|
||||
Important Note: Linux kernel 4.3 or newer always behaves as if
|
||||
"retain_attached_hw_handler yes" was set.
|
||||
'';
|
||||
};
|
||||
|
||||
detect_prio = mkOption {
|
||||
type = nullOr (enum [ "yes" "no" ]);
|
||||
default = null; # real default: "yes"
|
||||
description = ''
|
||||
If set to "yes", multipath will try to detect if the device supports
|
||||
SCSI-3 ALUA. If so, the device will automatically use the sysfs
|
||||
prioritizer if the required sysf attributes access_state and
|
||||
preferred_path are supported, or the alua prioritizer if not. If set
|
||||
to "no", the prioritizer will be selected as usual.
|
||||
'';
|
||||
};
|
||||
|
||||
detect_checker = mkOption {
|
||||
type = nullOr (enum [ "yes" "no" ]);
|
||||
default = null; # real default: "yes"
|
||||
description = ''
|
||||
If set to "yes", multipath will try to detect if the device supports
|
||||
SCSI-3 ALUA. If so, the device will automatically use the tur checker.
|
||||
If set to "no", the checker will be selected as usual.
|
||||
'';
|
||||
};
|
||||
|
||||
deferred_remove = mkOption {
|
||||
type = nullOr (enum [ "yes" "no" ]);
|
||||
default = null; # real default: "no"
|
||||
description = ''
|
||||
If set to "yes", multipathd will do a deferred remove instead of a
|
||||
regular remove when the last path device has been deleted. This means
|
||||
that if the multipath device is still in use, it will be freed when
|
||||
the last user closes it. If path is added to the multipath device
|
||||
before the last user closes it, the deferred remove will be canceled.
|
||||
'';
|
||||
};
|
||||
|
||||
san_path_err_threshold = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
If set to a value greater than 0, multipathd will watch paths and check
|
||||
how many times a path has been failed due to errors.If the number of
|
||||
failures on a particular path is greater then the san_path_err_threshold,
|
||||
then the path will not reinstate till san_path_err_recovery_time. These
|
||||
path failures should occur within a san_path_err_forget_rate checks, if
|
||||
not we will consider the path is good enough to reinstantate.
|
||||
'';
|
||||
};
|
||||
|
||||
san_path_err_forget_rate = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
If set to a value greater than 0, multipathd will check whether the path
|
||||
failures has exceeded the san_path_err_threshold within this many checks
|
||||
i.e san_path_err_forget_rate. If so we will not reinstante the path till
|
||||
san_path_err_recovery_time.
|
||||
'';
|
||||
};
|
||||
|
||||
san_path_err_recovery_time = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
If set to a value greater than 0, multipathd will make sure that when
|
||||
path failures has exceeded the san_path_err_threshold within
|
||||
san_path_err_forget_rate then the path will be placed in failed state
|
||||
for san_path_err_recovery_time duration. Once san_path_err_recovery_time
|
||||
has timeout we will reinstante the failed path. san_path_err_recovery_time
|
||||
value should be in secs.
|
||||
'';
|
||||
};
|
||||
|
||||
marginal_path_err_sample_time = mkOption {
|
||||
type = nullOr int;
|
||||
default = null;
|
||||
description = "One of the four parameters of supporting path check based on accounting IO error such as intermittent error";
|
||||
};
|
||||
|
||||
marginal_path_err_rate_threshold = mkOption {
|
||||
type = nullOr int;
|
||||
default = null;
|
||||
description = "The error rate threshold as a permillage (1/1000)";
|
||||
};
|
||||
|
||||
marginal_path_err_recheck_gap_time = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "One of the four parameters of supporting path check based on accounting IO error such as intermittent error";
|
||||
};
|
||||
|
||||
marginal_path_double_failed_time = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "One of the four parameters of supporting path check based on accounting IO error such as intermittent error";
|
||||
};
|
||||
|
||||
delay_watch_checks = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "This option is deprecated, and mapped to san_path_err_forget_rate";
|
||||
};
|
||||
|
||||
delay_wait_checks = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "This option is deprecated, and mapped to san_path_err_recovery_time";
|
||||
};
|
||||
|
||||
skip_kpartx = mkOption {
|
||||
type = nullOr (enum [ "yes" "no" ]);
|
||||
default = null; # real default: "no"
|
||||
description = "If set to yes, kpartx will not automatically create partitions on the device";
|
||||
};
|
||||
|
||||
max_sectors_kb = mkOption {
|
||||
type = nullOr int;
|
||||
default = null;
|
||||
description = "Sets the max_sectors_kb device parameter on all path devices and the multipath device to the specified value";
|
||||
};
|
||||
|
||||
ghost_delay = mkOption {
|
||||
type = nullOr int;
|
||||
default = null;
|
||||
description = "Sets the number of seconds that multipath will wait after creating a device with only ghost paths before marking it ready for use in systemd";
|
||||
};
|
||||
|
||||
all_tg_pt = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Set the 'all targets ports' flag when registering keys with mpathpersist";
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
defaults = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
This section defines default values for attributes which are used
|
||||
whenever no values are given in the appropriate device or multipath
|
||||
sections.
|
||||
'';
|
||||
};
|
||||
|
||||
blacklist = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
This section defines which devices should be excluded from the
|
||||
multipath topology discovery.
|
||||
'';
|
||||
};
|
||||
|
||||
blacklist_exceptions = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
This section defines which devices should be included in the
|
||||
multipath topology discovery, despite being listed in the
|
||||
blacklist section.
|
||||
'';
|
||||
};
|
||||
|
||||
overrides = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
This section defines values for attributes that should override the
|
||||
device-specific settings for all devices.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Lines to append to default multipath.conf";
|
||||
};
|
||||
|
||||
extraConfigFile = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Append an additional file's contents to /etc/multipath.conf";
|
||||
};
|
||||
|
||||
pathGroups = mkOption {
|
||||
example = literalExpression ''
|
||||
[
|
||||
{
|
||||
wwid = "360080e500043b35c0123456789abcdef";
|
||||
alias = 10001234;
|
||||
array = "bigarray.example.com";
|
||||
fsType = "zfs"; # optional
|
||||
options = "ro"; # optional
|
||||
}, ...
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
This option allows you to define multipath groups as described
|
||||
in http://christophe.varoqui.free.fr/usage.html.
|
||||
'';
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
|
||||
alias = mkOption {
|
||||
type = int;
|
||||
example = 1001234;
|
||||
description = "The name of the multipath device";
|
||||
};
|
||||
|
||||
wwid = mkOption {
|
||||
type = hexStr;
|
||||
example = "360080e500043b35c0123456789abcdef";
|
||||
description = "The identifier for the multipath device";
|
||||
};
|
||||
|
||||
array = mkOption {
|
||||
type = str;
|
||||
default = null;
|
||||
example = "bigarray.example.com";
|
||||
description = "The DNS name of the storage array";
|
||||
};
|
||||
|
||||
fsType = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
example = "zfs";
|
||||
description = "Type of the filesystem";
|
||||
};
|
||||
|
||||
options = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
example = "ro";
|
||||
description = "Options used to mount the file system";
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.etc."multipath.conf".text =
|
||||
let
|
||||
inherit (cfg) defaults blacklist blacklist_exceptions overrides;
|
||||
|
||||
mkDeviceBlock = cfg: let
|
||||
nonNullCfg = lib.filterAttrs (k: v: v != null) cfg;
|
||||
attrs = lib.mapAttrsToList (name: value: " ${name} ${toString value}") nonNullCfg;
|
||||
in ''
|
||||
device {
|
||||
${lib.concatStringsSep "\n" attrs}
|
||||
}
|
||||
'';
|
||||
devices = lib.concatMapStringsSep "\n" mkDeviceBlock cfg.devices;
|
||||
|
||||
mkMultipathBlock = m: ''
|
||||
multipath {
|
||||
wwid ${m.wwid}
|
||||
alias ${toString m.alias}
|
||||
}
|
||||
'';
|
||||
multipaths = lib.concatMapStringsSep "\n" mkMultipathBlock cfg.pathGroups;
|
||||
|
||||
in ''
|
||||
devices {
|
||||
${indentLines 2 devices}
|
||||
}
|
||||
|
||||
${optionalString (!isNull defaults) ''
|
||||
defaults {
|
||||
${indentLines 2 defaults}
|
||||
multipath_dir ${cfg.package}/lib/multipath
|
||||
}
|
||||
''}
|
||||
${optionalString (!isNull blacklist) ''
|
||||
blacklist {
|
||||
${indentLines 2 blacklist}
|
||||
}
|
||||
''}
|
||||
${optionalString (!isNull blacklist_exceptions) ''
|
||||
blacklist_exceptions {
|
||||
${indentLines 2 blacklist_exceptions}
|
||||
}
|
||||
''}
|
||||
${optionalString (!isNull overrides) ''
|
||||
overrides {
|
||||
${indentLines 2 overrides}
|
||||
}
|
||||
''}
|
||||
multipaths {
|
||||
${indentLines 2 multipaths}
|
||||
}
|
||||
'';
|
||||
|
||||
systemd.packages = [ cfg.package ];
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
boot.kernelModules = [ "dm-multipath" "dm-service-time" ];
|
||||
|
||||
# We do not have systemd in stage-1 boot so must invoke `multipathd`
|
||||
# with the `-1` argument which disables systemd calls. Invoke `multipath`
|
||||
# to display the multipath mappings in the output of `journalctl -b`.
|
||||
boot.initrd.kernelModules = [ "dm-multipath" "dm-service-time" ];
|
||||
boot.initrd.postDeviceCommands = ''
|
||||
modprobe -a dm-multipath dm-service-time
|
||||
multipathd -s
|
||||
(set -x && sleep 1 && multipath -ll)
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -6,6 +6,8 @@ let
|
||||
cfg = config.services.nextcloud;
|
||||
fpm = config.services.phpfpm.pools.nextcloud;
|
||||
|
||||
inherit (cfg) datadir;
|
||||
|
||||
phpPackage = cfg.phpPackage.buildEnv {
|
||||
extensions = { enabled, all }:
|
||||
(with all;
|
||||
@@ -40,7 +42,7 @@ let
|
||||
if [[ "$USER" != nextcloud ]]; then
|
||||
sudo='exec /run/wrappers/bin/sudo -u nextcloud --preserve-env=NEXTCLOUD_CONFIG_DIR --preserve-env=OC_PASS'
|
||||
fi
|
||||
export NEXTCLOUD_CONFIG_DIR="${cfg.home}/config"
|
||||
export NEXTCLOUD_CONFIG_DIR="${datadir}/config"
|
||||
$sudo \
|
||||
${phpPackage}/bin/php \
|
||||
occ "$@"
|
||||
@@ -85,6 +87,59 @@ in {
|
||||
default = "/var/lib/nextcloud";
|
||||
description = "Storage path of nextcloud.";
|
||||
};
|
||||
datadir = mkOption {
|
||||
type = types.str;
|
||||
defaultText = "config.services.nextcloud.home";
|
||||
description = ''
|
||||
Data storage path of nextcloud. Will be <xref linkend="opt-services.nextcloud.home" /> by default.
|
||||
This folder will be populated with a config.php and data folder which contains the state of the instance (excl the database).";
|
||||
'';
|
||||
example = "/mnt/nextcloud-file";
|
||||
};
|
||||
extraApps = mkOption {
|
||||
type = types.attrsOf types.package;
|
||||
default = { };
|
||||
description = ''
|
||||
Extra apps to install. Should be an attrSet of appid to packages generated by fetchNextcloudApp.
|
||||
The appid must be identical to the "id" value in the apps appinfo/info.xml.
|
||||
Using this will disable the appstore to prevent Nextcloud from updating these apps (see <xref linkend="opt-services.nextcloud.appstoreEnable" />).
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
maps = pkgs.fetchNextcloudApp {
|
||||
name = "maps";
|
||||
sha256 = "007y80idqg6b6zk6kjxg4vgw0z8fsxs9lajnv49vv1zjy6jx2i1i";
|
||||
url = "https://github.com/nextcloud/maps/releases/download/v0.1.9/maps-0.1.9.tar.gz";
|
||||
version = "0.1.9";
|
||||
};
|
||||
phonetrack = pkgs.fetchNextcloudApp {
|
||||
name = "phonetrack";
|
||||
sha256 = "0qf366vbahyl27p9mshfma1as4nvql6w75zy2zk5xwwbp343vsbc";
|
||||
url = "https://gitlab.com/eneiluj/phonetrack-oc/-/wikis/uploads/931aaaf8dca24bf31a7e169a83c17235/phonetrack-0.6.9.tar.gz";
|
||||
version = "0.6.9";
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
extraAppsEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Automatically enable the apps in <xref linkend="opt-services.nextcloud.extraApps" /> every time nextcloud starts.
|
||||
If set to false, apps need to be enabled in the Nextcloud user interface or with nextcloud-occ app:enable.
|
||||
'';
|
||||
};
|
||||
appstoreEnable = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
example = true;
|
||||
description = ''
|
||||
Allow the installation of apps and app updates from the store.
|
||||
Enabled by default unless there are packages in <xref linkend="opt-services.nextcloud.extraApps" />.
|
||||
Set to true to force enable the store even if <xref linkend="opt-services.nextcloud.extraApps" /> is used.
|
||||
Set to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting.
|
||||
'';
|
||||
};
|
||||
logLevel = mkOption {
|
||||
type = types.ints.between 0 4;
|
||||
default = 2;
|
||||
@@ -524,6 +579,8 @@ in {
|
||||
else nextcloud22
|
||||
);
|
||||
|
||||
services.nextcloud.datadir = mkOptionDefault config.services.nextcloud.home;
|
||||
|
||||
services.nextcloud.phpPackage =
|
||||
if versionOlder cfg.package.version "21" then pkgs.php74
|
||||
else pkgs.php80;
|
||||
@@ -563,6 +620,14 @@ in {
|
||||
]
|
||||
'';
|
||||
|
||||
showAppStoreSetting = cfg.appstoreEnable != null || cfg.extraApps != {};
|
||||
renderedAppStoreSetting =
|
||||
let
|
||||
x = cfg.appstoreEnable;
|
||||
in
|
||||
if x == null then "false"
|
||||
else boolToString x;
|
||||
|
||||
overrideConfig = pkgs.writeText "nextcloud-config.php" ''
|
||||
<?php
|
||||
${optionalString requiresReadSecretFunction ''
|
||||
@@ -581,10 +646,12 @@ in {
|
||||
''}
|
||||
$CONFIG = [
|
||||
'apps_paths' => [
|
||||
${optionalString (cfg.extraApps != { }) "[ 'path' => '${cfg.home}/nix-apps', 'url' => '/nix-apps', 'writable' => false ],"}
|
||||
[ 'path' => '${cfg.home}/apps', 'url' => '/apps', 'writable' => false ],
|
||||
[ 'path' => '${cfg.home}/store-apps', 'url' => '/store-apps', 'writable' => true ],
|
||||
],
|
||||
'datadirectory' => '${cfg.home}/data',
|
||||
${optionalString (showAppStoreSetting) "'appstoreenabled' => ${renderedAppStoreSetting},"}
|
||||
'datadirectory' => '${datadir}/data',
|
||||
'skeletondirectory' => '${cfg.skeletonDirectory}',
|
||||
${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"}
|
||||
'log_type' => 'syslog',
|
||||
@@ -628,7 +695,7 @@ in {
|
||||
"--database-pass" = "\$${dbpass.arg}";
|
||||
"--admin-user" = ''"${c.adminuser}"'';
|
||||
"--admin-pass" = "\$${adminpass.arg}";
|
||||
"--data-dir" = ''"${cfg.home}/data"'';
|
||||
"--data-dir" = ''"${datadir}/data"'';
|
||||
});
|
||||
in ''
|
||||
${mkExport dbpass}
|
||||
@@ -670,9 +737,15 @@ in {
|
||||
|
||||
ln -sf ${cfg.package}/apps ${cfg.home}/
|
||||
|
||||
# Install extra apps
|
||||
ln -sfT \
|
||||
${pkgs.linkFarm "nix-apps"
|
||||
(mapAttrsToList (name: path: { inherit name path; }) cfg.extraApps)} \
|
||||
${cfg.home}/nix-apps
|
||||
|
||||
# create nextcloud directories.
|
||||
# if the directories exist already with wrong permissions, we fix that
|
||||
for dir in ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps; do
|
||||
for dir in ${datadir}/config ${datadir}/data ${cfg.home}/store-apps ${cfg.home}/nix-apps; do
|
||||
if [ ! -e $dir ]; then
|
||||
install -o nextcloud -g nextcloud -d $dir
|
||||
elif [ $(stat -c "%G" $dir) != "nextcloud" ]; then
|
||||
@@ -680,23 +753,29 @@ in {
|
||||
fi
|
||||
done
|
||||
|
||||
ln -sf ${overrideConfig} ${cfg.home}/config/override.config.php
|
||||
ln -sf ${overrideConfig} ${datadir}/config/override.config.php
|
||||
|
||||
# Do not install if already installed
|
||||
if [[ ! -e ${cfg.home}/config/config.php ]]; then
|
||||
if [[ ! -e ${datadir}/config/config.php ]]; then
|
||||
${occInstallCmd}
|
||||
fi
|
||||
|
||||
${occ}/bin/nextcloud-occ upgrade
|
||||
|
||||
${occ}/bin/nextcloud-occ config:system:delete trusted_domains
|
||||
|
||||
${optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) ''
|
||||
# Try to enable apps (don't fail when one of them cannot be enabled , eg. due to incompatible version)
|
||||
${occ}/bin/nextcloud-occ app:enable ${concatStringsSep " " (attrNames cfg.extraApps)}
|
||||
''}
|
||||
|
||||
${occSetTrustedDomainsCmd}
|
||||
'';
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.User = "nextcloud";
|
||||
};
|
||||
nextcloud-cron = {
|
||||
environment.NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
|
||||
environment.NEXTCLOUD_CONFIG_DIR = "${datadir}/config";
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.User = "nextcloud";
|
||||
serviceConfig.ExecStart = "${phpPackage}/bin/php -f ${cfg.package}/cron.php";
|
||||
@@ -715,7 +794,7 @@ in {
|
||||
group = "nextcloud";
|
||||
phpPackage = phpPackage;
|
||||
phpEnv = {
|
||||
NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
|
||||
NEXTCLOUD_CONFIG_DIR = "${datadir}/config";
|
||||
PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin";
|
||||
};
|
||||
settings = mapAttrs (name: mkDefault) {
|
||||
@@ -765,6 +844,10 @@ in {
|
||||
priority = 201;
|
||||
extraConfig = "root ${cfg.home};";
|
||||
};
|
||||
"~ ^/nix-apps" = {
|
||||
priority = 201;
|
||||
extraConfig = "root ${cfg.home};";
|
||||
};
|
||||
"^~ /.well-known" = {
|
||||
priority = 210;
|
||||
extraConfig = ''
|
||||
|
||||
@@ -237,6 +237,12 @@
|
||||
Some apps may require extra PHP extensions to be installed.
|
||||
This can be configured with the <xref linkend="opt-services.nextcloud.phpExtraExtensions" /> setting.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Alternatively, extra apps can also be declared with the <xref linkend="opt-services.nextcloud.extraApps" /> setting.
|
||||
When using this setting, apps can no longer be managed statefully because this can lead to Nextcloud updating apps
|
||||
that are managed by Nix. If you want automatic updates it is recommended that you use web interface to install apps.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="module-services-nextcloud-maintainer-info">
|
||||
|
||||
@@ -137,6 +137,14 @@ let
|
||||
copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs
|
||||
''}
|
||||
|
||||
# Copy multipath.
|
||||
${optionalString config.services.multipath.enable ''
|
||||
copy_bin_and_libs ${config.services.multipath.package}/bin/multipath
|
||||
copy_bin_and_libs ${config.services.multipath.package}/bin/multipathd
|
||||
# Copy lib/multipath manually.
|
||||
cp -rpv ${config.services.multipath.package}/lib/multipath $out/lib
|
||||
''}
|
||||
|
||||
# Copy secrets if needed.
|
||||
#
|
||||
# TODO: move out to a separate script; see #85000.
|
||||
@@ -199,6 +207,10 @@ let
|
||||
$out/bin/dmsetup --version 2>&1 | tee -a log | grep -q "version:"
|
||||
LVM_SYSTEM_DIR=$out $out/bin/lvm version 2>&1 | tee -a log | grep -q "LVM"
|
||||
$out/bin/mdadm --version
|
||||
${optionalString config.services.multipath.enable ''
|
||||
($out/bin/multipath || true) 2>&1 | grep -q 'need to be root'
|
||||
($out/bin/multipathd || true) 2>&1 | grep -q 'need to be root'
|
||||
''}
|
||||
|
||||
${config.boot.initrd.extraUtilsCommandsTest}
|
||||
fi
|
||||
@@ -338,7 +350,26 @@ let
|
||||
{ object = pkgs.kmod-debian-aliases;
|
||||
symlink = "/etc/modprobe.d/debian.conf";
|
||||
}
|
||||
];
|
||||
] ++ lib.optionals config.services.multipath.enable [
|
||||
{ object = pkgs.runCommand "multipath.conf" {
|
||||
src = config.environment.etc."multipath.conf".text;
|
||||
preferLocalBuild = true;
|
||||
} ''
|
||||
target=$out
|
||||
printf "$src" > $out
|
||||
substituteInPlace $out \
|
||||
--replace ${config.services.multipath.package}/lib ${extraUtils}/lib
|
||||
'';
|
||||
symlink = "/etc/multipath.conf";
|
||||
}
|
||||
] ++ (lib.mapAttrsToList
|
||||
(symlink: options:
|
||||
{
|
||||
inherit symlink;
|
||||
object = options.source;
|
||||
}
|
||||
)
|
||||
config.boot.initrd.extraFiles);
|
||||
};
|
||||
|
||||
# Script to add secret files to the initrd at bootloader update time
|
||||
@@ -419,6 +450,22 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
boot.initrd.extraFiles = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf
|
||||
(types.submodule {
|
||||
options = {
|
||||
source = mkOption {
|
||||
type = types.package;
|
||||
description = "The object to make available inside the initrd.";
|
||||
};
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
Extra files to link and copy in to the initrd.
|
||||
'';
|
||||
};
|
||||
|
||||
boot.initrd.prepend = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, lib, ... }:
|
||||
let
|
||||
initiatorName = "iqn.2020-08.org.linux-iscsi.initiatorhost:example";
|
||||
targetName = "iqn.2003-01.org.linux-iscsi.target.x8664:sn.acf8fd9c23af";
|
||||
in
|
||||
{
|
||||
name = "iscsi";
|
||||
meta = {
|
||||
maintainers = pkgs.lib.teams.deshaw.members;
|
||||
};
|
||||
|
||||
nodes = {
|
||||
target = { config, pkgs, lib, ... }: {
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
services.target = {
|
||||
enable = true;
|
||||
config = {
|
||||
fabric_modules = [ ];
|
||||
storage_objects = [
|
||||
{
|
||||
dev = "/dev/vdb";
|
||||
name = "test";
|
||||
plugin = "block";
|
||||
write_back = true;
|
||||
wwn = "92b17c3f-6b40-4168-b082-ceeb7b495522";
|
||||
}
|
||||
];
|
||||
targets = [
|
||||
{
|
||||
fabric = "iscsi";
|
||||
tpgs = [
|
||||
{
|
||||
enable = true;
|
||||
attributes = {
|
||||
authentication = 0;
|
||||
generate_node_acls = 1;
|
||||
};
|
||||
luns = [
|
||||
{
|
||||
alias = "94dfe06967";
|
||||
alua_tg_pt_gp_name = "default_tg_pt_gp";
|
||||
index = 0;
|
||||
storage_object = "/backstores/block/test";
|
||||
}
|
||||
];
|
||||
node_acls = [
|
||||
{
|
||||
mapped_luns = [
|
||||
{
|
||||
alias = "d42f5bdf8a";
|
||||
index = 0;
|
||||
tpg_lun = 0;
|
||||
write_protect = false;
|
||||
}
|
||||
];
|
||||
node_wwn = initiatorName;
|
||||
}
|
||||
];
|
||||
portals = [
|
||||
{
|
||||
ip_address = "0.0.0.0";
|
||||
iser = false;
|
||||
offload = false;
|
||||
port = 3260;
|
||||
}
|
||||
];
|
||||
tag = 1;
|
||||
}
|
||||
];
|
||||
wwn = targetName;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 3260 ];
|
||||
networking.firewall.allowedUDPPorts = [ 3260 ];
|
||||
|
||||
virtualisation.memorySize = 2048;
|
||||
virtualisation.emptyDiskImages = [ 2048 ];
|
||||
};
|
||||
|
||||
initiatorAuto = { nodes, config, pkgs, ... }: {
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
|
||||
services.multipath = {
|
||||
enable = true;
|
||||
defaults = ''
|
||||
find_multipaths yes
|
||||
user_friendly_names yes
|
||||
'';
|
||||
pathGroups = [
|
||||
{
|
||||
alias = 123456;
|
||||
wwid = "3600140592b17c3f6b404168b082ceeb7";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.openiscsi = {
|
||||
enable = true;
|
||||
enableAutoLoginOut = true;
|
||||
discoverPortal = "target";
|
||||
name = initiatorName;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
xfsprogs
|
||||
];
|
||||
|
||||
environment.etc."initiator-root-disk-closure".source = nodes.initiatorRootDisk.config.system.build.toplevel;
|
||||
|
||||
nix.binaryCaches = lib.mkForce [ ];
|
||||
nix.extraOptions = ''
|
||||
hashed-mirrors =
|
||||
connect-timeout = 1
|
||||
'';
|
||||
};
|
||||
|
||||
initiatorRootDisk = { config, pkgs, modulesPath, lib, ... }: {
|
||||
boot.initrd.network.enable = true;
|
||||
boot.loader.grub.enable = false;
|
||||
|
||||
boot.kernelParams = lib.mkOverride 5 (
|
||||
[
|
||||
"boot.shell_on_fail"
|
||||
"console=tty1"
|
||||
"ip=192.168.1.1:::255.255.255.0::ens9:none"
|
||||
"ip=192.168.2.1:::255.255.255.0::ens10:none"
|
||||
]
|
||||
);
|
||||
|
||||
# defaults to true, puts some code in the initrd that tries to mount an overlayfs on /nix/store
|
||||
virtualisation.writableStore = false;
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
|
||||
services.multipath = {
|
||||
enable = true;
|
||||
defaults = ''
|
||||
find_multipaths yes
|
||||
user_friendly_names yes
|
||||
'';
|
||||
pathGroups = [
|
||||
{
|
||||
alias = 123456;
|
||||
wwid = "3600140592b17c3f6b404168b082ceeb7";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems = lib.mkOverride 5 {
|
||||
"/" = {
|
||||
fsType = "xfs";
|
||||
device = "/dev/mapper/123456";
|
||||
options = [ "_netdev" ];
|
||||
};
|
||||
};
|
||||
|
||||
boot.initrd.extraFiles."etc/multipath/wwids".source = pkgs.writeText "wwids" "/3600140592b17c3f6b404168b082ceeb7/";
|
||||
|
||||
boot.iscsi-initiator = {
|
||||
discoverPortal = "target";
|
||||
name = initiatorName;
|
||||
target = targetName;
|
||||
extraIscsiCommands = ''
|
||||
iscsiadm -m discovery -o update -t sendtargets -p 192.168.2.3 --login
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
testScript = { nodes, ... }: ''
|
||||
target.start()
|
||||
target.wait_for_unit("iscsi-target.service")
|
||||
|
||||
initiatorAuto.start()
|
||||
|
||||
initiatorAuto.wait_for_unit("iscsid.service")
|
||||
initiatorAuto.wait_for_unit("iscsi.service")
|
||||
initiatorAuto.get_unit_info("iscsi")
|
||||
|
||||
# Expecting this to fail since we should already know about 192.168.1.3
|
||||
initiatorAuto.fail("iscsiadm -m discovery -o update -t sendtargets -p 192.168.1.3 --login")
|
||||
# Expecting this to succeed since we don't yet know about 192.168.2.3
|
||||
initiatorAuto.succeed("iscsiadm -m discovery -o update -t sendtargets -p 192.168.2.3 --login")
|
||||
|
||||
# /dev/sda is provided by iscsi on target
|
||||
initiatorAuto.succeed("set -x; while ! test -e /dev/sda; do sleep 1; done")
|
||||
|
||||
initiatorAuto.succeed("mkfs.xfs /dev/sda")
|
||||
initiatorAuto.succeed("mkdir /mnt")
|
||||
|
||||
# Start by verifying /dev/sda and /dev/sdb are both the same disk
|
||||
initiatorAuto.succeed("mount /dev/sda /mnt")
|
||||
initiatorAuto.succeed("touch /mnt/hi")
|
||||
initiatorAuto.succeed("umount /mnt")
|
||||
|
||||
initiatorAuto.succeed("mount /dev/sdb /mnt")
|
||||
initiatorAuto.succeed("test -e /mnt/hi")
|
||||
initiatorAuto.succeed("umount /mnt")
|
||||
|
||||
initiatorAuto.succeed("systemctl restart multipathd")
|
||||
initiatorAuto.succeed("multipath -ll | systemd-cat")
|
||||
|
||||
# Install our RootDisk machine to 123456, the alias to the device that multipath is now managing
|
||||
initiatorAuto.succeed("mount /dev/mapper/123456 /mnt")
|
||||
initiatorAuto.succeed("mkdir -p /mnt/etc/{multipath,iscsi}")
|
||||
initiatorAuto.succeed("cp -r /etc/multipath/wwids /mnt/etc/multipath/wwids")
|
||||
initiatorAuto.succeed("cp -r /etc/iscsi/{nodes,send_targets} /mnt/etc/iscsi")
|
||||
initiatorAuto.succeed(
|
||||
"nixos-install --no-bootloader --no-root-passwd --system /etc/initiator-root-disk-closure"
|
||||
)
|
||||
initiatorAuto.succeed("umount /mnt")
|
||||
initiatorAuto.shutdown()
|
||||
|
||||
initiatorRootDisk.start()
|
||||
initiatorRootDisk.wait_for_unit("multi-user.target")
|
||||
initiatorRootDisk.wait_for_unit("iscsid")
|
||||
|
||||
# Log in over both nodes
|
||||
initiatorRootDisk.fail("iscsiadm -m discovery -o update -t sendtargets -p 192.168.1.3 --login")
|
||||
initiatorRootDisk.fail("iscsiadm -m discovery -o update -t sendtargets -p 192.168.2.3 --login")
|
||||
initiatorRootDisk.succeed("systemctl restart multipathd")
|
||||
initiatorRootDisk.succeed("multipath -ll | systemd-cat")
|
||||
|
||||
# Verify we can write and sync the root disk
|
||||
initiatorRootDisk.succeed("mkdir /scratch")
|
||||
initiatorRootDisk.succeed("touch /scratch/both-up")
|
||||
initiatorRootDisk.succeed("sync /scratch")
|
||||
|
||||
# Verify we can write to the root with ens9 (sda, 192.168.1.3) down
|
||||
initiatorRootDisk.succeed("ip link set ens9 down")
|
||||
initiatorRootDisk.succeed("touch /scratch/ens9-down")
|
||||
initiatorRootDisk.succeed("sync /scratch")
|
||||
initiatorRootDisk.succeed("ip link set ens9 up")
|
||||
|
||||
# todo: better way to wait until multipath notices the link is back
|
||||
initiatorRootDisk.succeed("sleep 5")
|
||||
initiatorRootDisk.succeed("touch /scratch/both-down")
|
||||
initiatorRootDisk.succeed("sync /scratch")
|
||||
|
||||
# Verify we can write to the root with ens10 (sdb, 192.168.2.3) down
|
||||
initiatorRootDisk.succeed("ip link set ens10 down")
|
||||
initiatorRootDisk.succeed("touch /scratch/ens10-down")
|
||||
initiatorRootDisk.succeed("sync /scratch")
|
||||
initiatorRootDisk.succeed("ip link set ens10 up")
|
||||
initiatorRootDisk.succeed("touch /scratch/ens10-down")
|
||||
initiatorRootDisk.succeed("sync /scratch")
|
||||
|
||||
initiatorRootDisk.succeed("ip link set ens9 up")
|
||||
initiatorRootDisk.succeed("ip link set ens10 up")
|
||||
initiatorRootDisk.shutdown()
|
||||
|
||||
# Verify we can boot with the target's eth1 down, forcing
|
||||
# it to multipath via the second link
|
||||
target.succeed("ip link set eth1 down")
|
||||
initiatorRootDisk.start()
|
||||
initiatorRootDisk.wait_for_unit("multi-user.target")
|
||||
initiatorRootDisk.wait_for_unit("iscsid")
|
||||
initiatorRootDisk.succeed("test -e /scratch/both-up")
|
||||
'';
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -33,8 +33,13 @@ in {
|
||||
in {
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/nextcloud-data 0750 nextcloud nginx - -"
|
||||
];
|
||||
|
||||
services.nextcloud = {
|
||||
enable = true;
|
||||
datadir = "/var/lib/nextcloud-data";
|
||||
hostName = "nextcloud";
|
||||
config = {
|
||||
# Don't inherit adminuser since "root" is supposed to be the default
|
||||
@@ -98,6 +103,7 @@ in {
|
||||
"${withRcloneEnv} ${copySharedFile}"
|
||||
)
|
||||
client.wait_for_unit("multi-user.target")
|
||||
nextcloud.succeed("test -f /var/lib/nextcloud-data/data/root/files/test-shared-file")
|
||||
client.succeed(
|
||||
"${withRcloneEnv} ${diffSharedFile}"
|
||||
)
|
||||
|
||||
@@ -198,6 +198,8 @@
|
||||
|
||||
railgun = callPackage ./railgun { };
|
||||
|
||||
rec-mode = callPackage ./rec-mode { };
|
||||
|
||||
structured-haskell-mode = self.shm;
|
||||
|
||||
sv-kalender = callPackage ./sv-kalender { };
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{ lib
|
||||
, trivialBuild
|
||||
, recutils
|
||||
}:
|
||||
|
||||
trivialBuild {
|
||||
pname = "rec-mode";
|
||||
|
||||
inherit (recutils) version src;
|
||||
|
||||
postUnpack = ''
|
||||
sourceRoot="$sourceRoot/etc"
|
||||
'';
|
||||
|
||||
meta = recutils.meta // {
|
||||
description = "A major mode for editing rec files";
|
||||
};
|
||||
}
|
||||
@@ -18,11 +18,11 @@ let
|
||||
vivaldiName = if isSnapshot then "vivaldi-snapshot" else "vivaldi";
|
||||
in stdenv.mkDerivation rec {
|
||||
pname = "vivaldi";
|
||||
version = "4.1.2369.21-1";
|
||||
version = "4.3.2439.44-1";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://downloads.vivaldi.com/${branch}/vivaldi-${branch}_${version}_amd64.deb";
|
||||
sha256 = "03062mik6paqp219jz420jsg762jjrfxmj1daq129z2zgzq0qr8l";
|
||||
sha256 = "1bsx8axs438f4p019mdq66pmpimf575r31rv6cibpgv85366xhh9";
|
||||
};
|
||||
|
||||
unpackPhase = ''
|
||||
@@ -49,7 +49,7 @@ in stdenv.mkDerivation rec {
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
echo "Patching Vivaldi binaries"
|
||||
for f in crashpad_handler vivaldi-bin vivaldi-sandbox ; do
|
||||
for f in chrome_crashpad_handler vivaldi-bin vivaldi-sandbox ; do
|
||||
patchelf \
|
||||
--set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
|
||||
--set-rpath "${libPath}" \
|
||||
|
||||
@@ -563,10 +563,10 @@
|
||||
"owner": "hashicorp",
|
||||
"provider-source-address": "registry.terraform.io/hashicorp/kubernetes",
|
||||
"repo": "terraform-provider-kubernetes",
|
||||
"rev": "v2.4.1",
|
||||
"sha256": "0mk0f12yy58gjkki7xpf9bjfw9h9zdgby2b4bddqp5csq11payhd",
|
||||
"rev": "v2.5.0",
|
||||
"sha256": "1hp3bwhlfiwf1a4l6xfldwdxmyjs4nq3n8g343grjya7ibbhh4sg",
|
||||
"vendorSha256": null,
|
||||
"version": "2.4.1"
|
||||
"version": "2.5.0"
|
||||
},
|
||||
"launchdarkly": {
|
||||
"owner": "terraform-providers",
|
||||
|
||||
@@ -7,7 +7,7 @@ let
|
||||
|
||||
# Please keep the version x.y.0.z and do not update to x.y.76.z because the
|
||||
# source of the latter disappears much faster.
|
||||
version = "8.75.0.140";
|
||||
version = "8.77.0.97";
|
||||
|
||||
rpath = lib.makeLibraryPath [
|
||||
alsa-lib
|
||||
@@ -69,7 +69,7 @@ let
|
||||
"https://mirror.cs.uchicago.edu/skype/pool/main/s/skypeforlinux/skypeforlinux_${version}_amd64.deb"
|
||||
"https://web.archive.org/web/https://repo.skype.com/deb/pool/main/s/skypeforlinux/skypeforlinux_${version}_amd64.deb"
|
||||
];
|
||||
sha256 = "sha256-z3xsl53CSJthSd/BMbMD7RdYQ4z9oI/Rb9jUvd82H4E=";
|
||||
sha256 = "sha256-0u1fpKJrsEgbvTwdkqJZ/SwCRDmJwEi9IXHbMmY8MJI=";
|
||||
}
|
||||
else
|
||||
throw "Skype for linux is not supported on ${stdenv.hostPlatform.system}";
|
||||
|
||||
@@ -19,7 +19,7 @@ stdenv.mkDerivation rec {
|
||||
# z3's install phase is stupid because it tries to calculate the
|
||||
# python package store location itself, meaning it'll attempt to
|
||||
# write files into the nix store, and fail.
|
||||
soext = if stdenv.system == "x86_64-darwin" then ".dylib" else ".so";
|
||||
soext = stdenv.hostPlatform.extensions.sharedLibrary;
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/lib/${python.libPrefix}/site-packages $out/include
|
||||
cp ../src/api/z3*.h $out/include
|
||||
|
||||
@@ -13,11 +13,11 @@ let
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "gitkraken";
|
||||
version = "7.7.2";
|
||||
version = "8.0.1";
|
||||
|
||||
src = fetchzip {
|
||||
url = "https://release.axocdn.com/linux/GitKraken-v${version}.tar.gz";
|
||||
sha256 = "sha256-jL0XLw0V0ED+lDBn3sGaJmm96zQwXue333UuYGHjB64=";
|
||||
sha256 = "1n88m41424qwsfp2hy58piqpv2dk6i74hcj184aq6njllvnsznnq";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{ stdenv, gnutar, findutils, fetchurl, ... }:
|
||||
{ name
|
||||
, url
|
||||
, version
|
||||
, sha256
|
||||
, patches ? [ ]
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "nc-app-${name}";
|
||||
inherit version patches;
|
||||
|
||||
src = fetchurl {
|
||||
inherit url sha256;
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
gnutar
|
||||
findutils
|
||||
];
|
||||
|
||||
unpackPhase = ''
|
||||
tar -xzpf $src
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
approot="$(dirname $(dirname $(find -path '*/appinfo/info.xml' | head -n 1)))"
|
||||
|
||||
if [ -d "$approot" ];
|
||||
then
|
||||
mv "$approot/" $out
|
||||
chmod -R a-w $out
|
||||
else
|
||||
echo "Could not find appinfo/info.xml"
|
||||
exit 1;
|
||||
fi
|
||||
'';
|
||||
}
|
||||
@@ -151,13 +151,11 @@ stdenv.mkDerivation rec {
|
||||
in
|
||||
(lib.optionalString enableFIPS (''
|
||||
for libname in freebl3 nssdbm3 softokn3
|
||||
do '' +
|
||||
do libfile="$out/lib/lib$libname${stdenv.hostPlatform.extensions.sharedLibrary}"'' +
|
||||
(if stdenv.isDarwin
|
||||
then ''
|
||||
libfile="$out/lib/lib$libname.dylib"
|
||||
DYLD_LIBRARY_PATH=$out/lib:${nspr.out}/lib \
|
||||
'' else ''
|
||||
libfile="$out/lib/lib$libname.so"
|
||||
LD_LIBRARY_PATH=$out/lib:${nspr.out}/lib \
|
||||
'') + ''
|
||||
${nss}/bin/shlibsign -v -i "$libfile"
|
||||
|
||||
@@ -166,13 +166,11 @@ stdenv.mkDerivation rec {
|
||||
in
|
||||
(lib.optionalString enableFIPS (''
|
||||
for libname in freebl3 nssdbm3 softokn3
|
||||
do '' +
|
||||
do libfile="$out/lib/lib$libname${stdenv.hostPlatform.extensions.sharedLibrary}"'' +
|
||||
(if stdenv.isDarwin
|
||||
then ''
|
||||
libfile="$out/lib/lib$libname.dylib"
|
||||
DYLD_LIBRARY_PATH=$out/lib:${nspr.out}/lib \
|
||||
'' else ''
|
||||
libfile="$out/lib/lib$libname.so"
|
||||
LD_LIBRARY_PATH=$out/lib:${nspr.out}/lib \
|
||||
'') + ''
|
||||
${nss}/bin/shlibsign -v -i "$libfile"
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
passthru = {
|
||||
fancyName = "MariaDB";
|
||||
driver = if stdenv.isDarwin then "lib/libmaodbc.dylib" else "lib/libmaodbc.so";
|
||||
driver = "lib/libmaodbc${stdenv.hostPlatform.extensions.sharedLibrary}";
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "aiodiscover";
|
||||
version = "1.4.4";
|
||||
version = "1.4.5";
|
||||
disabled = pythonOlder "3.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "bdraco";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-DobTx6oUr25J8bolo84V4yTT0b0jBsOIzPn93uAmDl0=";
|
||||
sha256 = "sha256-QfeAEFB5WikuriBTcfFIgnJw5H4vEcGIVX47fyDb1Dk=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -12,7 +12,7 @@ buildPythonPackage rec {
|
||||
|
||||
# TODO: not very nice!
|
||||
postPatch =
|
||||
let libname = if stdenv.isDarwin then "libaugeas.dylib" else "libaugeas.so";
|
||||
let libname = "libaugeas${stdenv.hostPlatform.extensions.sharedLibrary}";
|
||||
in
|
||||
''
|
||||
substituteInPlace augeas/ffi.py \
|
||||
|
||||
@@ -48,7 +48,7 @@ buildPythonPackage rec {
|
||||
"-DOPENCOLLADA_LIBRARY_DIR=${opencollada}/lib/opencollada"
|
||||
"-DSWIG_EXECUTABLE=${swig}/bin/swig"
|
||||
"-DLIBXML2_INCLUDE_DIR=${libxml2.dev}/include/libxml2"
|
||||
"-DLIBXML2_LIBRARIES=${libxml2.out}/lib/${if stdenv.isDarwin then "libxml2.dylib" else "libxml2.so"}"
|
||||
"-DLIBXML2_LIBRARIES=${libxml2.out}/lib/libxml2${stdenv.hostPlatform.extensions.sharedLibrary}"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
, stdenv
|
||||
}:
|
||||
|
||||
let
|
||||
node-api-lib = (if stdenv.isDarwin then "libquery_engine.dylib" else "libquery_engine.so");
|
||||
in rustPlatform.buildRustPackage rec {
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "prisma-engines";
|
||||
version = "3.2.0";
|
||||
|
||||
@@ -47,7 +45,7 @@ in rustPlatform.buildRustPackage rec {
|
||||
cargoBuildFlags = "-p query-engine -p query-engine-node-api -p migration-engine-cli -p introspection-core -p prisma-fmt";
|
||||
|
||||
postInstall = ''
|
||||
mv $out/lib/${node-api-lib} $out/lib/libquery_engine.node
|
||||
mv $out/lib/libquery_engine${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/libquery_engine.node
|
||||
'';
|
||||
|
||||
# Tests are long to compile
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "postman";
|
||||
version = "8.10.0";
|
||||
version = "9.0.4";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://dl.pstmn.io/download/version/${version}/linux64";
|
||||
sha256 = "05f3eaa229483a7e1f698e6e2ea2031d37687de540d4fad05ce677ac216db24d";
|
||||
sha256 = "9OX1rSNWq2YJQBCt64iE4osZvfVajgEC2F28w7HSs3U=";
|
||||
name = "${pname}.tar.gz";
|
||||
};
|
||||
|
||||
@@ -74,7 +74,7 @@ stdenv.mkDerivation rec {
|
||||
rm $out/share/postman/Postman
|
||||
|
||||
mkdir -p $out/bin
|
||||
ln -s $out/share/postman/_Postman $out/bin/postman
|
||||
ln -s $out/share/postman/postman $out/bin/postman
|
||||
|
||||
mkdir -p $out/share/applications
|
||||
ln -s ${desktopItem}/share/applications/* $out/share/applications/
|
||||
@@ -88,8 +88,8 @@ stdenv.mkDerivation rec {
|
||||
|
||||
postFixup = ''
|
||||
pushd $out/share/postman
|
||||
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" _Postman
|
||||
for file in $(find . -type f \( -name \*.node -o -name _Postman -o -name \*.so\* \) ); do
|
||||
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" postman
|
||||
for file in $(find . -type f \( -name \*.node -o -name postman -o -name \*.so\* \) ); do
|
||||
ORIGIN=$(patchelf --print-rpath $file); \
|
||||
patchelf --set-rpath "${lib.makeLibraryPath buildInputs}:$ORIGIN" $file
|
||||
done
|
||||
@@ -101,6 +101,6 @@ stdenv.mkDerivation rec {
|
||||
description = "API Development Environment";
|
||||
license = licenses.postman;
|
||||
platforms = [ "x86_64-linux" ];
|
||||
maintainers = with maintainers; [ xurei evanjs ];
|
||||
maintainers = with maintainers; [ johnrichardrinehart evanjs ];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,6 +81,14 @@ stdenv.mkDerivation rec {
|
||||
|
||||
CONFIG_LFS y
|
||||
|
||||
# More features for modprobe.
|
||||
${lib.optionalString (!enableMinimal) ''
|
||||
CONFIG_FEATURE_MODPROBE_BLACKLIST y
|
||||
CONFIG_FEATURE_MODUTILS_ALIAS y
|
||||
CONFIG_FEATURE_MODUTILS_SYMBOLS y
|
||||
CONFIG_MODPROBE_SMALL n
|
||||
''}
|
||||
|
||||
${lib.optionalString enableStatic ''
|
||||
CONFIG_STATIC y
|
||||
''}
|
||||
|
||||
@@ -19,9 +19,11 @@ stdenv.mkDerivation rec {
|
||||
substituteInPlace libmultipath/Makefile \
|
||||
--replace /usr/include/libdevmapper.h ${lib.getDev lvm2}/include/libdevmapper.h
|
||||
|
||||
# systemd-udev-settle.service is deprecated.
|
||||
substituteInPlace multipathd/multipathd.service \
|
||||
--replace /sbin/modprobe ${lib.getBin kmod}/sbin/modprobe \
|
||||
--replace /sbin/multipathd "$out/bin/multipathd"
|
||||
--replace /sbin/multipathd "$out/bin/multipathd" \
|
||||
--replace " systemd-udev-settle.service" ""
|
||||
|
||||
sed -i -re '
|
||||
s,^( *#define +DEFAULT_MULTIPATHDIR\>).*,\1 "'"$out/lib/multipath"'",
|
||||
|
||||
@@ -12,16 +12,16 @@
|
||||
# server, and the FHS userenv and corresponding NixOS module should
|
||||
# automatically pick up the changes.
|
||||
stdenv.mkDerivation rec {
|
||||
version = "1.24.3.5033-757abe6b4";
|
||||
version = "1.24.4.5081-e362dc1ee";
|
||||
pname = "plexmediaserver";
|
||||
|
||||
# Fetch the source
|
||||
src = if stdenv.hostPlatform.system == "aarch64-linux" then fetchurl {
|
||||
url = "https://downloads.plex.tv/plex-media-server-new/${version}/debian/plexmediaserver_${version}_arm64.deb";
|
||||
sha256 = "063llf34h6dbzrysm98xwwmv8fwyk8vsc3sj7dniy9j29wwygwdz";
|
||||
sha256 = "0q3s1qcr65rx2jbf9k0i38w5xvnzw1wcy13gvm0150ad2hqw358b";
|
||||
} else fetchurl {
|
||||
url = "https://downloads.plex.tv/plex-media-server-new/${version}/debian/plexmediaserver_${version}_amd64.deb";
|
||||
sha256 = "0cnv1i00xv7ls5yb9xlim4haal7bvn41p3zskbab85vwhffr9irx";
|
||||
sha256 = "17igy0lq7mjmrw5xq92b57np422x8hj6m8qzjri493yc6fw1cl1m";
|
||||
};
|
||||
|
||||
outputs = [ "out" "basedb" ];
|
||||
|
||||
@@ -1,36 +1,42 @@
|
||||
{ fetchurl, lib, stdenv, emacs, curl, check, bc }:
|
||||
{ lib
|
||||
, stdenv
|
||||
, fetchurl
|
||||
, bc
|
||||
, check
|
||||
, curl
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "recutils";
|
||||
version = "1.8";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://gnu/recutils/recutils-${version}.tar.gz";
|
||||
sha256 = "14xiln4immfsw8isnvwvq0h23f6z0wilpgsc4qzabnrzb5lsx3nz";
|
||||
url = "mirror://gnu/recutils/${pname}-${version}.tar.gz";
|
||||
hash = "sha256-346uaVk/26U+Jky/SyMH37ghIMCbb6sj4trVGomlsZM=";
|
||||
};
|
||||
|
||||
hardeningDisable = [ "format" ];
|
||||
|
||||
buildInputs = [ curl emacs ];
|
||||
buildInputs = [
|
||||
curl
|
||||
];
|
||||
|
||||
checkInputs = [ check bc ];
|
||||
checkInputs = [
|
||||
check
|
||||
bc
|
||||
];
|
||||
doCheck = true;
|
||||
|
||||
meta = {
|
||||
description = "Tools and libraries to access human-editable, text-based databases";
|
||||
|
||||
longDescription =
|
||||
'' GNU Recutils is a set of tools and libraries to access
|
||||
human-editable, text-based databases called recfiles. The data is
|
||||
stored as a sequence of records, each record containing an arbitrary
|
||||
number of named fields.
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://www.gnu.org/software/recutils/";
|
||||
|
||||
license = lib.licenses.gpl3Plus;
|
||||
|
||||
platforms = lib.platforms.all;
|
||||
maintainers = [ ];
|
||||
description = "Tools and libraries to access human-editable, text-based databases";
|
||||
longDescription = ''
|
||||
GNU Recutils is a set of tools and libraries to access human-editable,
|
||||
text-based databases called recfiles. The data is stored as a sequence of
|
||||
records, each record containing an arbitrary number of named fields.
|
||||
'';
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = with maintainers; [ AndersonTorres ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -520,6 +520,8 @@ with pkgs;
|
||||
tests = callPackages ../build-support/fetchfirefoxaddon/tests.nix { };
|
||||
};
|
||||
|
||||
fetchNextcloudApp = callPackage ../build-support/fetchnextcloudapp {};
|
||||
|
||||
# `fetchurl' downloads a file from the network.
|
||||
fetchurl = if stdenv.buildPlatform != stdenv.hostPlatform
|
||||
then buildPackages.fetchurl # No need to do special overrides twice,
|
||||
|
||||
Reference in New Issue
Block a user