An optional autowiring module is provided that will scan the directory structure and wire up the appropriate flake outputs automatically without you having to do it manually.
A ready demonstration is available in nixos-unified-template as well as srid/nixos-config. In the latter, you will notice the following directory structure:
โฎ lsd --tree --depth 1 configurations modules overlays packages
๐ configurations
โโโ ๐ darwin
โโโ ๐ home
โโโ ๐ nixos
๐ modules
โโโ ๐ darwin
โโโ ๐ flake
โโโ ๐ home
โโโ ๐ nixos
๐ overlays
โโโ โ๏ธ default.nix
๐ packages
โโโ โ๏ธ git-squash.nix
โโโ โ๏ธ sshuttle-via.nix
โโโ ๐ twitter-convertEach of these are wired to the corresponding flake output, as indicated in the below table:
| Directory | Flake Output |
|---|---|
configurations/nixos/foo.nix
1
| nixosConfigurations.foo |
configurations/darwin/foo.nix
1
| darwinConfigurations.foo |
configurations/home/foo.nix
1
| legacyPackages.${system}.homeConfigurations.foo
2
|
modules/nixos/foo.nix | nixosModules.foo |
modules/darwin/foo.nix | darwinModules.foo |
modules/flake/foo.nix | flakeModules.foo |
overlays/foo.nix | overlays.foo |
packages/foo.nix | packages.${system}.foo
3
|
flake-parts
Autowiring is also provided if you use just flake-parts, via the lib.mkFlake function. In your top-level flake.nix, you only need to define your outputs as follows:
{
inputs = ...;
outputs = inputs:
inputs.nixos-unified.lib.mkFlake
{ inherit inputs; root = ./.; };
}This will,
-
Auto-import flake-parts modules under either
./nix/modules/flakeor./modules/flake(whichever exists) -
Use a sensible default for
systemswhich can be overriden. -
Pass
rootas top-level module args, as a non-recursive way of referring to the path of the flake (without needinginputs.self).
See srid/haskell-templateโs flake.nix for a ready example. For another example, see this emanote PR.
Package Autowiring Example
The packages/ directory allows you to define custom packages that will be automatically wired as flake outputs. Hereโs an example project structure:
โฎ lsd --tree --depth 2 packages
๐ packages
โโโ โ๏ธ hello-world.nix
โโโ ๐ complex-app
โโโ โ๏ธ default.nix
Each package file should export a function compatible with pkgs.callPackage. Here are two examples:
packages/hello-world.nix - Simple shell script package:
{ lib, writeShellApplication }:
writeShellApplication {
name = "hello-world";
text = ''
echo "Hello from my autowired package!"
echo "Args: $*"
'';
meta = {
description = "A simple hello world script";
license = lib.licenses.mit;
};
}packages/complex-app/default.nix - Directory-based package:
{ lib, stdenv, makeWrapper }:
stdenv.mkDerivation {
pname = "complex-app";
version = "1.0.0";
src = ./.;
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
mkdir -p $out/bin
cp app.sh $out/bin/complex-app
chmod +x $out/bin/complex-app
'';
meta = {
description = "A more complex application";
license = lib.licenses.gpl3;
platforms = lib.platforms.unix;
};
}After defining these packages, they become available in your flake outputs:
# Build and run packages
nix build .#hello-world
nix run .#complex-app
# List all autowired packages
nix flake show | grep packagesThe packages will appear as:
-
packages.${system}.hello-world -
packages.${system}.complex-app
configurations/nixos/foo/default.nix. Likewise for other output types.
legacyPackages? Because, creating a home-manager configuration requires pkgs. See https://github.com/nix-community/home-manager/issues/3075
callPackage. The autowiring system automatically calls pkgs.callPackage on each package file, making them available as packages.${system}.{name} in your flake outputs.