secrets: define these by crawling the repo to decrease duplication
This commit is contained in:
parent
bf56200345
commit
fb427e55e8
|
@ -4,19 +4,7 @@
|
||||||
./fs.nix
|
./fs.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
sops.secrets.colin-passwd = {
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
sopsFile = ../../../secrets/desko/colin-passwd.bin;
|
|
||||||
format = "binary";
|
|
||||||
neededForUsers = true;
|
|
||||||
};
|
|
||||||
sops.secrets.duplicity_passphrase = {
|
|
||||||
sopsFile = ../../../secrets/desko/duplicity_passphrase.env.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets.nix_serve_privkey = {
|
|
||||||
sopsFile = ../../../secrets/desko/nix_serve_privkey.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.roles.build-machine.enable = true;
|
sane.roles.build-machine.enable = true;
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
|
|
|
@ -21,11 +21,7 @@
|
||||||
"stepmania"
|
"stepmania"
|
||||||
];
|
];
|
||||||
|
|
||||||
sops.secrets.colin-passwd = {
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
sopsFile = ../../../secrets/lappy/colin-passwd.bin;
|
|
||||||
format = "binary";
|
|
||||||
neededForUsers = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# default config: https://man.archlinux.org/man/snapper-configs.5
|
# default config: https://man.archlinux.org/man/snapper-configs.5
|
||||||
# defaults to something like:
|
# defaults to something like:
|
||||||
|
|
|
@ -15,11 +15,7 @@
|
||||||
users.users.colin.initialPassword = "147147";
|
users.users.colin.initialPassword = "147147";
|
||||||
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
||||||
|
|
||||||
sops.secrets.colin-passwd = {
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
sopsFile = ../../../secrets/moby/colin-passwd.bin;
|
|
||||||
format = "binary";
|
|
||||||
neededForUsers = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.programs.web-browser.config = {
|
sane.programs.web-browser.config = {
|
||||||
# compromise impermanence for the sake of usability
|
# compromise impermanence for the sake of usability
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./net.nix
|
./net.nix
|
||||||
./secrets.nix
|
|
||||||
./services
|
./services
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sops.secrets."ddns_afraid" = {
|
|
||||||
sopsFile = ../../../secrets/servo/ddns_afraid.env.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."ddns_he" = {
|
|
||||||
sopsFile = ../../../secrets/servo/ddns_he.env.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."dovecot_passwd" = {
|
|
||||||
sopsFile = ../../../secrets/servo/dovecot_passwd.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."duplicity_passphrase" = {
|
|
||||||
sopsFile = ../../../secrets/servo/duplicity_passphrase.env.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."freshrss_passwd" = {
|
|
||||||
sopsFile = ../../../secrets/servo/freshrss_passwd.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."matrix_synapse_secrets" = {
|
|
||||||
sopsFile = ../../../secrets/servo/matrix_synapse_secrets.yaml.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."mautrix_signal_env" = {
|
|
||||||
sopsFile = ../../../secrets/servo/mautrix_signal_env.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."mediawiki_pw" = {
|
|
||||||
sopsFile = ../../../secrets/servo/mediawiki_pw.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."nix_serve_privkey" = {
|
|
||||||
sopsFile = ../../../secrets/servo/nix_serve_privkey.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."pleroma_secrets" = {
|
|
||||||
sopsFile = ../../../secrets/servo/pleroma_secrets.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."wg_ovpns_privkey" = {
|
|
||||||
sopsFile = ../../../secrets/servo/wg_ovpns_privkey.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@ lib.mkIf false
|
||||||
systemd.services.ddns-afraid = {
|
systemd.services.ddns-afraid = {
|
||||||
description = "update dynamic DNS entries for freedns.afraid.org";
|
description = "update dynamic DNS entries for freedns.afraid.org";
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
EnvironmentFile = config.sops.secrets.ddns_afraid.path;
|
EnvironmentFile = config.sops.secrets."ddns_afraid.env".path;
|
||||||
# TODO: ProtectSystem = "strict";
|
# TODO: ProtectSystem = "strict";
|
||||||
# TODO: ProtectHome = "full";
|
# TODO: ProtectHome = "full";
|
||||||
# TODO: PrivateTmp = true;
|
# TODO: PrivateTmp = true;
|
||||||
|
|
|
@ -6,7 +6,7 @@ lib.mkIf false
|
||||||
systemd.services.ddns-he = {
|
systemd.services.ddns-he = {
|
||||||
description = "update dynamic DNS entries for HurricaneElectric";
|
description = "update dynamic DNS entries for HurricaneElectric";
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
EnvironmentFile = config.sops.secrets.ddns_he.path;
|
EnvironmentFile = config.sops.secrets."ddns_he.env".path;
|
||||||
# TODO: ProtectSystem = "strict";
|
# TODO: ProtectSystem = "strict";
|
||||||
# TODO: ProtectHome = "full";
|
# TODO: ProtectHome = "full";
|
||||||
# TODO: PrivateTmp = true;
|
# TODO: PrivateTmp = true;
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
services.matrix-synapse.settings.registrations_require_3pid = [ "email" ];
|
services.matrix-synapse.settings.registrations_require_3pid = [ "email" ];
|
||||||
|
|
||||||
services.matrix-synapse.extraConfigFiles = [
|
services.matrix-synapse.extraConfigFiles = [
|
||||||
config.sops.secrets.matrix_synapse_secrets.path
|
config.sops.secrets."matrix_synapse_secrets.yaml".path
|
||||||
];
|
];
|
||||||
|
|
||||||
# services.matrix-synapse.extraConfigFiles = [builtins.toFile "matrix-synapse-extra-config" ''
|
# services.matrix-synapse.extraConfigFiles = [builtins.toFile "matrix-synapse-extra-config" ''
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
sops.secrets."matrix_synapse_secrets" = {
|
sops.secrets."matrix_synapse_secrets.yaml" = {
|
||||||
owner = config.users.users.matrix-synapse.name;
|
owner = config.users.users.matrix-synapse.name;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,47 @@
|
||||||
{ config, ... }:
|
# SOPS configuration:
|
||||||
|
# docs: https://github.com/Mic92/sops-nix
|
||||||
|
#
|
||||||
|
# for each new user you want to edit sops files:
|
||||||
|
# create a private age key from ssh key:
|
||||||
|
# $ mkdir -p ~/.config/sops/age; ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt; chmod 600 ~/.config/sops/age/keys.txt
|
||||||
|
# if the private key was password protected, then first decrypt it:
|
||||||
|
# $ cp ~/.ssh/id_ed25519 /tmp/id_ed25519
|
||||||
|
# $ ssh-keygen -p -N "" -f /tmp/id_ed25519
|
||||||
|
#
|
||||||
|
# for each user you want to decrypt secrets:
|
||||||
|
# $ cat ~/.ssh/id_ed25519.pub | ssh-to-age
|
||||||
|
# add the result to .sops.yaml
|
||||||
|
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
|
||||||
|
#
|
||||||
|
# for each host you want to decrypt secrets:
|
||||||
|
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
|
||||||
|
# add the result to .sops.yaml
|
||||||
|
# $ sops updatekeys secrets/example.yaml
|
||||||
|
#
|
||||||
|
# to create a new secret:
|
||||||
|
# $ sops secrets/example.yaml
|
||||||
|
# control access below (sops.secret.<x>.owner = ...)
|
||||||
|
#
|
||||||
|
# to read a secret:
|
||||||
|
# $ cat /run/secrets/example_key
|
||||||
|
|
||||||
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib.strings) hasSuffix removeSuffix;
|
||||||
|
secretsForHost = host: sane-lib.joinAttrsets (
|
||||||
|
map
|
||||||
|
(path: lib.optionalAttrs (hasSuffix ".bin" path) (sane-lib.nameValueToAttrs {
|
||||||
|
name = removeSuffix ".bin" path;
|
||||||
|
value = {
|
||||||
|
sopsFile = ../../secrets/${host}/${path};
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
}))
|
||||||
|
(sane-lib.enumerateFilePaths ../../secrets/${host})
|
||||||
|
);
|
||||||
|
in
|
||||||
{
|
{
|
||||||
# SOPS configuration:
|
|
||||||
# docs: https://github.com/Mic92/sops-nix
|
|
||||||
#
|
|
||||||
# for each new user you want to edit sops files:
|
|
||||||
# create a private age key from ssh key:
|
|
||||||
# $ mkdir -p ~/.config/sops/age; ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt; chmod 600 ~/.config/sops/age/keys.txt
|
|
||||||
# if the private key was password protected, then first decrypt it:
|
|
||||||
# $ cp ~/.ssh/id_ed25519 /tmp/id_ed25519
|
|
||||||
# $ ssh-keygen -p -N "" -f /tmp/id_ed25519
|
|
||||||
#
|
|
||||||
# for each user you want to decrypt secrets:
|
|
||||||
# $ cat ~/.ssh/id_ed25519.pub | ssh-to-age
|
|
||||||
# add the result to .sops.yaml
|
|
||||||
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
|
|
||||||
#
|
|
||||||
# for each host you want to decrypt secrets:
|
|
||||||
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
|
|
||||||
# add the result to .sops.yaml
|
|
||||||
# $ sops updatekeys secrets/example.yaml
|
|
||||||
#
|
|
||||||
# to create a new secret:
|
|
||||||
# $ sops secrets/example.yaml
|
|
||||||
# control access below (sops.secret.<x>.owner = ...)
|
|
||||||
#
|
|
||||||
# to read a secret:
|
|
||||||
# $ cat /run/secrets/example_key
|
|
||||||
|
|
||||||
# sops.age.sshKeyPaths = [ "/home/colin/.ssh/id_ed25519_dec" ];
|
# sops.age.sshKeyPaths = [ "/home/colin/.ssh/id_ed25519_dec" ];
|
||||||
sops.gnupg.sshKeyPaths = []; # disable RSA key import
|
sops.gnupg.sshKeyPaths = []; # disable RSA key import
|
||||||
|
@ -41,107 +56,15 @@
|
||||||
# };
|
# };
|
||||||
# sops.secrets."myservice/my_subdir/my_secret" = {};
|
# sops.secrets."myservice/my_subdir/my_secret" = {};
|
||||||
|
|
||||||
## secrets exposed to all hosts
|
sops.secrets = lib.mkMerge [
|
||||||
# TODO: glob these?
|
(secretsForHost "common")
|
||||||
|
(secretsForHost config.networking.hostName)
|
||||||
sops.secrets."jackett_apikey" = {
|
{
|
||||||
sopsFile = ../../secrets/common/jackett_apikey.bin;
|
"jackett_apikey".owner = config.users.users.colin.name;
|
||||||
format = "binary";
|
"mx-sanebot-env".owner = config.users.users.colin.name;
|
||||||
owner = config.users.users.colin.name;
|
"snippets".owner = config.users.users.colin.name;
|
||||||
};
|
}
|
||||||
sops.secrets."mx-sanebot-env" = {
|
];
|
||||||
sopsFile = ../../secrets/common/mx-sanebot-env.bin;
|
|
||||||
format = "binary";
|
|
||||||
owner = config.users.users.colin.name;
|
|
||||||
};
|
|
||||||
sops.secrets."router_passwd" = {
|
|
||||||
sopsFile = ../../secrets/common/router_passwd.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."transmission_passwd" = {
|
|
||||||
sopsFile = ../../secrets/common/transmission_passwd.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."wg_ovpnd_us_privkey" = {
|
|
||||||
sopsFile = ../../secrets/common/wg/ovpnd_us_privkey.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."wg_ovpnd_us-atl_privkey" = {
|
|
||||||
sopsFile = ../../secrets/common/wg/ovpnd_us-atl_privkey.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."wg_ovpnd_us-mi_privkey" = {
|
|
||||||
sopsFile = ../../secrets/common/wg/ovpnd_us-mi_privkey.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."wg_ovpnd_ukr_privkey" = {
|
|
||||||
sopsFile = ../../secrets/common/wg/ovpnd_ukr_privkey.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."snippets" = {
|
|
||||||
sopsFile = ../../secrets/common/snippets.bin;
|
|
||||||
format = "binary";
|
|
||||||
owner = config.users.users.colin.name;
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."bt/car" = {
|
|
||||||
sopsFile = ../../secrets/common/bt/car.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."bt/earbuds" = {
|
|
||||||
sopsFile = ../../secrets/common/bt/earbuds.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."bt/portable-speaker" = {
|
|
||||||
sopsFile = ../../secrets/common/bt/portable-speaker.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."iwd/calyx-roomie.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/calyx-roomie.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/community-university.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/community-university.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/friend-libertarian-dod.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/friend-libertarian-dod.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/friend-rationalist-empathist.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/friend-rationalist-empathist.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/home-shared.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/home-shared.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/makespace-south.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/makespace-south.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/archive-2023-02-home-bedroom.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/archive/2023-02-home-bedroom.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/archive-2023-02-home-shared-24G.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/archive/2023-02-home-shared-24G.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/archive-2023-02-home-shared.psk" = {
|
|
||||||
sopsFile = ../../secrets/common/net/archive/2023-02-home-shared.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/iphone" = {
|
|
||||||
sopsFile = ../../secrets/common/net/iphone.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
sops.secrets."iwd/parents" = {
|
|
||||||
sopsFile = ../../secrets/common/net/parents.psk.bin;
|
|
||||||
format = "binary";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ let
|
||||||
def-ovpn = name: { endpoint, publicKey, address }: {
|
def-ovpn = name: { endpoint, publicKey, address }: {
|
||||||
networking.wg-quick.interfaces."ovpnd-${name}" = {
|
networking.wg-quick.interfaces."ovpnd-${name}" = {
|
||||||
inherit address;
|
inherit address;
|
||||||
privateKeyFile = config.sops.secrets."wg_ovpnd_${name}_privkey".path;
|
privateKeyFile = config.sops.secrets."wg/ovpnd_${name}_privkey".path;
|
||||||
dns = [
|
dns = [
|
||||||
"46.227.67.134"
|
"46.227.67.134"
|
||||||
"192.165.9.158"
|
"192.165.9.158"
|
||||||
|
|
|
@ -29,7 +29,7 @@ in
|
||||||
# web-created keys are allowed to delete files, which you probably don't want for an incremental backup program
|
# web-created keys are allowed to delete files, which you probably don't want for an incremental backup program
|
||||||
# you need to create a new application key from the web in order to first get a key which can create new keys (use env vars in the above command)
|
# you need to create a new application key from the web in order to first get a key which can create new keys (use env vars in the above command)
|
||||||
# TODO: s/duplicity_passphrase/duplicity_env/
|
# TODO: s/duplicity_passphrase/duplicity_env/
|
||||||
services.duplicity.secretFile = config.sops.secrets.duplicity_passphrase.path;
|
services.duplicity.secretFile = config.sops.secrets."duplicity_passphrase.env".path;
|
||||||
# NB: manually trigger with `systemctl start duplicity`
|
# NB: manually trigger with `systemctl start duplicity`
|
||||||
services.duplicity.frequency = "daily";
|
services.duplicity.frequency = "daily";
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
{ lib, ... }:
|
{ lib, sane-lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (builtins) concatLists concatStringsSep foldl' fromJSON map readDir readFile;
|
inherit (builtins) concatLists concatStringsSep foldl' fromJSON map readDir readFile;
|
||||||
inherit (lib) hasSuffix listToAttrs mapAttrsToList removeSuffix splitString;
|
inherit (lib) hasSuffix listToAttrs mapAttrsToList removeSuffix splitString;
|
||||||
|
inherit (sane-lib) enumerateFilePaths;
|
||||||
|
|
||||||
# given a path to a .json file relative to sources, construct the best feed object we can.
|
# given a path to a .json file relative to sources, construct the best feed object we can.
|
||||||
# the .json file could be empty, in which case we make assumptions about the feed based
|
# the .json file could be empty, in which case we make assumptions about the feed based
|
||||||
|
@ -32,20 +33,5 @@ let
|
||||||
fromJSON as-str;
|
fromJSON as-str;
|
||||||
|
|
||||||
sources = enumerateFilePaths ./sources;
|
sources = enumerateFilePaths ./sources;
|
||||||
|
|
||||||
# like `lib.listFilesRecursive` but does not mangle paths.
|
|
||||||
# Type: enumerateFilePaths :: path -> [String]
|
|
||||||
enumerateFilePaths = base:
|
|
||||||
concatLists (
|
|
||||||
mapAttrsToList
|
|
||||||
(name: type:
|
|
||||||
if type == "directory" then
|
|
||||||
# enumerate this directory and then prefix each result with the directory's name
|
|
||||||
map (e: "${name}/${e}") (enumerateFilePaths (base + "/${name}"))
|
|
||||||
else
|
|
||||||
[ name ]
|
|
||||||
)
|
|
||||||
(readDir base)
|
|
||||||
);
|
|
||||||
in
|
in
|
||||||
listToAttrs (map feedFromSourcePath sources)
|
listToAttrs (map feedFromSourcePath sources)
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
./users.nix
|
./users.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
_module.args = {
|
_module.args = rec {
|
||||||
sane-lib = import ./lib { inherit lib; };
|
sane-lib = import ./lib { inherit lib; };
|
||||||
sane-data = import ./data { inherit lib; };
|
sane-data = import ./data { inherit lib sane-lib; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,5 +72,22 @@ sane-lib = rec {
|
||||||
inherit path value;
|
inherit path value;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
# like `lib.listFilesRecursive` but does not mangle paths.
|
||||||
|
#
|
||||||
|
# Type: enumerateFilePaths :: path -> [String]
|
||||||
|
enumerateFilePaths = base:
|
||||||
|
builtins.concatLists (
|
||||||
|
lib.mapAttrsToList
|
||||||
|
(name: type:
|
||||||
|
if type == "directory" then
|
||||||
|
# enumerate this directory and then prefix each result with the directory's name
|
||||||
|
builtins.map (e: "${name}/${e}") (enumerateFilePaths (base + "/${name}"))
|
||||||
|
else
|
||||||
|
[ name ]
|
||||||
|
)
|
||||||
|
(builtins.readDir base)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
in sane-lib
|
in sane-lib
|
||||||
|
|
Loading…
Reference in New Issue
Block a user