{
  inputs = {

    secrets = {
      url = "git+ssh://gitea@git.ingolf-wagner.de/palo/nixos-secrets.git?ref=main";
      flake = false;
    };
    nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
    nixpkgs-legacy_2305.url = "github:nixos/nixpkgs/nixos-23.05";
    nixpkgs-legacy_2211.url = "github:nixos/nixpkgs/nixos-22.11";
    nixpkgs-legacy_2205.url = "github:nixos/nixpkgs/nixos-22.05";
    nixpkgs-legacy_2105.url = "github:nixos/nixpkgs/nixos-21.05";
    nixos-hardware.url = "github:nixos/nixos-hardware";
    home-manager = {
      url = "github:nix-community/home-manager/release-23.11";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    polygon-art = {
      url = "git+https://git.ingolf-wagner.de/palo/polygon-art.git";
    };
    sops-nix.url = "github:Mic92/sops-nix";
    doom-emacs-nix = {
      url = "github:nix-community/nix-doom-emacs";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    home-manager-utils = {
      url = "github:mrvandalo/home-manager-utils";
      inputs.home-manager.follows = "home-manager";
    };
    nixpkgs-fmt = {
      url = "github:nix-community/nixpkgs-fmt";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    grocy-scanner = {
      url = "github:mrVanDalo/grocy-scanner";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    permown = {
      url = "github:mrVanDalo/module.permown";
      #url = "git+file:///home/palo/dev/nixos/permown";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    private_assets = {
      url = "git+file:///home/palo/dev/nixos/nixos-private-assets";
      #url = "git+ssh://gitea@git.ingolf-wagner.de/palo/nixos-private-assets.git?ref=main";
      flake = true;
    };
    retiolum = {
      url = "github:Mic92/retiolum";
      #url = "git+file:///home/palo/dev/nixos/retiolum";
    };
    landingpage = {
      #url = "git+file:///home/palo/dev/landingpage";
      url = "github:mrVanDalo/landingpage";
    };
    kmonad = {
      url = "github:kmonad/kmonad?dir=nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    disko = {
      url = "github:nix-community/disko";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    dns = {
      url = "github:kirelagin/dns.nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixinate.url = "github:matthewcroughan/nixinate";
    stylix = {
      #url = "github:danth/stylix?ref=35cab8eb76c1d3672b2b290a64f357847c30d090";
      url = "github:danth/stylix";
      #inputs.nixpkgs.follows = "nixpkgs";
      #inputs.home-manager.follows = "home-manager";
    };
    taskshell = {
      url = "github:mrvandalo/taskshell";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    overviewer.url = "git+ssh://gitea@git.ingolf-wagner.de/palo/overviewer.git?ref=main";
  };

  outputs =
    { self
    , disko
    , dns
    , doom-emacs-nix
    , grocy-scanner
    , home-manager
    , home-manager-utils
    , kmonad
    , landingpage
    , nixinate
    , nixos-hardware
    , nixpkgs
    , nixpkgs-fmt
    , nixpkgs-legacy_2105
    , nixpkgs-legacy_2205
    , nixpkgs-legacy_2211
    , nixpkgs-legacy_2305
    , nixpkgs-unstable
    , overviewer
    , permown
    , polygon-art
    , private_assets
    , retiolum
    , secrets
    , sops-nix
    , stylix
    , taskshell
    }:
    let
      system = "x86_64-linux";

      pkgs = nixpkgs.legacyPackages.${system};
      inherit (nixpkgs) lib;


      meta = rec {
        system = "x86_64-linux";
        pkgs = import nixpkgs {
          inherit system;
          config.allowUnfree = true;
          config.permittedInsecurePackages = [
            "python-2.7.18.6"
            "python-2.7.18.7"
            "electron-24.8.6" # for bitwarden
          ];

          overlays = [
            (_self: _super: {
              unstable = import nixpkgs-unstable {
                inherit system;
                config.allowUnfree = true;
              };
              legacy_2211 = import nixpkgs-legacy_2211 { inherit system; };
              legacy_2205 = import nixpkgs-legacy_2205 { inherit system; };
              legacy_2105 = nixpkgs-legacy_2105 { inherit system; };
              legacy_2305 = nixpkgs-legacy_2105 { inherit system; };
              polygon-art = polygon-art.packages.${system};
              landingpage = landingpage.packages.${system}.plain;
              trilium-server = nixpkgs-unstable.legacyPackages.${system}.trilium-server;
              kmonad = kmonad.packages.${system}.kmonad;
              tasksh = taskshell.packages.${system}.tasksh;
              overviewer = overviewer.packages.${system}.overviewer;
            })
            (import ./nixos/pkgs)
          ];
        };
        specialArgs = {
          inherit private_assets;
          assets = ./nixos/assets;
        };
      };

      # todo : why redefine it?
      # Mic92 means, is not needed anymore
      nixosSystem = args:
        (lib.makeOverridable lib.nixosSystem)
          (lib.recursiveUpdate args {
            modules =
              args.modules
              ++ [
                {
                  config.nixpkgs.pkgs = lib.mkDefault args.pkgs;
                  config.nixpkgs.localSystem = lib.mkDefault args.pkgs.stdenv.hostPlatform;
                }
              ];
          });

      nixosConfigurationSetup =
        { name
        , host ? "${name}.private"
        , modules
        }:
        nixosSystem {
          inherit (meta) system specialArgs pkgs;
          modules = modules ++ defaultModules ++ [
            {
              _module.args.nixinate = {
                host = host;
                sshUser = "root";
                buildOn = "remote"; # valid args are "local" or "remote"
                substituteOnTarget = false; # if buildOn is "local" then it will substitute on the target, "-s"
                hermetic = false;
              };
            }
            {
              imports = [
                ./nixos/machines/${name}/configuration.nix
                (sopsModule name)
              ];
            }
          ];
        };

      defaultModules = [
        {
          # todo : find out what this is?
          # make flake inputs accessiable in NixOS
          _module.args.self = self;
          _module.args.inputs = self.inputs;
        }
        ({ pkgs, lib, ... }:
          {
            # todo : check if this is still needed
            nix = {
              # no channesl needed this way
              nixPath = [ "nixpkgs=${pkgs.path}" ];
              # make flakes available
              package = pkgs.nixUnstable;
              extraOptions = ''
                experimental-features = nix-command flakes
              '';
            };
          })
        { nix.settings.substituters = [ "https://cache.nixos.org/" ]; }
        {
          boot.tmp.useTmpfs = lib.mkDefault true;
          environment.systemPackages = [ nixpkgs-fmt.defaultPackage.${system} ];
          imports = [
            permown.nixosModules.permown
            disko.nixosModules.disko
            kmonad.nixosModules.default
            grocy-scanner.nixosModule
          ];
        }
      ];

      homeManagerModules = { config, ... }: {
        imports = [
          home-manager.nixosModules.home-manager
          stylix.nixosModules.stylix
        ];
        stylix.image = ./nixos/assets/wallpaper.png;
        stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-light-medium.yaml";
        stylix.fonts = {
          serif = {
            package = pkgs.ubuntu_font_family;
            name = "Ubuntu";
          };
          sansSerif = {
            package = pkgs.ubuntu_font_family;
            name = "Ubuntu";
          };
          monospace = {
            package = pkgs.jetbrains-mono;
            name = "JetBrains Mono";
          };
          emoji = {
            package = pkgs.noto-fonts-emoji;
            name = "Noto Color Emoji";
          };
        };

        home-manager.useGlobalPkgs = true;
        home-manager.useUserPackages = true;
        home-manager.sharedModules = [
          doom-emacs-nix.hmModule
          home-manager-utils.hmModule
        ];
        home-manager.users.mainUser.home.stateVersion = "22.11";
        home-manager.users.root.home.stateVersion = "22.11";
      };

      sopsModule = name: { lib, ... }: {
        imports = [ sops-nix.nixosModules.sops ];
        sops.defaultSopsFile = lib.mkForce "${secrets}/secrets/${name}.yaml";
      };

    in
    {
      devShells.${system}.default =
        pkgs.mkShell {
          buildInputs = [
            nixpkgs-fmt.defaultPackage.${system}
          ];
        };

      apps = nixinate.nixinate.x86_64-linux self;

      packages = with nixpkgs.lib; {
        ${system} =
          let
            vms = mapAttrs'
              (host: sys: {
                name = "vm-${host}";
                value = sys.config.system.build.vm;
              })
              self.nixosConfigurations;
            sds = mapAttrs'
              (host: sys: {
                name = "sd-${host}";
                value = sys.config.system.build.sdImage;
              })
              (filterAttrs
                (n: hasAttrByPath [ "config" "system" "build" "sdImage" ])
                self.nixosConfigurations);
          in
          vms // sds;
      };

      nixosConfigurations =
        {
          sternchen = nixosConfigurationSetup {
            name = "sternchen";
            host = "sternchen.secret";
            modules = [
              nixos-hardware.nixosModules.lenovo-thinkpad-x220
              #retiolum.nixosModules.retiolum
              #private_assets.nixosModules.jobrad
              homeManagerModules
            ];
          };
          sterni = nixosConfigurationSetup {
            name = "sterni";
            modules = [
              nixos-hardware.nixosModules.lenovo-thinkpad-x220
              #retiolum.nixosModules.retiolum
              #private_assets.nixosModules.jobrad
              homeManagerModules
            ];
          };
          cream = nixosConfigurationSetup {
            name = "cream";
            modules = [
              nixos-hardware.nixosModules.framework-12th-gen-intel
              retiolum.nixosModules.retiolum
              private_assets.nixosModules.jobrad
              homeManagerModules
              # { home-manager.users.root = import ./nixos/homes/root; }
              { home-manager.users.mainUser = import ./nixos/homes/palo; }
              { home-manager.users.mainUser.gui.enable = true; }
            ];
          };
          chungus = nixosConfigurationSetup {
            name = "chungus";
            modules = [
              homeManagerModules
              retiolum.nixosModules.retiolum
              { home-manager.users.mainUser = import ./nixos/homes/palo; }
            ];
          };
          robi = nixosConfigurationSetup {
            name = "robi";
            modules = [
              homeManagerModules
            ];
          };
        };
    };
}