Help with concatMap (loops?)

Hello,
I am trying hard to make a NFS config for my nix machine.

So far this is it:

{ config, pkgs, ... }:

let
  allowedIPs = [ ip1 ip2 ];
  discDir = "inner";
  nfsDir = "/srv/nfs/${discDir}";
  nfsPermissions = "rw,sync,anonuid=1000,anongid=100,no_subtree_check,root_squash";
  #exportsFile = builtins.concatMap (ip: "${nfsDir} ${ip}(${nfsPermissions})") allowedIPs;
in
{
  fileSystems.${nfsDir} = { # see hardware-config.nix
    device = "/mnt/${discDir}";
    options = [ "bind" ];
  };
 
  users = { 
    groups.shares.gid = 1000;
    users.share = {
      isSystemUser = true; # local users use this
      #uid = 1000;
      group = "shares";
      description = "User for NFS";
    };
  };

  services.nfs.server = { enable=true; # NOTE: this works for both v3 and v4
    # TODO: restrict it to just v4
    hostName = "HOSTNAME"; #NOTE: only one host honoured
    exports =''
      ${nfsDir} ip1(${nfsPermissions})
      ${nfsDir} ip2(${nfsPermissions})
    '';
    #exports = "${exportsFile}"; # REVIEW: does not work and it should
  };

  networking.firewall.allowedTCPPorts = [ 2049 ];
}

As of right now it works. I want to replace many lines with one.
I tried doing that with concatMap, but during nixos-rebuild test it says that
error: value is a string while a list was expected

Does anyone how to make this work?

concatMap expects a function which returns a list (see the documentation). It looks like you want to do two things:

  1. Apply a function to each element of a list, in order to produce a list of strings.
  2. Join all the strings together, with each string separated by newlines.

builtins.map (or just map; they’re the same function) will accomplish your first goal. concatStringsSep will accomplish your second goal.

okay.

I have succesfully used the builtins.map.
However I cannot use concatStringsSep as it is recognized as an empty variable.

Here is the code:

let
  allowedIPs = [ "ip1" "ip2" ];
  LoS = builtins.map (ip: "${nfsDir} ${ip}(${nfsPermissions})") allowedIPs;
  eks = concatStringsSep "\n" LoS;

Do i need to import the function somehow?

Do i need to import the function somehow?

Oops; sorry, yes. concatStringsSep should be builtins.concatStringsSep. The documentation I linked mentions this, but only once at the top of the page.

Thanks, this works perfectly!

{ config, pkgs, ... }:

let
  allowedIPs = [ "ip1" "ip2"];
  discDir = "inner";
  nfsDir = "/srv/nfs/${discDir}";
  nfsPermissions = "ro";

  ipsWithPermissions = builtins.map (ip: "${nfsDir} ${ip}(${nfsPermissions})") allowedIPs;
  exportFileContents = builtins.concatStringsSep "\n" ipsWithPermissions;
in
{
  fileSystems.${nfsDir} = { # see hardware-config.nix
    device = "/mnt/${discDir}";
    options = [ "bind" ];
    fsType = "nfs4";
  };
 
  users = { 
    groups.shares.gid = 1000;
    users.share = {
      isSystemUser = true;
      group = "shares";
      description = "User for NFS";
    };
  };

  services.nfs.server = { enable=true; # NOTE: this works for both v3 and v4
    # TODO: restrict it to just v4
    exports = "${exportFileContents}";
  };

  networking.firewall.allowedTCPPorts = [ 2049 ];
}

Here is how I used it