let

  # import plops with pkgs and lib
  opsImport = import ((import <nixpkgs> { }).fetchgit {
    url = "https://github.com/mrVanDalo/plops.git";
    rev = "9fabba016a3553ae6e13d5d17d279c4de2eb00ad";
    sha256 = "193pajq1gcd9jyd12nii06q1sf49xdhbjbfqk3lcq83s0miqfs63";
  });

  ops = let
    overlay = self: super: {
      # overwrite ssh to use the generated ssh configuration
      openssh = super.writeShellScriptBin "ssh" ''
        ${super.openssh}/bin/ssh -F ${
          toString ./generated/ssh-configuration
        } "$@"
      '';
    };
  in opsImport { overlays = [ overlay ]; };

  lib = ops.lib;
  pkgs = ops.pkgs;

  # define all sources
  source = {

    # nixpkgs (no need for channels anymore)
    nixPkgs.nixpkgs.git = {
      ref = "nixos-20.09";
      url = "https://github.com/NixOS/nixpkgs";
    };

    # system configurations
    system = name: {
      configs.file = toString ./configs;
      nixos-config.symlink = "configs/${name}/configuration.nix";
    };

    # secrets which are hold and stored by pass
    secrets = name: {
      secrets.pass = {
        dir = toString ./secrets;
        name = name;
      };
    };
  };

  servers = import ./generated/nixos-machines.nix;

  deployServer = name:
    { user ? "root", host, ... }:
    with ops;
    jobs "deploy-${name}" "${user}@${host.ipv4}" [
      # deploy secrets to /run/plops-secrets/secrets
      # (populateTmpfs (source.secrets name))
      # deploy system to /var/src/system
      (populate (source.system name))
      # deploy nixpkgs to /var/src/nixpkgs
      (populate source.nixPkgs)
      switch
    ];

in pkgs.mkShell {

  buildInputs = lib.mapAttrsToList deployServer servers;

  shellHook = ''
    export PASSWORD_STORE_DIR=./secrets
  '';

}