在 vhost.nix 中,我想在循环中添加用户,就像 httpd.virtualHosts 中的工作示例一样。
这是我在虚拟机中使用的
configuration.nix
:
# vm.nix
{ lib, config, ... }:
{
imports = [
./vhosts.nix
];
services.httpd.enable = true;
vhosts = {
"test.example.de" = {
customer = "web2";
phpuser = "web2www1";
};
"test2.example.de" = {
customer = "web3";
phpuser = "web3www1";
};
};
}
这是我的模块
vhost.nix
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.vhosts;
in
{
options.vhosts = lib.mkOption {
type = with lib.types; attrsOf (submodule ({domain, ... }: {
options = {
customer = mkOption {
type = str;
};
phpuser = mkOption {
type = str;
};
};
}));
};
config = {
services.httpd.virtualHosts = lib.mapAttrs (domain: cfg: {
documentRoot = "/srv/www/${cfg.customer}/${domain}";
}) cfg;
# how do I solve this in a loop like above ?
users.users.web2www1.isNormalUser = true;
users.users.web3www1.isNormalUser = true;
};
}
如何在像上面这样的循环中解决这个问题?
正如 Chris 指出的那样,在 Nix 中,不使用传统的命令式编程结构,如 for 循环。相反,采用函数式编程范例,特别是对列表或属性集进行操作的 map
、
fold
和
filter
等函数。您可以使用:
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.vhosts;
in
{
options.vhosts = lib.mkOption {
type = with lib.types; attrsOf (submodule ({domain, ... }: {
options = {
customer = mkOption {
type = str;
};
phpuser = mkOption {
type = str;
};
};
}));
};
config = {
services.httpd.virtualHosts = lib.mapAttrs (domain: cfg: {
documentRoot = "/srv/www/${cfg.customer}/${domain}";
}) cfg;
users.users = lib.foldl' (acc: domain: let
user = cfg.${domain}.phpuser;
in acc // { "${user}".isNormalUser = true; }
) {} (lib.attrNames cfg);
};
}
lib.foldl'
用于迭代
vhosts
属性集。对于
vhosts
中的每个域,它会提取
phpuser
并将
isNormalUser
设置为用户配置中的
true
。