Ansible: How to manage collections with nix?

Starting with ansible version 2.10, ansible and all its modules are no longer provided in a single repository, but split into

  • an ansible-base package, which includes some base modules and a collection manager (ansible-galaxy), and
  • collections, which are installed with ansible-galaxy (into ~/.ansible, by default).

See for more information on that. With nixos 20.09, nixpkgs provides ansible 2.10 as the default ansible version, which now no longer includes modules that were part of ansible 2.9 and earlier.

Originally, it was enough to enter a nix-shell providing ansible to be able to run ansible playbooks. Now you need to

  1. manually install the collections your ansible playbooks depend on, or
  2. get the necessary collections as nix packages, and research how to point ansible-specific environment variables to the correct locations in the nix-store.

2 is obviously the way you’d like it to work with nix, but nixpkgs currently provides no framework for dealing with collections, so 1 is the current way to do it if you need to get work done. What kind of user interface would nixpkgs even need to have for this to be actually usable and consistent with how other non-reproducible package managers are lifted into nixpkgs? I imagine this could be similar to how python packages are handled, but I don’t know how much effort it is to maintain such a package set.

Any input on how to approach lifting such a package manager into nixpkgs?


Managing ansible collections is about:

  1. downloading collections,
  2. then installing the collections with ansible-galaxy collection install <collection.tar.gz>.

The following function automates this inside the nix store:

{ stdenv, lib, pkgs }: ansible: collections:

/* Install ansible collections
 * Collections are downloaded, then each collection is installed with:
 * $ ansible-galaxy collection install <collection.tar.gz>.
 * The resulting derivation is the ansible collections path.
 * Example:
 * ANSIBLE_COLLECTIONS_PATH = callPackage ./ansible-collections.nix {} ansible_2_10 {
 *   "community-postgresql" = {
 *     version = "1.4.0";
 *     sha256 = "14izkq5knrch2xv4jx7jvxnq2lwhhdlyck7i7ga9mny3skrz9qfp";
 *   };
 * };


  installCollections =
    lib.concatStringsSep "\n" (lib.mapAttrsToList installCollection collections);

  installCollection = name: versionAndSha256:
    "${ansible}/bin/ansible-galaxy collection install ${collection name versionAndSha256}/collection.tar.gz";

  collection = name: { version, sha256 }:
    stdenv.mkDerivation {
      pname = name;
      version = version;

      src = builtins.fetchurl {
        name = name;
        url = "${name}-${version}.tar.gz";
        sha256 = sha256;

      phases = [ "installPhase" ];

      installPhase = ''
        mkdir -p $out
        cp $src $out/collection.tar.gz

pkgs.runCommand "ansible-collections" {} ''
  mkdir -p $out
  export HOME=./