diff --git a/flake.lock b/flake.lock index fadc031..7e64ef5 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "a1111-src": { "flake": false, "locked": { - "lastModified": 1699030214, - "narHash": "sha256-UQ2cJ92JdSHOe0g5IkaCXPO0MYyWpLAcp6f8p+T6bxs=", + "lastModified": 1702709887, + "narHash": "sha256-xOId/D5eJszmRn0tCZtS+/u5WQUBpdPQ0I5XZIv3FvE=", "owner": "automatic1111", "repo": "stable-diffusion-webui", - "rev": "4afaaf8a020c1df457bcf7250cb1c7f609699fa7", + "rev": "cf2772fab0af5573da775e7437e6acdca424f26e", "type": "github" }, "original": { @@ -35,11 +35,11 @@ "comfyui-src": { "flake": false, "locked": { - "lastModified": 1702736172, - "narHash": "sha256-BYZHfnhdubasOAhUyq/iW4HvYKPiqBwiXY3ozZXU1Oc=", + "lastModified": 1708708880, + "narHash": "sha256-0ibYcqMczdT9oN026EwxlnGeeBcKISJ+OToHp7cOUlY=", "owner": "comfyanonymous", "repo": "ComfyUI", - "rev": "6453dc1ca2d98d89af7cf312bb48d1e3fd2ca27f", + "rev": "1e5f0f66be93182f30d5d453dc8df50f3f7c1826", "type": "github" }, "original": { @@ -55,11 +55,11 @@ ] }, "locked": { - "lastModified": 1685662779, - "narHash": "sha256-cKDDciXGpMEjP1n6HlzKinN0H+oLmNpgeCTzYnsA2po=", + "lastModified": 1706830856, + "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "71fb97f0d875fd4de4994dfb849f2c75e17eb6c3", + "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f", "type": "github" }, "original": { @@ -70,14 +70,17 @@ }, "flake-parts_2": { "inputs": { - "nixpkgs-lib": "nixpkgs-lib" + "nixpkgs-lib": [ + "hercules-ci-effects", + "nixpkgs" + ] }, "locked": { - "lastModified": 1685662779, - "narHash": "sha256-cKDDciXGpMEjP1n6HlzKinN0H+oLmNpgeCTzYnsA2po=", + "lastModified": 1701473968, + "narHash": "sha256-YcVE5emp1qQ8ieHUnxt1wCZCC3ZfAS+SRRWZ2TMda7E=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "71fb97f0d875fd4de4994dfb849f2c75e17eb6c3", + "rev": "34fed993f1674c8d06d58b37ce1e0fe5eebcb9f5", "type": "github" }, "original": { @@ -85,77 +88,19 @@ "type": "indirect" } }, - "flake-parts_3": { - "inputs": { - "nixpkgs-lib": [ - "hercules-ci-effects", - "hercules-ci-agent", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1685662779, - "narHash": "sha256-cKDDciXGpMEjP1n6HlzKinN0H+oLmNpgeCTzYnsA2po=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "71fb97f0d875fd4de4994dfb849f2c75e17eb6c3", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "haskell-flake": { - "locked": { - "lastModified": 1684780604, - "narHash": "sha256-2uMZsewmRn7rRtAnnQNw1lj0uZBMh4m6Cs/7dV5YF08=", - "owner": "srid", - "repo": "haskell-flake", - "rev": "74210fa80a49f1b6f67223debdbf1494596ff9f2", - "type": "github" - }, - "original": { - "owner": "srid", - "ref": "0.3.0", - "repo": "haskell-flake", - "type": "github" - } - }, - "hercules-ci-agent": { - "inputs": { - "flake-parts": "flake-parts_3", - "haskell-flake": "haskell-flake", - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1686721748, - "narHash": "sha256-ilD6ANYID+b0/+GTFbuZXfmu92bqVqY5ITKXSxqIp5A=", - "owner": "hercules-ci", - "repo": "hercules-ci-agent", - "rev": "7192b83935ab292a8e894db590dfd44f976e183b", - "type": "github" - }, - "original": { - "id": "hercules-ci-agent", - "type": "indirect" - } - }, "hercules-ci-effects": { "inputs": { "flake-parts": "flake-parts_2", - "hercules-ci-agent": "hercules-ci-agent", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1686830987, - "narHash": "sha256-1XLTM0lFr3NV+0rd55SQW/8oQ3ACnqlYcda3FelIwHU=", + "lastModified": 1708547820, + "narHash": "sha256-xU/KC1PWqq5zL9dQ9wYhcdgxAwdeF/dJCLPH3PNZEBg=", "owner": "hercules-ci", "repo": "hercules-ci-effects", - "rev": "04e4ab63b9eed2452edee1bb698827e1cb8265c6", + "rev": "0ca27bd58e4d5be3135a4bef66b582e57abe8f4a", "type": "github" }, "original": { @@ -184,11 +129,11 @@ "kohya_ss-src": { "flake": false, "locked": { - "lastModified": 1699706768, - "narHash": "sha256-/9YWOUbqErxrG5igF7CgUTGzxjSkOPhMA79wekGPfaQ=", + "lastModified": 1708209234, + "narHash": "sha256-ae/bkcIdSsV4FBnAj0EiBHNoRLJSgSbRnlsK6XZwmGA=", "owner": "bmaltais", "repo": "kohya_ss", - "rev": "9eb5da23002c6e00f084a19d62da6fc82074c773", + "rev": "f8d2673641778ed5b362f107f9f92a20aa15979a", "type": "github" }, "original": { @@ -199,11 +144,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1686501370, - "narHash": "sha256-G0WuM9fqTPRc2URKP9Lgi5nhZMqsfHGrdEbrLvAPJcg=", + "lastModified": 1708655239, + "narHash": "sha256-ZrP/yACUvDB+zbqYJsln4iwotbH6CTZiTkANJ0AgDv4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "75a5ebf473cd60148ba9aec0d219f72e5cf52519", + "rev": "cbc4211f0afffe6dfd2478a62615dd5175a13f9a", "type": "github" }, "original": { @@ -213,52 +158,18 @@ "type": "github" } }, - "nixpkgs-lib": { - "locked": { - "dir": "lib", - "lastModified": 1685564631, - "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a", - "type": "github" - }, - "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs-stable": { "locked": { - "lastModified": 1700403855, - "narHash": "sha256-Q0Uzjik9kUTN9pd/kp52XJi5kletBhy29ctBlAG+III=", + "lastModified": 1708566995, + "narHash": "sha256-e/THimsoxxMAHSbwMKov5f5Yg+utTj6XVGEo24Lhx+0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0c5678df521e1407884205fe3ce3cf1d7df297db", + "rev": "3cb4ae6689d2aa3f363516234572613b31212b78", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1697059129, - "narHash": "sha256-9NJcFF9CEYPvHJ5ckE8kvINvI84SZZ87PvqMbH6pro0=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "5e4c2ada4fcd54b99d56d7bd62f384511a7e2593", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } @@ -272,7 +183,7 @@ "hercules-ci-effects": "hercules-ci-effects", "invokeai-src": "invokeai-src", "kohya_ss-src": "kohya_ss-src", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs", "nixpkgs-stable": "nixpkgs-stable", "sd-src": "sd-src", "sgm-src": "sgm-src", @@ -298,11 +209,11 @@ "sgm-src": { "flake": false, "locked": { - "lastModified": 1692287310, - "narHash": "sha256-Gvpjfv5hFEeQl67OeTXVhiB4zvgV5UZ5B/ar4rBW0d0=", + "lastModified": 1708536887, + "narHash": "sha256-1jGByyT7EDHsCifLjlcvg9Y5BYb7cr3xR3+hsiQOaEA=", "owner": "Stability-AI", "repo": "generative-models", - "rev": "477d8b9a7730d9b2e92b326a770c0420d00308c9", + "rev": "1e30a2df801a18c82a24223adfbdc71be0e8ca20", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index e5adfce..eaef27b 100644 --- a/flake.nix +++ b/flake.nix @@ -1,18 +1,18 @@ { nixConfig = { - extra-substituters = [ "https://ai.cachix.org" ]; - extra-trusted-public-keys = [ "ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc=" ]; + extra-substituters = ["https://ai.cachix.org"]; + extra-trusted-public-keys = ["ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc="]; }; description = "A Nix Flake that makes AI reproducible and easy to run"; inputs = { comfyui-src = { - url = github:comfyanonymous/ComfyUI; + url = "github:comfyanonymous/ComfyUI"; flake = false; }; nixpkgs-stable = { - url = github:NixOS/nixpkgs/nixos-23.05; + url = "github:NixOS/nixpkgs/nixos-23.11"; }; bark-gui-src = { url = "github:C0untFloyd/bark-gui"; @@ -54,32 +54,21 @@ inputs.nixpkgs.follows = "nixpkgs"; }; }; - outputs = { flake-parts, invokeai-src, hercules-ci-effects, ... }@inputs: - flake-parts.lib.mkFlake { inherit inputs; } { - perSystem = { system, ... }: { + outputs = { + flake-parts, + invokeai-src, + hercules-ci-effects, + ... + } @ inputs: + flake-parts.lib.mkFlake {inherit inputs;} { + perSystem = {system, ...}: { # _module.args.pkgs = import inputs.nixpkgs { config.allowUnfree = true; inherit system; config.cudaSupport = true; }; _module.args.pkgs = import inputs.nixpkgs { inherit system; - /*overlays = [ - ( - final: prev: { - final.python310 = prev.python310.override { - enableOptimizations = true; - reproducibleBuild = false; - self = final.python310; - buildInputs = [ final.ffmpeg-full ]; - }; - pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [ - ( - python-final: python-prev: { - torch = python-prev.torch-bin; - } - ) - ]; - } - ) - ];*/ - config = { allowUnfree = true; cudaSupport = true; }; + config = { + allowUnfree = true; + cudaSupport = true; + }; }; legacyPackages = { koboldai = builtins.throw '' @@ -103,8 +92,8 @@ ./projects/automatic1111 ./projects/invokeai ./projects/textgen - ./projects/kohya_ss - ./projects/bark-gui + #./projects/kohya_ss + #./projects/bark-gui ./website ]; }; diff --git a/overlays/python/default.nix b/overlays/python/default.nix index 1ad43b8..935ef92 100644 --- a/overlays/python/default.nix +++ b/overlays/python/default.nix @@ -1,57 +1,65 @@ lib: { - fixPackages = final: prev: - let - relaxProtobuf = pkg: pkg.overrideAttrs (old: { - nativeBuildInputs = old.nativeBuildInputs ++ [ final.pythonRelaxDepsHook ]; - pythonRelaxDeps = [ "protobuf" ]; + fixPackages = final: prev: let + relaxProtobuf = pkg: + pkg.overrideAttrs (old: { + nativeBuildInputs = old.nativeBuildInputs ++ [final.pythonRelaxDepsHook]; + pythonRelaxDeps = ["protobuf"]; }); - in - { - invisible-watermark = prev.invisible-watermark.overridePythonAttrs { - pythonImportsCheck = [ ]; - }; - torchsde = prev.torchsde.overridePythonAttrs { - doCheck = false; - pythonImportsCheck = [ ]; - }; - pytorch-lightning = relaxProtobuf prev.pytorch-lightning; - wandb = relaxProtobuf (prev.wandb.overridePythonAttrs { - doCheck = false; - }); - anyio = prev.anyio.overridePythonAttrs { doCheck = false; dontUsePytestCheck = true; }; - mocket = prev.mocket.overridePythonAttrs { doCheck = false; dontUsePytestCheck = true; }; - markdown-it-py = prev.markdown-it-py.overrideAttrs (old: { - nativeBuildInputs = old.nativeBuildInputs ++ [ final.pythonRelaxDepsHook ]; - pythonRelaxDeps = [ "linkify-it-py" ]; - passthru = old.passthru // { + in { + invisible-watermark = prev.invisible-watermark.overridePythonAttrs { + pythonImportsCheck = []; + }; + torchsde = prev.torchsde.overridePythonAttrs { + doCheck = false; + pythonImportsCheck = []; + }; + pytorch-lightning = relaxProtobuf prev.pytorch-lightning; + wandb = relaxProtobuf (prev.wandb.overridePythonAttrs { + doCheck = false; + }); + anyio = prev.anyio.overridePythonAttrs { + doCheck = false; + dontUsePytestCheck = true; + }; + mocket = prev.mocket.overridePythonAttrs { + doCheck = false; + dontUsePytestCheck = true; + }; + markdown-it-py = prev.markdown-it-py.overrideAttrs (old: { + nativeBuildInputs = old.nativeBuildInputs ++ [final.pythonRelaxDepsHook]; + pythonRelaxDeps = ["linkify-it-py"]; + passthru = + old.passthru + // { optional-dependencies = with final; { - linkify = [ linkify-it-py ]; - plugins = [ mdit-py-plugins ]; + linkify = [linkify-it-py]; + plugins = [mdit-py-plugins]; }; }; - }); - filterpy = prev.filterpy.overrideAttrs (old: { - doInstallCheck = false; - }); - shap = prev.shap.overrideAttrs (old: { - doInstallCheck = false; - propagatedBuildInputs = old.propagatedBuildInputs ++ [ final.packaging ]; - pythonImportsCheck = [ "shap" ]; + }); + filterpy = prev.filterpy.overrideAttrs (old: { + doInstallCheck = false; + }); + shap = prev.shap.overrideAttrs (old: { + doInstallCheck = false; + propagatedBuildInputs = old.propagatedBuildInputs ++ [final.packaging]; + pythonImportsCheck = ["shap"]; - meta = old.meta // { + meta = + old.meta + // { broken = false; }; - }); - streamlit = - let - streamlit = final.callPackage (final.pkgs.path + "/pkgs/applications/science/machine-learning/streamlit") { - protobuf3 = final.protobuf; - }; - in - final.toPythonModule (relaxProtobuf streamlit); - opencv-python-headless = final.opencv-python; - opencv-python = final.opencv4; - }; + }); + streamlit = let + streamlit = final.callPackage (final.pkgs.path + "/pkgs/applications/science/machine-learning/streamlit") { + protobuf3 = final.protobuf; + }; + in + final.toPythonModule (relaxProtobuf streamlit); + opencv-python-headless = final.opencv-python; + opencv-python = final.opencv4; + }; torchRocm = final: prev: { torch = prev.torch.override { @@ -60,7 +68,7 @@ lib: { rocmSupport = true; }; torchvision = prev.torchvision.overridePythonAttrs (old: { - patches = (old.patches or [ ]) ++ [ ./torchvision/fix-rocm-build.patch ]; + patches = (old.patches or []) ++ [./torchvision/fix-rocm-build.patch]; }); }; diff --git a/projects/automatic1111/nixos/default.nix b/projects/automatic1111/nixos/default.nix index f28afc5..be4d207 100644 --- a/projects/automatic1111/nixos/default.nix +++ b/projects/automatic1111/nixos/default.nix @@ -1,22 +1,42 @@ -{ config, lib, ... }: - -let - inherit (lib) - mkIf mkOption mkEnableOption mkRenamedOptionModule types - escapeShellArgs flatten getExe mapAttrsToList - isBool isFloat isInt isList isString - floatToString optionalString - ; +{ + config, + lib, + ... +}: let + inherit + (lib) + mkIf + mkOption + mkEnableOption + mkRenamedOptionModule + types + escapeShellArgs + flatten + getExe + mapAttrsToList + isBool + isFloat + isInt + isList + isString + floatToString + optionalString + ; cfg = config.services.a1111; -in - -{ - imports = map ({ old, new ? old }: mkRenamedOptionModule [ "services" "a1111" old ] [ "services" "a1111" "settings" new ]) [ - { old = "host"; } - { old = "port"; } - { old = "dataDir"; new = "root"; } - { old = "precision"; } +in { + imports = map ({ + old, + new ? old, + }: + mkRenamedOptionModule ["services" "a1111" old] ["services" "a1111" "settings" new]) [ + {old = "host";} + {old = "port";} + { + old = "dataDir"; + new = "root"; + } + {old = "precision";} ]; options.services.a1111 = { enable = mkEnableOption "Automatic1111 UI for Stable Diffusion"; @@ -40,7 +60,7 @@ in settings = mkOption { description = "Structured command line arguments."; - default = { }; + default = {}; type = types.submodule { freeformType = with types; let atom = nullOr (oneOf [ @@ -49,7 +69,8 @@ in int float ]); - in attrsOf (either atom (listOf atom)); + in + attrsOf (either atom (listOf atom)); options = { #listen = mkOption { # description = "Launch gradio with 0.0.0.0 as server name, allowing to respond to network requests."; @@ -86,46 +107,55 @@ in }; config = let - - cliArgs = (flatten (mapAttrsToList (n: v: - if v == null then [] - #else if isBool v then [ "--${optionalString (!v) "no-"}${n}" ] - else if isInt v then [ "--${n}" "${toString v}" ] - else if isFloat v then [ "--${n}" "${floatToString v}" ] - else if isString v then ["--${n}" v ] - else if isList v then [ "--${n}" (toString v) ] - else throw "Unhandled type for setting \"${n}\"" - ) cfg.settings)) ++ cfg.extraArgs; - - in mkIf cfg.enable { - users.users = mkIf (cfg.user == "a1111") { - a1111 = { - isSystemUser = true; - inherit (cfg) group; + cliArgs = + (flatten (mapAttrsToList ( + n: v: + if v == null + then [] + #else if isBool v then [ "--${optionalString (!v) "no-"}${n}" ] + else if isInt v + then ["--${n}" "${toString v}"] + else if isFloat v + then ["--${n}" "${floatToString v}"] + else if isString v + then ["--${n}" v] + else if isList v + then ["--${n}" (toString v)] + else throw "Unhandled type for setting \"${n}\"" + ) + cfg.settings)) + ++ cfg.extraArgs; + in + mkIf cfg.enable { + users.users = mkIf (cfg.user == "a1111") { + a1111 = { + isSystemUser = true; + inherit (cfg) group; + }; }; - }; - users.groups = mkIf (cfg.group == "a1111") { - a1111 = {}; - }; - systemd.services.a1111 = { - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - environment = { - HOME = "${cfg.settings.data-dir}/.home"; - COMMANDLINE_ARGS = escapeShellArgs cliArgs; - NIXIFIED_AI_NONINTERACTIVE = "1"; + users.groups = mkIf (cfg.group == "a1111") { + a1111 = {}; }; - serviceConfig = { - User = cfg.user; - Group = cfg.group; - ExecStart = "${getExe cfg.package}"; - PrivateTmp = true; + systemd.services.a1111 = { + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + environment = { + HOME = "${cfg.settings.data-dir}/.home"; + COMMANDLINE_ARGS = escapeShellArgs cliArgs; + NIXIFIED_AI_NONINTERACTIVE = "1"; + }; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + ExecStart = "${getExe cfg.package}"; + Restart = "always"; + PrivateTmp = true; + }; }; + systemd.tmpfiles.rules = [ + "d '${cfg.settings.data-dir}/' 0755 ${cfg.user} ${cfg.group} - -" + "d '${cfg.settings.data-dir}/configs' 0755 ${cfg.user} ${cfg.group} - -" + "d '${cfg.settings.data-dir}/.home' 0750 ${cfg.user} ${cfg.group} - -" + ]; }; - systemd.tmpfiles.rules = [ - "d '${cfg.settings.data-dir}/' 0755 ${cfg.user} ${cfg.group} - -" - "d '${cfg.settings.data-dir}/configs' 0755 ${cfg.user} ${cfg.group} - -" - "d '${cfg.settings.data-dir}/.home' 0750 ${cfg.user} ${cfg.group} - -" - ]; - }; } diff --git a/projects/comfyui/default.nix b/projects/comfyui/default.nix index 0750e0d..6c56160 100644 --- a/projects/comfyui/default.nix +++ b/projects/comfyui/default.nix @@ -1,40 +1,73 @@ -{ config, inputs, lib, withSystem, ... }: { - perSystem = { config, pkgs, system, ... }: - let - src = inputs.comfyui-src; + config, + inputs, + lib, + withSystem, + ... +}: { + perSystem = { + config, + pkgs, + system, + ... + }: let + src = inputs.comfyui-src; - stable-pkgs = import inputs.nixpkgs-stable { - allowUnfree = true; - cudaSupport = true; - inherit system; - }; - - mkComfyUIVariant = args: pkgs.python310Packages.callPackage ./package.nix ({ - inherit src; - } // args); - in - { - packages = { - comfyui-nvidia = mkComfyUIVariant { }; - }; + stable-pkgs = import inputs.nixpkgs-stable { + allowUnfree = true; + cudaSupport = true; + inherit system; + inherit overlays; }; + overlays = [ + ( + final: prev: { + final.python310 = prev.python310.override { + enableOptimizations = true; + reproducibleBuild = false; + self = final.python310; + buildInputs = [final.ffmpeg-full]; + }; + pythonPackagesExtensions = + prev.pythonPackagesExtensions + ++ [ + ( + python-final: python-prev: { + torch = python-prev.torch.override { + rocmSupport = false; + cudaSupport = true; + }; + } + ) + ]; + } + ) + ]; - #flake.nixosModules = - /* let - packageModule = pkgAttrName: { pkgs, ... }: { - services.comfyui.package = withSystem pkgs.system ( - { config, ... }: lib.mkOptionDefault config.packages.${pkgAttrName} - ); + mkComfyUIVariant = args: + stable-pkgs.python310Packages.callPackage ./package.nix ({ + inherit src; + } + // args); + in { + packages = { + comfyui-nvidia = mkComfyUIVariant {}; }; - in - { + }; + + flake.nixosModules = let + packageModule = pkgAttrName: {pkgs, ...}: { + services.comfyui.package = withSystem pkgs.system ( + {config, ...}: lib.mkOptionDefault config.packages.${pkgAttrName} + ); + }; + in { comfyui = ./nixos; comfyui-nvidia = { - imports = [ - config.flake.nixosModules.a1111 - (packageModule "comfyui-nvidia") - ]; + imports = [ + config.flake.nixosModules.comfyui + (packageModule "comfyui-nvidia") + ]; }; - };*/ + }; } diff --git a/projects/comfyui/nixos/default.nix b/projects/comfyui/nixos/default.nix index efbede4..22a5fbc 100644 --- a/projects/comfyui/nixos/default.nix +++ b/projects/comfyui/nixos/default.nix @@ -1,83 +1,63 @@ -{ config, lib, ... }: - -let - inherit (lib) - mkIf mkOption mkEnableOption mkRenamedOptionModule types - escapeShellArgs flatten getExe mapAttrsToList - isBool isFloat isInt isList isString - floatToString optionalString - ; +{ + config, + lib, + ... +}: let + inherit + (lib) + mkIf + mkOption + mkEnableOption + mkRenamedOptionModule + types + escapeShellArgs + flatten + getExe + mapAttrsToList + isBool + isFloat + isInt + isList + isString + floatToString + optionalString + ; cfg = config.services.comfyui; -in - -{ - imports = map ({ old, new ? old }: mkRenamedOptionModule [ "services" "comfyui" old ] [ "services" "comfyui" "settings" new ]) [ - { old = "host"; } - { old = "port"; } - { old = "dataDir"; new = "root"; } - { old = "precision"; } +in { + imports = map ({ + old, + new ? old, + }: + mkRenamedOptionModule ["services" "comfyui" old] ["services" "comfyui" "settings" new]) [ + {old = "host";} + {old = "port";} + { + old = "dataDir"; + new = "root"; + } + {old = "precision";} ]; - options.services.a1111 = { - enable = mkEnableOption "Automatic1111 UI for Stable Diffusion"; + options.services.comfyui = { + enable = mkEnableOption "ComfyUI for Stable Diffusion"; package = mkOption { - description = "Which Automatic1111 package to use."; + description = "Which ComfyUI package to use."; type = types.package; }; user = mkOption { - description = "Which user to run A1111 as."; - default = "a1111"; + description = "Which user to run ComfyUI as."; + default = "comfyui"; type = types.str; }; group = mkOption { - description = "Which group to run A1111 as."; - default = "a1111"; + description = "Which group to run ComfyUI as."; + default = "comfyui"; type = types.str; }; - settings = mkOption { - description = "Structured command line arguments."; - default = { }; - type = types.submodule { - freeformType = with types; let - atom = nullOr (oneOf [ - bool - str - int - float - ]); - in attrsOf (either atom (listOf atom)); - options = { - #listen = mkOption { - # description = "Launch gradio with 0.0.0.0 as server name, allowing to respond to network requests."; - # default = false; - # type = types.bool; - #}; - - port = mkOption { - description = "Launch gradio with given server port, you need root/admin rights for ports < 1024; defaults to 7860 if available."; - default = 7860; - type = types.port; - }; - - data-dir = mkOption { - description = "Where to store A1111's state."; - default = "/var/lib/a1111"; - type = types.path; - }; - - ckpt-dir = mkOption { - description = "Path to A1111's SD models."; - default = "/var/lib/models/ckpt"; - type = types.path; - }; - }; - }; - }; - extraArgs = mkOption { description = "Additional raw command line arguments."; default = []; @@ -86,46 +66,37 @@ in }; config = let - - cliArgs = (flatten (mapAttrsToList (n: v: - if v == null then [] - #else if isBool v then [ "--${optionalString (!v) "no-"}${n}" ] - else if isInt v then [ "--${n}" "${toString v}" ] - else if isFloat v then [ "--${n}" "${floatToString v}" ] - else if isString v then ["--${n}" v ] - else if isList v then [ "--${n}" (toString v) ] - else throw "Unhandled type for setting \"${n}\"" - ) cfg.settings)) ++ cfg.extraArgs; - - in mkIf cfg.enable { - users.users = mkIf (cfg.user == "a1111") { - a1111 = { - isSystemUser = true; - inherit (cfg) group; + cliArgs = cfg.extraArgs; + in + mkIf cfg.enable { + users.users = mkIf (cfg.user == "comfyui") { + comfyui = { + isSystemUser = true; + inherit (cfg) group; + }; }; - }; - users.groups = mkIf (cfg.group == "a1111") { - a1111 = {}; - }; - systemd.services.a1111 = { - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - environment = { - HOME = "${cfg.settings.data-dir}/.home"; - COMMANDLINE_ARGS = escapeShellArgs cliArgs; - NIXIFIED_AI_NONINTERACTIVE = "1"; + users.groups = mkIf (cfg.group == "comfyui") { + comfyui = {}; }; - serviceConfig = { - User = cfg.user; - Group = cfg.group; - ExecStart = "${getExe cfg.package}"; - PrivateTmp = true; + systemd.services.a1111 = { + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + environment = { + HOME = "${cfg.settings.data-dir}/.home"; + COMMANDLINE_ARGS = escapeShellArgs cliArgs; + NIXIFIED_AI_NONINTERACTIVE = "1"; + }; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + ExecStart = "${getExe cfg.package}"; + PrivateTmp = true; + }; }; + systemd.tmpfiles.rules = [ + "d '${cfg.settings.data-dir}/' 0755 ${cfg.user} ${cfg.group} - -" + "d '${cfg.settings.data-dir}/configs' 0755 ${cfg.user} ${cfg.group} - -" + "d '${cfg.settings.data-dir}/.home' 0750 ${cfg.user} ${cfg.group} - -" + ]; }; - systemd.tmpfiles.rules = [ - "d '${cfg.settings.data-dir}/' 0755 ${cfg.user} ${cfg.group} - -" - "d '${cfg.settings.data-dir}/configs' 0755 ${cfg.user} ${cfg.group} - -" - "d '${cfg.settings.data-dir}/.home' 0750 ${cfg.user} ${cfg.group} - -" - ]; - }; } diff --git a/projects/comfyui/package.nix b/projects/comfyui/package.nix index dd06fe1..9776101 100644 --- a/projects/comfyui/package.nix +++ b/projects/comfyui/package.nix @@ -1,17 +1,16 @@ -{ src -, buildPythonPackage -, torchvision-bin -, torch-bin -, safetensors -, psutil -, einops -, transformers -, scipy -, torchsde -, pillow -, torch -, torchvision -, accelerate +{ + src, + buildPythonPackage, + safetensors, + psutil, + einops, + transformers, + scipy, + torchsde, + pillow, + torch, + torchvision, + accelerate, }: buildPythonPackage { pname = "ComfyUI"; @@ -29,22 +28,24 @@ buildPythonPackage { scipy pillow torchsde - ]; + ]; - buildPhase = - '' + buildPhase = '' runHook preBuild - + mkdir -p dist cp -R . $out chmod -R +w $out cd $out - + substituteInPlace ./folder_paths.py --replace 'os.path.join(base_path, "models")' '"/home/denis/comfyui/models"' + substituteInPlace ./folder_paths.py --replace 'os.path.join(os.path.dirname(os.path.realpath(__file__)), "temp")' '"/home/denis/comfyui/temp"' + substituteInPlace ./folder_paths.py --replace 'os.path.join(os.path.dirname(os.path.realpath(__file__)), "output")' '"/home/denis/comfyui/output"' + substituteInPlace ./folder_paths.py --replace 'os.path.join(os.path.dirname(os.path.realpath(__file__)), "input")' '"/home/denis/comfyui/input"' #make main.py executable > shebang mkdir -p $out/bin cat <<-EOF > main.py - $(echo "#!/usr/bin/python") - $(cat main.py) + $(echo "#!/usr/bin/python") + $(cat main.py) EOF chmod +x main.py makeWrapper "$out/main.py" $out/bin/main-wrapped.py \ @@ -60,11 +61,4 @@ buildPythonPackage { homepage = "https://github.com/comfyanonymous/ComfyUI.git"; mainProgram = "main-wrapped.py"; }; - - #Tiled VAE supported without additional dependencies - #Infinit image browser couple of deps - #civit-ai browser + couple of deps - #animatediff --> needs deforum for frame interpolation - #deforum - #controlnet } diff --git a/projects/invokeai/default.nix b/projects/invokeai/default.nix index f735d4d..7f66745 100644 --- a/projects/invokeai/default.nix +++ b/projects/invokeai/default.nix @@ -1,12 +1,18 @@ -{ config, inputs, lib, withSystem, ... }: - -let +{ + config, + inputs, + lib, + withSystem, + ... +}: let l = lib // config.flake.lib; inherit (config.flake) overlays; -in - -{ - perSystem = { config, pkgs, ... }: let +in { + perSystem = { + config, + pkgs, + ... + }: let commonOverlays = [ overlays.python-fixPackages (l.overlays.callManyPackages [ @@ -44,37 +50,43 @@ in ../../packages/mediapipe ../../packages/python-engineio ]) - (final: prev: lib.mapAttrs - (_: pkg: pkg.overrideAttrs (old: { - nativeBuildInputs = old.nativeBuildInputs ++ [ final.pythonRelaxDepsHook ]; - pythonRemoveDeps = [ "opencv-python-headless" "opencv-python" "tb-nightly" "clip" ]; - })) - { - inherit (prev) - albumentations - qudida - gfpgan - basicsr - facexlib - realesrgan - clipseg - ; - } + ( + final: prev: + lib.mapAttrs + (_: pkg: + pkg.overrideAttrs (old: { + nativeBuildInputs = old.nativeBuildInputs ++ [final.pythonRelaxDepsHook]; + pythonRemoveDeps = ["opencv-python-headless" "opencv-python" "tb-nightly" "clip"]; + })) + { + inherit + (prev) + albumentations + qudida + gfpgan + basicsr + facexlib + realesrgan + clipseg + ; + } ) ]; python3Variants = { - amd = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays ++ [ - overlays.python-torchRocm - ]); - nvidia = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays ++ [ - overlays.python-torchCuda - ]); + amd = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays + ++ [ + overlays.python-torchRocm + ]); + nvidia = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays + ++ [ + overlays.python-torchCuda + ]); }; src = inputs.invokeai-src; - mkInvokeAIVariant = args: pkgs.callPackage ./package.nix ({ inherit src; } // args); + mkInvokeAIVariant = args: pkgs.callPackage ./package.nix ({inherit src;} // args); in { packages = { invokeai-amd = mkInvokeAIVariant { @@ -87,9 +99,9 @@ in }; flake.nixosModules = let - packageModule = pkgAttrName: { pkgs, ... }: { + packageModule = pkgAttrName: {pkgs, ...}: { services.invokeai.package = withSystem pkgs.system ( - { config, ... }: lib.mkOptionDefault config.packages.${pkgAttrName} + {config, ...}: lib.mkOptionDefault config.packages.${pkgAttrName} ); }; in { diff --git a/projects/invokeai/package.nix b/projects/invokeai/package.nix index 5da44b4..758ddf7 100644 --- a/projects/invokeai/package.nix +++ b/projects/invokeai/package.nix @@ -1,146 +1,144 @@ -{ python3Packages -# misc -, lib -, src -, pkgs -# extra deps -}: - -let +{ + python3Packages, + # misc + lib, + src, + pkgs, + # extra deps +}: let getVersion = lib.flip lib.pipe [ (src: builtins.readFile "${src}/invokeai/version/invokeai_version.py") (builtins.match ".*__version__ = \"([^\"]+)\".*") builtins.head ]; in + python3Packages.buildPythonPackage { + pname = "InvokeAI"; + format = "pyproject"; + version = getVersion src; + inherit src; + propagatedBuildInputs = with python3Packages; [ + semver + mediapipe + numpy + torchsde + uvicorn + pyperclip + #invisible-watermark + fastapi + fastapi-events + fastapi-socketio + timm + scikit-image + controlnet-aux + compel + python-dotenv + uvloop + watchfiles + httptools + websockets + dnspython + albumentations + opencv4 + pudb + imageio + imageio-ffmpeg + compel + npyscreen + pytorch-lightning + protobuf + omegaconf + test-tube + einops + taming-transformers-rom1504 + torch-fidelity + torchmetrics + transformers + kornia + k-diffusion + picklescan + diffusers + pypatchmatch + realesrgan + pillow + send2trash + flask + flask-cors + dependency-injector + gfpgan + eventlet + clipseg + getpass-asterisk + safetensors + datasets + accelerate + huggingface-hub + easing-functions + dynamicprompts + torchvision-bin + test-tube + ]; + nativeBuildInputs = with python3Packages; [pythonRelaxDepsHook pip]; + pythonRemoveDeps = ["clip" "pyreadline3" "flaskwebgui" "opencv-python" "fastapi-socketio"]; + pythonRelaxDeps = ["dnspython" "flask" "requests" "numpy" "pytorch-lightning" "torchsde" "uvicorn" "accelerate" "scikit-image" "safetensors" "huggingface-hub" "torchvision" "test-tube" "fastapi"]; + makeWrapperArgs = [ + '' --run ' + if [ -d "/usr/lib/wsl/lib" ] + then + echo "Running via WSL (Windows Subsystem for Linux), setting LD_LIBRARY_PATH=/usr/lib/wsl/lib" + set -x + export LD_LIBRARY_PATH="/usr/lib/wsl/lib" + set +x + fi + ' + '' + # See note about consumer GPUs: + # https://docs.amd.com/bundle/ROCm-Deep-Learning-Guide-v5.4.3/page/Troubleshooting.html + " --set-default HSA_OVERRIDE_GFX_VERSION 10.3.0" -python3Packages.buildPythonPackage { - pname = "InvokeAI"; - format = "pyproject"; - version = getVersion src; - inherit src; - propagatedBuildInputs = with python3Packages; [ - semver - mediapipe - numpy - torchsde - uvicorn - pyperclip - invisible-watermark - fastapi - fastapi-events - fastapi-socketio - timm - scikit-image - controlnet-aux - compel - python-dotenv - uvloop - watchfiles - httptools - websockets - dnspython - albumentations - opencv4 - pudb - imageio - imageio-ffmpeg - compel - npyscreen - pytorch-lightning - protobuf - omegaconf - test-tube - einops - taming-transformers-rom1504 - torch-fidelity - torchmetrics - transformers - kornia - k-diffusion - picklescan - diffusers - pypatchmatch - realesrgan - pillow - send2trash - flask - flask-cors - dependency-injector - gfpgan - eventlet - clipseg - getpass-asterisk - safetensors - datasets - accelerate - huggingface-hub - easing-functions - dynamicprompts - torchvision-bin - test-tube - ]; - nativeBuildInputs = with python3Packages; [ pythonRelaxDepsHook pip ]; - pythonRemoveDeps = [ "clip" "pyreadline3" "flaskwebgui" "opencv-python" "fastapi-socketio" ]; - pythonRelaxDeps = [ "dnspython" "flask" "requests" "numpy" "pytorch-lightning" "torchsde" "uvicorn" "invisible-watermark" "accelerate" "scikit-image" "safetensors" "huggingface-hub" "torchvision" "test-tube" "fastapi" ]; - makeWrapperArgs = [ - '' --run ' - if [ -d "/usr/lib/wsl/lib" ] - then - echo "Running via WSL (Windows Subsystem for Linux), setting LD_LIBRARY_PATH=/usr/lib/wsl/lib" - set -x - export LD_LIBRARY_PATH="/usr/lib/wsl/lib" - set +x - fi + ''--run 'export INVOKEAI_ROOT="''${INVOKEAI_ROOT:-$HOME/.invokeai}"' '' + '' --run ' + if [[ ! -d "$INVOKEAI_ROOT" && "''${0##*/}" != invokeai-configure ]] + then + echo "State directory does not exist, running invokeai-configure" + if [[ "''${NIXIFIED_AI_NONINTERACTIVE:-0}" != 0 ]]; then + ${placeholder "out"}/bin/invokeai-configure --yes --skip-sd-weights + else + ${placeholder "out"}/bin/invokeai-configure + fi + fi + ' + '' + ]; + patchPhase = '' + runHook prePatch + + substituteInPlace ./pyproject.toml \ + --replace 'setuptools~=65.5' 'setuptools' \ + --replace 'pip~=22.3' 'pip' + + # Add subprocess to the imports + substituteInPlace ./invokeai/backend/install/invokeai_configure.py --replace \ + 'import shutil' \ ' - '' - # See note about consumer GPUs: - # https://docs.amd.com/bundle/ROCm-Deep-Learning-Guide-v5.4.3/page/Troubleshooting.html - " --set-default HSA_OVERRIDE_GFX_VERSION 10.3.0" - - '' --run 'export INVOKEAI_ROOT="''${INVOKEAI_ROOT:-$HOME/.invokeai}"' '' - '' --run ' - if [[ ! -d "$INVOKEAI_ROOT" && "''${0##*/}" != invokeai-configure ]] - then - echo "State directory does not exist, running invokeai-configure" - if [[ "''${NIXIFIED_AI_NONINTERACTIVE:-0}" != 0 ]]; then - ${placeholder "out"}/bin/invokeai-configure --yes --skip-sd-weights - else - ${placeholder "out"}/bin/invokeai-configure - fi - fi + import shutil + import subprocess ' - '' - ]; - patchPhase = '' - runHook prePatch + # shutil.copytree will inherit the permissions of files in the /nix/store + # which are read only, so we subprocess.call cp instead and tell it not to + # preserve the mode + substituteInPlace ./invokeai/backend/install/invokeai_configure.py --replace \ + "shutil.copytree(configs_src, configs_dest, dirs_exist_ok=True)" \ + "subprocess.call('cp -r --no-preserve=mode {configs_src} {configs_dest}'.format(configs_src=configs_src, configs_dest=configs_dest), shell=True)" + runHook postPatch - substituteInPlace ./pyproject.toml \ - --replace 'setuptools~=65.5' 'setuptools' \ - --replace 'pip~=22.3' 'pip' - - # Add subprocess to the imports - substituteInPlace ./invokeai/backend/install/invokeai_configure.py --replace \ - 'import shutil' \ -' -import shutil -import subprocess -' - # shutil.copytree will inherit the permissions of files in the /nix/store - # which are read only, so we subprocess.call cp instead and tell it not to - # preserve the mode - substituteInPlace ./invokeai/backend/install/invokeai_configure.py --replace \ - "shutil.copytree(configs_src, configs_dest, dirs_exist_ok=True)" \ - "subprocess.call('cp -r --no-preserve=mode {configs_src} {configs_dest}'.format(configs_src=configs_src, configs_dest=configs_dest), shell=True)" - runHook postPatch - - substituteInPlace ./pyproject.toml \ - --replace 'pip~=22.3' 'pip' \ - --replace 'setuptools~=65.5' 'setuptools' - ''; - meta = { - description = "Fancy Web UI for Stable Diffusion"; - homepage = "https://invoke-ai.github.io/InvokeAI/"; - mainProgram = "invokeai-web"; - }; -} + substituteInPlace ./pyproject.toml \ + --replace 'pip~=22.3' 'pip' \ + --replace 'setuptools~=65.5' 'setuptools' + ''; + meta = { + description = "Fancy Web UI for Stable Diffusion"; + homepage = "https://invoke-ai.github.io/InvokeAI/"; + mainProgram = "invokeai-web"; + }; + }