let
  sources = import ./npins;

  lib = import (sources.nix-lib + "/src/trivial.nix");

  patch = import sources.nix-patches { patchFile = ./patches; };

  nodes' = import ./meta/nodes.nix;
  nodes = builtins.attrNames nodes';

  mkNode = node: {
    # Import the base configuration for each node
    imports = builtins.map (lib.mkRel (./machines/${node})) [
      "_configuration.nix"
      "_hardware-configuration.nix"
    ];
  };

  nixpkgs' = import ./meta/nixpkgs.nix;
  # All supported nixpkgs versions, instanciated
  nixpkgs = lib.mapSingleFuse mkNixpkgs nixpkgs'.supported;

  # Get the configured nixos version for the node,
  # defaulting to the one defined in meta/nixpkgs
  version = node: nodes'.${node}.nixpkgs or nixpkgs'.default;

  # Builds a patched version of nixpkgs, only as the source
  mkNixpkgs' =
    v:
    let
      version = "nixos-${v}";
    in
    patch.mkNixpkgsSrc {
      src = sources.${version};
      inherit version;
    };

  # Instanciates the required nixpkgs version
  mkNixpkgs = version: import (mkNixpkgs' version) { };

  ###
  # Function to create arguments based on the node
  #
  mkArgs = node: rec {
    lib = import sources.nix-lib {
      inherit (nixpkgs.${version node}) lib;

      keysRoot = ./keys;
    };

    meta = (import ./meta) lib;

    nodeMeta = meta.nodes.${node};
  };
in

{
  meta = {
    nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${version n}) nodes;

    specialArgs = {
      inherit nixpkgs sources;
    };

    nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes;
  };

  defaults =
    { name, nodeMeta, ... }:
    {
      # Import the default modules
      imports = [ ./modules ];

      # Include default secrets
      age-secrets.sources = [ ./machines/${name}/secrets ];

      # Deployment config is specified in meta.nodes.${node}.deployment
      inherit (nodeMeta) deployment;

      nix = {
        # Set NIX_PATH to the patched version of nixpkgs
        nixPath = [ "nixpkgs=${mkNixpkgs' (version name)}" ];
        optimise.automatic = true;

        gc = {
          automatic = true;
          dates = "weekly";
          options = "--delete-older-than 7d";
        };
      };

      # Allow unfree packages
      nixpkgs.config.allowUnfree = true;

      # Use the stateVersion declared in the metadata
      system = {
        inherit (nodeMeta) stateVersion;
      };
    };
}
// (lib.mapSingleFuse mkNode nodes)