{self, ...} @ inputs: let
  nixpkgs = inputs.nixpkgs-unstable;
  inherit (nixpkgs) lib;

  inherit (lib.attrsets) mergeAttrsList recursiveUpdate;
  inherit (lib.lists) foldl' forEach filter;

  hosts = import ./hosts inputs;
in
  {
    inherit (hosts) nixosConfigurations homeConfigurations;
  }
  // (inputs.flake-utils.lib.eachDefaultSystem (
    system: let
      pkgs = import nixpkgs {
        inherit system;
        config.allowUnfree = true;
        overlays = [
          (import ./overlay)
        ];
      };
    in
      foldl' recursiveUpdate {} [
        {
          # we expose nixpkgs.${system} so that we can nix run/build stuff
          # from nixpkgs from flake's input versions
          nixpkgs = pkgs;

          formatter = pkgs.alejandra;

          devShell = pkgs.mkShell {
            VAULT_ADDR = "https://vault.owo.monster";
            packages =
              (with pkgs; [
                git
                nano
                nix
                nix-tree
                nix-output-monitor
              ])
              ++ (with self.packages."${system}"; [
                mk-enc-usb
                mk-encrypted-drive
              ]);
          };

          packages = {
            inherit (pkgs) comic-code comic-sans;
            inherit (pkgs) mk-enc-usb mk-encrypted-drive;
            inherit (pkgs) gotosocial mpd-headless;
            inherit (pkgs) kitty-terminfo;
            inherit (pkgs) linux_rpi5 raspberrypifw raspberrypiWirelessFirmware raspberrypi-utils;
            inherit (pkgs) widevine-aarch64-4k widevine-aarch64-16k;

            inherit (inputs.home-manager-unstable.packages."${system}") home-manager;
          };
        }

        # secrets-init, secrets-check and vault-policy for machines and containers
        (let
          secretsLib = import ./modules/nixos/secretsLib/lib.nix {
            inherit (nixpkgs) lib;
            inherit pkgs;
          };

          systemConfigForSystem = systemName: self.nixosConfigurations.${systemName}.config;

          secretsConfigForSystem = systemName: let
            systemConfig = systemConfigForSystem systemName;
          in
            systemConfig.services.secrets;

          systemConfigForContainer = systemName: containerName: let
            systemConfig = systemConfigForSystem systemName;
          in
            systemConfig.containers.${containerName}.config;

          secretsConfigForContainer = systemName: containerName: let
            systemConfig = systemConfigForContainer systemName containerName;
          in
            systemConfig.services.secrets;

          secretsInitScriptForSystem = systemName: let
            secretsConfig = secretsConfigForSystem systemName;
          in
            secretsLib.mkSecretsInitScriptWithName secretsConfig "${systemName}";

          secretsInitScriptForContainer = systemName: containerName: let
            secretsConfig = secretsConfigForContainer systemName containerName;
          in
            secretsLib.mkSecretsInitScriptWithName secretsConfig "${systemName}-container-${containerName}";

          vaultPolicyForSystem = systemName: let
            secretsConfig = secretsConfigForSystem systemName;
          in
            secretsLib.genVaultPolicy secretsConfig "${systemName}";

          vaultPolicyForContainer = systemName: containerName: let
            secretsConfig = secretsConfigForContainer systemName containerName;
          in
            secretsLib.genVaultPolicy secretsConfig "${systemName}-container-${containerName}";

          # All machines/containers with secrets.nix
          machines = let
            doesHaveHostSecrets = machineName: let
              hostConfig = self.nixosConfigurations.${machineName}.config;
              secretsConfig = hostConfig.services.secrets;
            in
              secretsConfig.enable && secretsConfig.vaultLogin.enable;

            containersForMachine = machineName: let
              hostConfig = self.nixosConfigurations.${machineName}.config;
            in
              lib.filter (containerName: let
                containerConfig = hostConfig.containers.${containerName}.config;
                secretsConfig = containerConfig.services.secrets;
              in
                secretsConfig.enable && secretsConfig.vaultLogin.enable) (builtins.attrNames hostConfig.containers);

            configForMachine = machineName: {
              hasHostSecrets = doesHaveHostSecrets machineName;
              containers = containersForMachine machineName;
            };
          in {
            "hetzner-arm" =
              configForMachine "hetzner-arm"
              // {
                sshAddress = "hetzner-arm.servers.genderfucked.monster";
              };
            "lappy-t495" = configForMachine "lappy-t495";
          };

          machinesWithHostSecrets = filter (
            machine: machines.${machine}.hasHostSecrets
          ) (builtins.attrNames machines);

          machinesWithContainers = filter (
            machine: (machines.${machine}.containers or []) != []
          ) (builtins.attrNames machines);
        in {
          packages = mergeAttrsList [
            {
              "update-vault-policies" = pkgs.writeShellScriptBin "update-vault-policies" ''
                ${lib.concatStringsSep "\n" (map (hostName: let
                    machineContainers = machines.${hostName}.containers;
                  in ''
                    echo "Deploying policy for ${hostName}"
                    vault policy write ${hostName} ${self.packages.${system}."vault-policy-${hostName}"}

                    ${lib.concatStringsSep "\n" (map (containerName: let
                        policyName = "${hostName}-container-${containerName}";
                      in ''
                        echo "Deploying policy for ${policyName}"
                        vault policy write ${policyName} ${self.packages.${system}."vault-policy-${policyName}"}
                        echo
                      '')
                      machineContainers)}

                    echo
                  '')
                  machinesWithHostSecrets)}
              '';
            }

            (mergeAttrsList (
              forEach machinesWithHostSecrets (machineName: {
                "secrets-init-${machineName}" = secretsInitScriptForSystem machineName;
                "vault-policy-${machineName}" = vaultPolicyForSystem machineName;
              })
            ))

            (mergeAttrsList (forEach machinesWithContainers (machineName: let
              machine = machines.${machineName};
              inherit (machine) containers;
            in
              mergeAttrsList (forEach containers (containerName: {
                "secrets-init-${machineName}-container-${containerName}" = secretsInitScriptForContainer machineName containerName;
                "vault-policy-${machineName}-container-${containerName}" = vaultPolicyForContainer machineName containerName;
              })))))
          ];
        })
      ]
  ))
