From 2d324fc2426fd320dcd15326b830b50fc2949c55 Mon Sep 17 00:00:00 2001 From: Sandro Jäckel Date: Mon, 4 Dec 2023 22:05:25 +0100 Subject: nixos/archisteamfarm: don't use asf abbreviation for more clarity --- nixos/doc/manual/release-notes/rl-2405.section.md | 3 + nixos/modules/module-list.nix | 2 +- nixos/modules/services/games/archisteamfarm.nix | 272 ++++++++++++++++++++++ nixos/modules/services/games/asf.nix | 272 ---------------------- 4 files changed, 276 insertions(+), 273 deletions(-) create mode 100644 nixos/modules/services/games/archisteamfarm.nix delete mode 100644 nixos/modules/services/games/asf.nix (limited to 'nixos') diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md index f4434fd6b94ca..86d3da934dc44 100644 --- a/nixos/doc/manual/release-notes/rl-2405.section.md +++ b/nixos/doc/manual/release-notes/rl-2405.section.md @@ -121,6 +121,9 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m We have added a warning for services that are `after = [ "network-online.target" ]` but do not depend on it (e.g. using `wants`). +- `services.archisteamfarm` no longer uses the abbreviation `asf` for its state directory (`/var/lib/asf`), user and group (both `asf`). Instead the long name `archisteamfarm` is used. + Configurations with `system.stateVersion` 23.11 or earlier, default to the old stateDirectory until the 24.11 release and must either set the option explicitly or move the data to the new directory. + - `networking.iproute2.enable` now does not set `environment.etc."iproute2/rt_tables".text`. Setting `environment.etc."iproute2/{CONFIG_FILE_NAME}".text` will override the whole configuration file instead of appending it to the upstream configuration file. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 00e6240f531d5..7c06d67eb0389 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -506,7 +506,7 @@ ./services/editors/haste.nix ./services/editors/infinoted.nix ./services/finance/odoo.nix - ./services/games/asf.nix + ./services/games/archisteamfarm.nix ./services/games/crossfire-server.nix ./services/games/deliantra-server.nix ./services/games/factorio.nix diff --git a/nixos/modules/services/games/archisteamfarm.nix b/nixos/modules/services/games/archisteamfarm.nix new file mode 100644 index 0000000000000..98360a4b58dc2 --- /dev/null +++ b/nixos/modules/services/games/archisteamfarm.nix @@ -0,0 +1,272 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.archisteamfarm; + + format = pkgs.formats.json { }; + + configFile = format.generate "ASF.json" (cfg.settings // { + # we disable it because ASF cannot update itself anyways + # and nixos takes care of restarting the service + # is in theory not needed as this is already the default for default builds + UpdateChannel = 0; + Headless = true; + } // lib.optionalAttrs (cfg.ipcPasswordFile != null) { + IPCPassword = "#ipcPassword#"; + }); + + ipc-config = format.generate "IPC.config" cfg.ipcSettings; + + mkBot = n: c: + format.generate "${n}.json" (c.settings // { + SteamLogin = if c.username == "" then n else c.username; + SteamPassword = c.passwordFile; + # sets the password format to file (https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Security#file) + PasswordFormat = 4; + Enabled = c.enabled; + }); +in +{ + options.services.archisteamfarm = { + enable = mkOption { + type = types.bool; + description = lib.mdDoc '' + If enabled, starts the ArchisSteamFarm service. + For configuring the SteamGuard token you will need to use the web-ui, which is enabled by default over on 127.0.0.1:1242. + You cannot configure ASF in any way outside of nix, since all the config files get wiped on restart and replaced with the programnatically set ones by nix. + ''; + default = false; + }; + + web-ui = mkOption { + type = types.submodule { + options = { + enable = mkEnableOption "" // { + description = lib.mdDoc "Whether to start the web-ui. This is the preferred way of configuring things such as the steam guard token."; + }; + + package = mkPackageOption pkgs [ "ArchiSteamFarm" "ui" ] { + extraDescription = '' + ::: {.note} + Contents must be in lib/dist + ::: + ''; + }; + }; + }; + default = { + enable = true; + }; + example = { + enable = false; + }; + description = lib.mdDoc "The Web-UI hosted on 127.0.0.1:1242."; + }; + + package = mkPackageOption pkgs "ArchiSteamFarm" { + extraDescription = '' + ::: {.warning} + Should always be the latest version, for security reasons, + since this module uses very new features and to not get out of sync with the Steam API. + ::: + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/archisteamfarm"; + description = lib.mdDoc '' + The ASF home directory used to store all data. + If left as the default value this directory will automatically be created before the ASF server starts, otherwise the sysadmin is responsible for ensuring the directory exists with appropriate ownership and permissions.''; + }; + + settings = mkOption { + type = format.type; + description = lib.mdDoc '' + The ASF.json file, all the options are documented [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#global-config). + Do note that `AutoRestart` and `UpdateChannel` is always to `false` respectively `0` because NixOS takes care of updating everything. + `Headless` is also always set to `true` because there is no way to provide inputs via a systemd service. + You should try to keep ASF up to date since upstream does not provide support for anything but the latest version and you're exposing yourself to all kinds of issues - as is outlined [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#updateperiod). + ''; + example = { + Statistics = false; + }; + default = { }; + }; + + ipcPasswordFile = mkOption { + type = types.nullOr types.path; + default = null; + description = lib.mdDoc "Path to a file containing the password. The file must be readable by the `archisteamfarm` user/group."; + }; + + ipcSettings = mkOption { + type = format.type; + description = lib.mdDoc '' + Settings to write to IPC.config. + All options can be found [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/IPC#custom-configuration). + ''; + example = { + Kestrel = { + Endpoints = { + HTTP = { + Url = "http://*:1242"; + }; + }; + }; + }; + default = { }; + }; + + bots = mkOption { + type = types.attrsOf (types.submodule { + options = { + username = mkOption { + type = types.str; + description = lib.mdDoc "Name of the user to log in. Default is attribute name."; + default = ""; + }; + passwordFile = mkOption { + type = types.path; + description = lib.mdDoc "Path to a file containing the password. The file must be readable by the `archisteamfarm` user/group."; + }; + enabled = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc "Whether to enable the bot on startup."; + }; + settings = mkOption { + type = types.attrs; + description = lib.mdDoc '' + Additional settings that are documented [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config). + ''; + default = { }; + }; + }; + }); + description = lib.mdDoc '' + Bots name and configuration. + ''; + example = { + exampleBot = { + username = "alice"; + passwordFile = "/var/lib/archisteamfarm/secrets/password"; + settings = { SteamParentalCode = "1234"; }; + }; + }; + default = { }; + }; + }; + + config = mkIf cfg.enable { + # TODO: drop with 24.11 + services.archisteamfarm.dataDir = lib.mkIf (lib.versionAtLeast config.system.stateVersion "24.05") (lib.mkDefault "/var/lib/asf"); + + users = { + users.archisteamfarm = { + home = cfg.dataDir; + isSystemUser = true; + group = "archisteamfarm"; + description = "Archis-Steam-Farm service user"; + }; + groups.archisteamfarm = { }; + }; + + systemd.services = { + archisteamfarm = { + description = "Archis-Steam-Farm Service"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = mkMerge [ + (mkIf (lib.hasPrefix "/var/lib/" cfg.dataDir) { + StateDirectory = lib.last (lib.splitString "/" cfg.dataDir); + StateDirectoryMode = "700"; + }) + { + User = "archisteamfarm"; + Group = "archisteamfarm"; + WorkingDirectory = cfg.dataDir; + Type = "simple"; + ExecStart = "${lib.getExe cfg.package} --no-restart --process-required --service --system-required --path ${cfg.dataDir}"; + Restart = "always"; + + # copied from the default systemd service at + # https://github.com/JustArchiNET/ArchiSteamFarm/blob/main/ArchiSteamFarm/overlay/variant-base/linux/ArchiSteamFarm%40.service + CapabilityBoundingSet = ""; + DevicePolicy = "closed"; + LockPersonality = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateIPC = true; + PrivateMounts = true; + PrivateTmp = true; # instead of rw /tmp + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK AF_UNIX"; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SecureBits = "noroot-locked"; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@privileged" ]; + UMask = "0077"; + } + ]; + + preStart = + let + createBotsScript = pkgs.runCommandLocal "ASF-bots" { } '' + mkdir -p $out + # clean potential removed bots + rm -rf $out/*.json + for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=","; + set -- $i + ln -fs $2 $out/$1 + done + ''; + replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret"; + in + '' + mkdir -p config + + cp --no-preserve=mode ${configFile} config/ASF.json + + ${optionalString (cfg.ipcPasswordFile != null) '' + ${replaceSecretBin} '#ipcPassword#' '${cfg.ipcPasswordFile}' config/ASF.json + ''} + + ${optionalString (cfg.ipcSettings != {}) '' + ln -fs ${ipc-config} config/IPC.config + ''} + + ${optionalString (cfg.ipcSettings != {}) '' + ln -fs ${createBotsScript}/* config/ + ''} + + rm -f www + ${optionalString cfg.web-ui.enable '' + ln -s ${cfg.web-ui.package}/ www + ''} + ''; + }; + }; + }; + + meta = { + buildDocsInSandbox = false; + maintainers = with maintainers; [ lom SuperSandro2000 ]; + }; +} diff --git a/nixos/modules/services/games/asf.nix b/nixos/modules/services/games/asf.nix deleted file mode 100644 index 27d174d6726ba..0000000000000 --- a/nixos/modules/services/games/asf.nix +++ /dev/null @@ -1,272 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.services.archisteamfarm; - - format = pkgs.formats.json { }; - - asf-config = format.generate "ASF.json" (cfg.settings // { - # we disable it because ASF cannot update itself anyways - # and nixos takes care of restarting the service - # is in theory not needed as this is already the default for default builds - UpdateChannel = 0; - Headless = true; - } // lib.optionalAttrs (cfg.ipcPasswordFile != null) { - IPCPassword = "#ipcPassword#"; - }); - - ipc-config = format.generate "IPC.config" cfg.ipcSettings; - - mkBot = n: c: - format.generate "${n}.json" (c.settings // { - SteamLogin = if c.username == "" then n else c.username; - SteamPassword = c.passwordFile; - # sets the password format to file (https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Security#file) - PasswordFormat = 4; - Enabled = c.enabled; - }); -in -{ - options.services.archisteamfarm = { - enable = mkOption { - type = types.bool; - description = lib.mdDoc '' - If enabled, starts the ArchisSteamFarm service. - For configuring the SteamGuard token you will need to use the web-ui, which is enabled by default over on 127.0.0.1:1242. - You cannot configure ASF in any way outside of nix, since all the config files get wiped on restart and replaced with the programnatically set ones by nix. - ''; - default = false; - }; - - web-ui = mkOption { - type = types.submodule { - options = { - enable = mkEnableOption "" // { - description = lib.mdDoc "Whether to start the web-ui. This is the preferred way of configuring things such as the steam guard token."; - }; - - package = mkPackageOption pkgs [ "ArchiSteamFarm" "ui" ] { - extraDescription = '' - ::: {.note} - Contents must be in lib/dist - ::: - ''; - }; - }; - }; - default = { - enable = true; - }; - example = { - enable = false; - }; - description = lib.mdDoc "The Web-UI hosted on 127.0.0.1:1242."; - }; - - package = mkPackageOption pkgs "ArchiSteamFarm" { - extraDescription = '' - ::: {.warning} - Should always be the latest version, for security reasons, - since this module uses very new features and to not get out of sync with the Steam API. - ::: - ''; - }; - - dataDir = mkOption { - type = types.path; - default = "/var/lib/asf"; - description = lib.mdDoc '' - The ASF home directory used to store all data. - If left as the default value this directory will automatically be created before the ASF server starts, otherwise the sysadmin is responsible for ensuring the directory exists with appropriate ownership and permissions.''; - }; - - settings = mkOption { - type = format.type; - description = lib.mdDoc '' - The ASF.json file, all the options are documented [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#global-config). - Do note that `AutoRestart` and `UpdateChannel` is always to `false` respectively `0` because NixOS takes care of updating everything. - `Headless` is also always set to `true` because there is no way to provide inputs via a systemd service. - You should try to keep ASF up to date since upstream does not provide support for anything but the latest version and you're exposing yourself to all kinds of issues - as is outlined [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#updateperiod). - ''; - example = { - Statistics = false; - }; - default = { }; - }; - - ipcPasswordFile = mkOption { - type = types.nullOr types.path; - default = null; - description = lib.mdDoc "Path to a file containing the password. The file must be readable by the `asf` user/group."; - }; - - ipcSettings = mkOption { - type = format.type; - description = lib.mdDoc '' - Settings to write to IPC.config. - All options can be found [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/IPC#custom-configuration). - ''; - example = { - Kestrel = { - Endpoints = { - HTTP = { - Url = "http://*:1242"; - }; - }; - }; - }; - default = { }; - }; - - bots = mkOption { - type = types.attrsOf (types.submodule { - options = { - username = mkOption { - type = types.str; - description = lib.mdDoc "Name of the user to log in. Default is attribute name."; - default = ""; - }; - passwordFile = mkOption { - type = types.path; - description = lib.mdDoc "Path to a file containing the password. The file must be readable by the `asf` user/group."; - }; - enabled = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc "Whether to enable the bot on startup."; - }; - settings = mkOption { - type = types.attrs; - description = lib.mdDoc '' - Additional settings that are documented [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config). - ''; - default = { }; - }; - }; - }); - description = lib.mdDoc '' - Bots name and configuration. - ''; - example = { - exampleBot = { - username = "alice"; - passwordFile = "/var/lib/asf/secrets/password"; - settings = { SteamParentalCode = "1234"; }; - }; - }; - default = { }; - }; - }; - - config = mkIf cfg.enable { - - users = { - users.asf = { - home = cfg.dataDir; - isSystemUser = true; - group = "asf"; - description = "Archis-Steam-Farm service user"; - }; - groups.asf = { }; - }; - - systemd.services = { - asf = { - description = "Archis-Steam-Farm Service"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = mkMerge [ - (mkIf (cfg.dataDir == "/var/lib/asf") { - StateDirectory = "asf"; - StateDirectoryMode = "700"; - }) - { - User = "asf"; - Group = "asf"; - WorkingDirectory = cfg.dataDir; - Type = "simple"; - ExecStart = "${lib.getExe cfg.package} --no-restart --process-required --service --system-required --path ${cfg.dataDir}"; - Restart = "always"; - - # copied from the default systemd service at - # https://github.com/JustArchiNET/ArchiSteamFarm/blob/main/ArchiSteamFarm/overlay/variant-base/linux/ArchiSteamFarm%40.service - CapabilityBoundingSet = ""; - DevicePolicy = "closed"; - LockPersonality = true; - NoNewPrivileges = true; - PrivateDevices = true; - PrivateIPC = true; - PrivateMounts = true; - PrivateTmp = true; # instead of rw /tmp - PrivateUsers = true; - ProcSubset = "pid"; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectProc = "invisible"; - ProtectSystem = "strict"; - RemoveIPC = true; - RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK AF_UNIX"; - RestrictNamespaces = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - SystemCallArchitectures = "native"; - UMask = "0077"; - - # we luckily already have systemd v247+ - SecureBits = "noroot-locked"; - SystemCallFilter = [ "@system-service" "~@privileged" ]; - } - ]; - - preStart = - let - createBotsScript = pkgs.runCommandLocal "ASF-bots" { } '' - mkdir -p $out - # clean potential removed bots - rm -rf $out/*.json - for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=","; - set -- $i - ln -fs $2 $out/$1 - done - ''; - replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret"; - in - '' - mkdir -p config - - cp --no-preserve=mode ${asf-config} config/ASF.json - - ${optionalString (cfg.ipcPasswordFile != null) '' - ${replaceSecretBin} '#ipcPassword#' '${cfg.ipcPasswordFile}' config/ASF.json - ''} - - ${optionalString (cfg.ipcSettings != {}) '' - ln -fs ${ipc-config} config/IPC.config - ''} - - ${optionalString (cfg.ipcSettings != {}) '' - ln -fs ${createBotsScript}/* config/ - ''} - - rm -f www - ${optionalString cfg.web-ui.enable '' - ln -s ${cfg.web-ui.package}/ www - ''} - ''; - }; - }; - }; - - meta = { - buildDocsInSandbox = false; - maintainers = with maintainers; [ lom SuperSandro2000 ]; - }; -} -- cgit 1.4.1 From 6d1d912716d73aa497727802caba6ba6783e5c3a Mon Sep 17 00:00:00 2001 From: Sandro Jäckel Date: Sun, 21 Jan 2024 01:54:35 +0100 Subject: nixos/archisteamfarm: drop with lib --- nixos/modules/services/games/archisteamfarm.nix | 66 ++++++++++++------------- 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'nixos') diff --git a/nixos/modules/services/games/archisteamfarm.nix b/nixos/modules/services/games/archisteamfarm.nix index 98360a4b58dc2..293e341bef385 100644 --- a/nixos/modules/services/games/archisteamfarm.nix +++ b/nixos/modules/services/games/archisteamfarm.nix @@ -1,7 +1,5 @@ { config, lib, pkgs, ... }: -with lib; - let cfg = config.services.archisteamfarm; @@ -30,8 +28,8 @@ let in { options.services.archisteamfarm = { - enable = mkOption { - type = types.bool; + enable = lib.mkOption { + type = lib.types.bool; description = lib.mdDoc '' If enabled, starts the ArchisSteamFarm service. For configuring the SteamGuard token you will need to use the web-ui, which is enabled by default over on 127.0.0.1:1242. @@ -40,14 +38,14 @@ in default = false; }; - web-ui = mkOption { - type = types.submodule { + web-ui = lib.mkOption { + type = lib.types.submodule { options = { - enable = mkEnableOption "" // { + enable = lib.mkEnableOption "" // { description = lib.mdDoc "Whether to start the web-ui. This is the preferred way of configuring things such as the steam guard token."; }; - package = mkPackageOption pkgs [ "ArchiSteamFarm" "ui" ] { + package = lib.mkPackageOption pkgs [ "ArchiSteamFarm" "ui" ] { extraDescription = '' ::: {.note} Contents must be in lib/dist @@ -65,7 +63,7 @@ in description = lib.mdDoc "The Web-UI hosted on 127.0.0.1:1242."; }; - package = mkPackageOption pkgs "ArchiSteamFarm" { + package = lib.mkPackageOption pkgs "ArchiSteamFarm" { extraDescription = '' ::: {.warning} Should always be the latest version, for security reasons, @@ -74,15 +72,15 @@ in ''; }; - dataDir = mkOption { - type = types.path; + dataDir = lib.mkOption { + type = lib.types.path; default = "/var/lib/archisteamfarm"; description = lib.mdDoc '' The ASF home directory used to store all data. If left as the default value this directory will automatically be created before the ASF server starts, otherwise the sysadmin is responsible for ensuring the directory exists with appropriate ownership and permissions.''; }; - settings = mkOption { + settings = lib.mkOption { type = format.type; description = lib.mdDoc '' The ASF.json file, all the options are documented [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#global-config). @@ -96,13 +94,13 @@ in default = { }; }; - ipcPasswordFile = mkOption { - type = types.nullOr types.path; + ipcPasswordFile = lib.mkOption { + type = with lib.types; nullOr path; default = null; description = lib.mdDoc "Path to a file containing the password. The file must be readable by the `archisteamfarm` user/group."; }; - ipcSettings = mkOption { + ipcSettings = lib.mkOption { type = format.type; description = lib.mdDoc '' Settings to write to IPC.config. @@ -120,25 +118,25 @@ in default = { }; }; - bots = mkOption { - type = types.attrsOf (types.submodule { + bots = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { options = { - username = mkOption { - type = types.str; + username = lib.mkOption { + type = lib.types.str; description = lib.mdDoc "Name of the user to log in. Default is attribute name."; default = ""; }; - passwordFile = mkOption { - type = types.path; + passwordFile = lib.mkOption { + type = lib.types.path; description = lib.mdDoc "Path to a file containing the password. The file must be readable by the `archisteamfarm` user/group."; }; - enabled = mkOption { - type = types.bool; + enabled = lib.mkOption { + type = lib.types.bool; default = true; description = lib.mdDoc "Whether to enable the bot on startup."; }; - settings = mkOption { - type = types.attrs; + settings = lib.mkOption { + type = lib.types.attrs; description = lib.mdDoc '' Additional settings that are documented [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config). ''; @@ -160,7 +158,7 @@ in }; }; - config = mkIf cfg.enable { + config = lib.mkIf cfg.enable { # TODO: drop with 24.11 services.archisteamfarm.dataDir = lib.mkIf (lib.versionAtLeast config.system.stateVersion "24.05") (lib.mkDefault "/var/lib/asf"); @@ -180,8 +178,8 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - serviceConfig = mkMerge [ - (mkIf (lib.hasPrefix "/var/lib/" cfg.dataDir) { + serviceConfig = lib.mkMerge [ + (lib.mkIf (lib.hasPrefix "/var/lib/" cfg.dataDir) { StateDirectory = lib.last (lib.splitString "/" cfg.dataDir); StateDirectoryMode = "700"; }) @@ -232,7 +230,7 @@ in mkdir -p $out # clean potential removed bots rm -rf $out/*.json - for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=","; + for i in ${lib.concatStringsSep " " (map (x: "${lib.getName x},${x}") (lib.mapAttrsToList mkBot cfg.bots))}; do IFS=","; set -- $i ln -fs $2 $out/$1 done @@ -244,20 +242,20 @@ in cp --no-preserve=mode ${configFile} config/ASF.json - ${optionalString (cfg.ipcPasswordFile != null) '' + ${lib.optionalString (cfg.ipcPasswordFile != null) '' ${replaceSecretBin} '#ipcPassword#' '${cfg.ipcPasswordFile}' config/ASF.json ''} - ${optionalString (cfg.ipcSettings != {}) '' + ${lib.optionalString (cfg.ipcSettings != {}) '' ln -fs ${ipc-config} config/IPC.config ''} - ${optionalString (cfg.ipcSettings != {}) '' + ${lib.optionalString (cfg.ipcSettings != {}) '' ln -fs ${createBotsScript}/* config/ ''} rm -f www - ${optionalString cfg.web-ui.enable '' + ${lib.optionalString cfg.web-ui.enable '' ln -s ${cfg.web-ui.package}/ www ''} ''; @@ -267,6 +265,6 @@ in meta = { buildDocsInSandbox = false; - maintainers = with maintainers; [ lom SuperSandro2000 ]; + maintainers = with lib.maintainers; [ lom SuperSandro2000 ]; }; } -- cgit 1.4.1