{
  description = "NixOS configuration with flakes";
  outputs = { alejandra, cryptpad, darwin, disko, endless-sky, flake-compat
    , flake-utils, helix, home-manager, nil, nix-ld, nixos-hardware
    , nixpkgs-master, nixpkgs-nixos-unstable, nixpkgs-rust-analyzer
    , nixpkgs-stable, nur, self, sops, }@inputs:
    let
      mkServer = pkgs: system: hostname:
        pkgs.lib.nixosSystem {
          inherit system;
          modules = [
            (./. + "/nixos/boxes/${hostname}")
            (import ./nixos/server-common.nix)
            sops.nixosModules.sops
            disko.nixosModules.disko
            ({ pkgs, ... }: {
              nixpkgs.overlays = [ inputs.cryptpad.overlays.default ];
            })
            inputs.cryptpad.nixosModules.cryptpad
          ];
          specialArgs = { inherit inputs system; };
        };
      mkRaspi = pkgs: hostname:
        pkgs.lib.nixosSystem {
          system = "aarch64-linux";
          modules =
            [ (./. + "/nixos/boxes/${hostname}") sops.nixosModules.sops ];
          specialArgs = { inherit inputs; };
        };
      mkKiosk = pkgs: system: hostname:
        pkgs.lib.nixosSystem {
          inherit system;
          modules = [
            (./. + "/nixos/boxes/${hostname}")
            (import ./nixos/common.nix)
            sops.nixosModules.sops

            home-manager.nixosModules.home-manager
            {
              home-manager.useGlobalPkgs = true;
              home-manager.useUserPackages = true;
              home-manager.users.cyryl = {
                imports =
                  [ ./nixos/home-manager ./nixos/home-manager/linux.nix ];
                _module.args.inputs = inputs;
                _module.args.system = system;
              };
            }
          ];
          specialArgs = {
            inherit inputs system;
            nixpkgs-nixos-stable-and-unfree = import nixpkgs-stable {
              inherit system;
              config = { allowUnfree = true; };
            };
            nixpkgs-nixos-unstable-and-unfree = import nixpkgs-nixos-unstable {
              inherit system;
              config = { allowUnfree = true; };
            };
          };
        };
      mkWorkstation = pkgs: system: hostname:
        pkgs.lib.nixosSystem {
          inherit system;
          modules = [
            (./. + "/nixos/boxes/${hostname}")
            (import ./nixos/email-accounts.nix)
            (import ./nixos/common.nix)
            sops.nixosModules.sops
            disko.nixosModules.disko
            nix-ld.nixosModules.nix-ld
            { programs.nix-ld.dev.enable = true; }
            home-manager.nixosModules.home-manager
            {
              home-manager.useGlobalPkgs = true;
              home-manager.useUserPackages = true;
              home-manager.users.cyryl = {
                imports =
                  [ ./nixos/home-manager ./nixos/home-manager/linux.nix ];
                _module.args.inputs = inputs;
                _module.args.system = system;
              };
            }
          ];
          specialArgs = {
            inherit inputs system;
            nixpkgs-nixos-stable-and-unfree = import nixpkgs-stable {
              inherit system;
              config = { allowUnfree = true; };
            };
            nixpkgs-nixos-unstable =
              import nixpkgs-nixos-unstable { inherit system; };
            nixpkgs-nixos-unstable-and-unfree = import nixpkgs-nixos-unstable {
              inherit system;
              config = { allowUnfree = true; };
            };
          };
        };
      mkShell = packageSet: system:
        let pkgs = packageSet.legacyPackages.${system};
        in pkgs.mkShell {
          packages = with pkgs; [
            inputs.alejandra.defaultPackage.${system}
            cacert
            git
            git-lfs
            nixpkgs-fmt
            openssh
            openssl
            pkg-config
            statix
          ];
        };
    in {
      devShells = {
        "x86_64-darwin".default = mkShell nixpkgs-stable "x86_64-darwin";
        "x86_64-linux".default = mkShell nixpkgs-stable "x86_64-linux";
      };
      darwinConfigurations = {
        "FORM3-CYRYLPLOTN" = darwin.lib.darwinSystem rec {
          system = "x86_64-darwin";
          modules = [
            (./. + "/nixos/boxes/form3")
            home-manager.darwinModules.home-manager
            {
              home-manager.useGlobalPkgs = true;
              home-manager.useUserPackages = true;
              home-manager.users.cyryl = {
                imports = [ ./nixos/home-manager ];
                _module.args.inputs = inputs;
                _module.args.system = system;
              };
            }
          ];
        };
      };

      nixosConfigurations = {
        foryog = mkWorkstation nixpkgs-nixos-unstable "x86_64-linux" "foryog";
        thinky = mkWorkstation nixpkgs-stable "x86_64-linux" "thinky";
        bolty = mkServer nixpkgs-stable "x86_64-linux" "bolty";
        vpsfree1 = mkServer nixpkgs-stable "x86_64-linux" "vpsfree1";
        cupsnet = mkServer nixpkgs-stable "aarch64-linux" "cupsnet";
        mb1 = mkServer nixpkgs-stable "x86_64-linux" "mb1";
        homescreen = mkRaspi nixpkgs-stable "homescreen";

        bootstrap = nixpkgs-stable.lib.nixosSystem rec {
          system = "x86_64-linux";
          modules = [ (./. + "/nixos/boxes/bootstrap") sops.nixosModules.sops ];
          specialArgs = {
            inherit inputs system;
            nixpkgs-nixos-unstable-and-unfree = import nixpkgs-nixos-unstable {
              inherit system;
              config = { allowUnfree = true; };
            };
          };
        };
        # nix build .#nixosConfigurations.raspiimage.config.system.build.sdImage
        # sudo dd if=result/sd-image/nixos-sd-image-21.11.20211201.a640d83-aarch64-linux.img of=/dev/sda bs=4M conv=fsync status=progress
        # make sure to update eeprom https://nixos.wiki/wiki/NixOS_on_ARM/Raspberry_Pi_4#Board-specific_installation_notes
        raspiimage = nixpkgs-stable.lib.nixosSystem {
          system = "aarch64-linux";
          modules = [
            (import
              "${inputs.nixpkgs-stable}/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix")
            {
              environment.systemPackages =
                with nixpkgs-nixos-unstable.legacyPackages."aarch64-linux"; [
                  neovim
                  htop
                  btop
                  atop
                ];

              networking.networkmanager.enable = false;
              hardware.enableRedistributableFirmware = true;
              networking.wireless.enable = true;

              services.openssh = {
                enable = true;
                permitRootLogin =
                  nixpkgs-stable.lib.mkForce "prohibit-password";
                passwordAuthentication = false;
              };

              services.xserver = {
                enable = true;
                displayManager.lightdm.enable = true;
                desktopManager.gnome.enable = true;
                libinput.enable = true;
              };

              users.extraUsers.root.openssh.authorizedKeys.keys = [
                "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEo4R+6J3h6Ix3xWpOMdU7Es1/YxFchHw0c+kcCOJxFb cyryl@foureighty"
              ];
              sdImage.compressImage = false;
              console.earlySetup = true;
            }
          ];
          specialArgs = { inherit inputs; };
        };
      };
    };
  inputs = {
    nixpkgs-master = {
      type = "github";
      owner = "NixOS";
      repo = "nixpkgs";
      ref = "master";
    };
    nixpkgs-nixos-unstable = {
      type = "github";
      owner = "NixOS";
      repo = "nixpkgs";
      ref = "nixos-unstable";
    };
    nixpkgs-stable = {
      type = "github";
      owner = "NixOS";
      repo = "nixpkgs";
      ref = "nixos-23.11";
    };
    nixpkgs-rust-analyzer = {
      type = "github";
      owner = "NixOS";
      repo = "nixpkgs";
      ref = "master";
    };
    endless-sky = {
      type = "github";
      owner = "NixOS";
      repo = "nixpkgs";
      ref = "2100c4926200b1ebbee032ad22113597195932f2";
    };
    nixos-hardware = {
      type = "github";
      owner = "NixOS";
      repo = "nixos-hardware";
      ref = "master";
    };
    darwin = {
      url = "github:lnl7/nix-darwin/master";
      inputs.nixpkgs.follows = "nixpkgs-stable";
    };
    home-manager = {
      type = "github";
      owner = "nix-community";
      repo = "home-manager";
      ref = "master";
      inputs.nixpkgs.follows = "nixpkgs-nixos-unstable";
    };
    flake-utils = {
      type = "github";
      owner = "numtide";
      repo = "flake-utils";
      ref = "main";
    };
    nur = {
      type = "github";
      owner = "nix-community";
      repo = "NUR";
      ref = "master";
    };
    nil = {
      type = "github";
      owner = "oxalica";
      repo = "nil";
      ref = "main";
      inputs.nixpkgs.follows = "nixpkgs-nixos-unstable";
      inputs.flake-utils.follows = "flake-utils";
    };
    nix-ld = {
      type = "github";
      owner = "Mic92";
      repo = "nix-ld";
      ref = "main";
      inputs.nixpkgs.follows = "nixpkgs-stable";
    };
    helix = {
      type = "github";
      owner = "helix-editor";
      repo = "helix";
      ref = "master";
      inputs.nixpkgs.follows = "nixpkgs-stable";
      inputs.flake-utils.follows = "flake-utils";
    };
    sops = {
      type = "github";
      owner = "Mic92";
      repo = "sops-nix";
      ref = "master";
      inputs.nixpkgs.follows = "nixpkgs-stable";
      inputs.nixpkgs-stable.follows = "nixpkgs-stable";
    };
    alejandra = {
      type = "github";
      owner = "kamadorueda";
      repo = "alejandra";
      ref = "main";
      inputs.nixpkgs.follows = "nixpkgs-nixos-unstable";
    };
    cryptpad = {
      url = "github:michaelshmitty/cryptpad-flake";
      inputs = { nixpkgs.follows = "nixpkgs-stable"; };
    };
    disko = {
      url = "github:nix-community/disko";
      inputs.nixpkgs.follows = "nixpkgs-stable";
    };
    flake-compat = {
      url = "github:edolstra/flake-compat";
      flake = false;
    };
  };
}
