How to ensure directory exists inside of generated lxc tarball

I am trying to create lxc tarballs for incus, and I want to bind certain directories so that the folders pertaining to the service I’m running are persisted on disk rather than inside the container (I want to be able to throw away the container and still have all the data saved where a new container could pick back up). My problem is that in order to create the incus instance with the bind mounts already defined, those folders need to already exist. I’ve tried using systemd.tmpfiles.rules, but that doesn’t seem to create them such that they already exist inside of the created image tarball. How would I achieve this?

There is no option for that right now, but adding something like this to your configuration should work:

{ config, lib, pkgs, modulesPath, ... }:

{
  ...

  image.modules.lxc = { config, lib, pkgs, modulesPath, ... }: {
    system.build.tarball = lib.mkForce (
      pkgs.callPackage
        (modulesPath + "/../lib/make-system-tarball.nix")
        {
          fileName = config.image.baseName;
          extraArgs = "--owner=0";

          storeContents = [
            {
              object = config.system.build.toplevel;
              symlink = "none";
            }
          ];

          contents = [
            {
              source = config.system.build.toplevel + "/init";
              target = "/sbin/init";
            }
            {
              source = config.system.build.toplevel + "/etc/os-release";
              target = "/etc/os-release";
            }
          ];

          extraCommands = ''
            mkdir -p proc sys dev

            # Additional empty directories
            mkdir -p opt/foo/bar
          '';
        }
    );
  };
}

For reference, here is what this is overwriting: nixpkgs/nixos/modules/virtualisation/lxc-container.nix at 94a0f8d9ca5da101ec1cddbdfecfdc1ae1766d04 · NixOS/nixpkgs · GitHub

Apologies for the late reply, haven’t gotten the chance to actually try this until now, if I implement this into my workflow it spits out a permission denied error when trying to create the “/var” folder. I’m assuming that it has to created as a relative path similar to your example, so I’ve removed the prefix / from the paths I’m using, however when I do that I get the same error about there being no such file or directory when I try to launch the incus instance. I’ll keep searching for a solution, and I’ll double check my own code in the meantime, perhaps something is wrong with the way I am generating the mkdir commands for use in the extraCommands string

Without looking into the exact mechanism, I am sure the relative path is due to the fact that the root of the tarball (or more precisely the folder it is built from) is not the root of the build environment. That is why I didn’t add absolute paths indeed, sorry that I didn’t say it, at this point of writing it was already clear to me so I forgot to include.

Don’t know what is the remaining issue.