{
  description = "My NixOS flake";

  inputs = {
    # Nixpkgs and unstable
    nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";

    # Lix - Substitution of the Nix package manager, focused on correctness, usability, and growth – and committed to doing right by its community.
    # https://git.lix.systems/lix-project/lix
    lix-module = {
      url = "https://git.lix.systems/lix-project/nixos-module/archive/2.91.0.tar.gz";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # impermanence
    # https://github.com/nix-community/impermanence
    impermanence.url = "github:nix-community/impermanence";

    # Nix User Repository: User contributed nix packages
    nur.url = "github:nix-community/NUR";

    # nix-community hardware quirks
    # https://github.com/nix-community
    nixos-hardware.url = "github:NixOS/nixos-hardware/master";

    # disko - Declarative disk partitioning and formatting using nix
    disko = {
      url = "github:nix-community/disko";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # home-manager - Manage user configuration with nix
    # https://github.com/nix-community/home-manager
    home-manager = {
      url = "github:nix-community/home-manager/release-24.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # sops-nix - secrets with mozilla sops
    # https://github.com/Mic92/sops-nix
    sops-nix = {
      url = "github:Mic92/sops-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # VSCode community extensions
    # https://github.com/nix-community/nix-vscode-extensions
    nix-vscode-extensions = {
      url = "github:nix-community/nix-vscode-extensions";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # nix-index database
    # https://github.com/nix-community/nix-index-database
    nix-index-database = {
      url = "github:nix-community/nix-index-database";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # nix-inspect - inspect nix derivations usingn a TUI interface
    # https://github.com/bluskript/nix-inspect
    nix-inspect = {
      url = "github:bluskript/nix-inspect";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # talhelper - A tool to help creating Talos kubernetes cluster
    # https://github.com/budimanjojo/talhelper
    talhelper = {
      url = "github:budimanjojo/talhelper";
      inputs.nixpkgs.follows = "nixpkgs-unstable";
    };

    # NixVirt for qemu & libvirt
    # https://github.com/AshleyYakeley/NixVirt
    nixvirt-git = {
      url = "github:AshleyYakeley/NixVirt/v0.5.0";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    vscode-server.url = "github:nix-community/nixos-vscode-server";

    # krewfile - Declarative krew plugin management
    krewfile = {
      # url = "github:brumhard/krewfile";
      url = "github:ajgon/krewfile?ref=feat/indexes";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # nix-minecraft - Minecraft server management
    # https://github.com/infinidoge/nix-minecraft
    nix-minecraft = {
      url = "github:Infinidoge/nix-minecraft";
      inputs.nixpkgs.follows = "nixpkgs-unstable";
    };
  };

  outputs =
    { self, nixpkgs, sops-nix, home-manager, nix-vscode-extensions, impermanence, disko, talhelper, lix-module, vscode-server, krewfile, ... } @ inputs:
    let
      forAllSystems = nixpkgs.lib.genAttrs [
        "aarch64-linux"
        "x86_64-linux"
      ];
    in
    rec {
      # Use nixpkgs-fmt for 'nix fmt'
      formatter = forAllSystems (system: nixpkgs.legacyPackages."${system}".nixpkgs-fmt);

      # setup devshells against shell.nix
      # devShells = forAllSystems (pkgs: import ./shell.nix { inherit pkgs; });

      # extend lib with my custom functions
      lib = nixpkgs.lib.extend (
        final: prev: {
          inherit inputs;
          myLib = import ./nixos/lib { inherit inputs; lib = final; };
        }
      );

      nixosConfigurations =
        let
          inherit inputs;
          # Import overlays for building nixosconfig with them.
          overlays = import ./nixos/overlays { inherit inputs; };
          # generate a base nixos configuration with the specified overlays, hardware modules, and any AerModules applied
          mkNixosConfig =
            { hostname
            , system ? "x86_64-linux"
            , nixpkgs ? inputs.nixpkgs
            , hardwareModules ? [ ]
              # basemodules is the base of the entire machine building
              # here we import all the modules and setup home-manager
            , baseModules ? [
                sops-nix.nixosModules.sops
                home-manager.nixosModules.home-manager
                impermanence.nixosModules.impermanence
                ./nixos/profiles/global.nix # all machines get a global profile
                ./nixos/modules/nixos # all machines get nixos modules
                ./nixos/hosts/${hostname}   # load this host's config folder for machine-specific config
                {
                  home-manager = {
                    useUserPackages = true;
                    useGlobalPkgs = true;
                    extraSpecialArgs = {
                      inherit inputs hostname system;
                    };
                  };
                }
              ]
            , profileModules ? [ ]
            }:
            nixpkgs.lib.nixosSystem {
              inherit system lib;
              modules = baseModules ++ hardwareModules ++ profileModules;
              specialArgs = { inherit self inputs nixpkgs; };
              # Add our overlays
              pkgs = import nixpkgs {
                inherit system;
                overlays = builtins.attrValues overlays;
                config = {
                  allowUnfree = true;
                  allowUnfreePredicate = _: true;
                };
              };
            };
        in
        {
          "varda" = mkNixosConfig {
            # Arm64 cax21 @ Hetzner
            # forgejo server
            hostname = "varda";
            system = "aarch64-linux";
            hardwareModules = [
              ./nixos/profiles/hw-hetzner-cax.nix
            ];
            profileModules = [
              ./nixos/profiles/role-server.nix
              { home-manager.users.jahanson = ./nixos/home/jahanson/server.nix; }
            ];
          };

          "telperion" = mkNixosConfig {
            # HP-S01 Intel G5900
            # Network services server
            hostname = "telperion";
            system = "x86_64-linux";
            hardwareModules = [
              ./nixos/profiles/hw-hp-s01.nix
              disko.nixosModules.disko
              (import ./nixos/profiles/disko-nixos.nix { disks = [ "/dev/nvme0n1" ]; })

            ];
            profileModules = [
              ./nixos/profiles/role-server.nix
              { home-manager.users.jahanson = ./nixos/home/jahanson/server.nix; }
            ];
          };

          "gandalf" = mkNixosConfig {
            # X9DRi-LN4+/X9DR3-LN4+ - Intel(R) Xeon(R) CPU E5-2650 v2
            # NAS
            hostname = "gandalf";
            system = "x86_64-linux";
            hardwareModules = [
              lix-module.nixosModules.default
              ./nixos/profiles/hw-supermicro.nix
            ];
            profileModules = [
              vscode-server.nixosModules.default
              ./nixos/profiles/role-dev.nix
              ./nixos/profiles/role-server.nix
              { home-manager.users.jahanson = ./nixos/home/jahanson/server.nix; }
            ];
          };

          "shadowfax" = mkNixosConfig {
            # Pro WS WRX80E-SAGE SE WIFI - AMD Ryzen Threadripper PRO 3955WX 16-Cores
            # Workloads server
            hostname = "shadowfax";
            system = "x86_64-linux";
            hardwareModules = [
              lix-module.nixosModules.default
              ./nixos/profiles/hw-threadripperpro.nix
            ];
            profileModules = [
              vscode-server.nixosModules.default
              ./nixos/profiles/role-dev.nix
              ./nixos/profiles/role-server.nix
              { home-manager.users.jahanson = ./nixos/home/jahanson/server.nix; }
            ];
          };
        };

      # Convenience output that aggregates the outputs for home, nixos.
      # Also used in ci to build targets generally.
      top =
        let
          nixtop = nixpkgs.lib.genAttrs
            (builtins.attrNames inputs.self.nixosConfigurations)
            (attr: inputs.self.nixosConfigurations.${attr}.config.system.build.toplevel);
        in
        nixtop;
    };
}