List of strings from files in folder

Is there a possibility to have files from a folder added as a list of strings in nix? In the concrete example I want to use this for for importing certificates. So at the moment my nix file looks something like this

{ pkgs, config, ... }:
{
  security.pki.certificates = [
    ''
    -----BEGIN CERTIFICATE-----
    ....
    ''
    ''
    -----BEGIN CERTIFICATE-----
    ....
    ''
  ];
}

However I would prefer something like this

{ pkgs, config, ... }:
{
  security.pki.certificates = [
    ''
    -----BEGIN CERTIFICATE-----
    ....
    ''
  ] ++ stringsFromList ./certs;
}

Is there a possibility to achive something similar or what would your recommendation be?

I haven’t tested it, but I think that you could do something like this:

{lib, ...}: let
  files = builtins.attrNames (builtins.readDir ./certs);
  certs = builtins.filter (f: builtins.match ".*\.pem" f != null) files;
  certPaths = map (v: lib.path.append ./certs "${v}") certs;
in {
  security.pki.certificateFiles = certPaths;
}

Expand the regex if your certificates have another extensions.

If you want to use security.pki.certificates then add security.pki.certificates = map (f: builtins.readFile f) certPaths;.

If you only have certificates in that folder, omit the filter and use files directly on the last map.

1 Like

Looks pretty cool. I still have the problem that certPaths (or lin.path.append i guess) resolves to absolute paths which results in a build error. But I will fiddle around with it more to see if I get it working and will report the progress. Thank you very much so far

Thank you very much. The solution was already pretty close. So my mistake was that I did not place my certs folder correctly (just one level too high which was causing the absolute path error).

One more tiny thing I had to fix was that the certPaths should in fact contain the string contents not the path to the file which could be fixed with the builtins.readFile.

The last addition I made was to add a condition that the build does not fail if on certs folder exists. This is what the result looks like now

let
  files = 
    if builtins.pathExists ./certs then
      builtins.attrNames (builtins.readDir ./certs)
    else
      [];
  certs = builtins.filter (f: builtins.match ".*\.pem" f != null) files;
  certContents = map (v: builtins.readFile (lib.path.append ./certs "${v}")) certs;
in
{
  security.pki.certificates = [
  ] ++ certContents
}