This commit is contained in:
Denis Manherz 2024-02-24 18:57:40 +01:00
parent a227d57d28
commit 45e0082ede
9 changed files with 530 additions and 584 deletions

View file

@ -3,11 +3,11 @@
"a1111-src": { "a1111-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1699030214, "lastModified": 1702709887,
"narHash": "sha256-UQ2cJ92JdSHOe0g5IkaCXPO0MYyWpLAcp6f8p+T6bxs=", "narHash": "sha256-xOId/D5eJszmRn0tCZtS+/u5WQUBpdPQ0I5XZIv3FvE=",
"owner": "automatic1111", "owner": "automatic1111",
"repo": "stable-diffusion-webui", "repo": "stable-diffusion-webui",
"rev": "4afaaf8a020c1df457bcf7250cb1c7f609699fa7", "rev": "cf2772fab0af5573da775e7437e6acdca424f26e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -35,11 +35,11 @@
"comfyui-src": { "comfyui-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1702736172, "lastModified": 1708708880,
"narHash": "sha256-BYZHfnhdubasOAhUyq/iW4HvYKPiqBwiXY3ozZXU1Oc=", "narHash": "sha256-0ibYcqMczdT9oN026EwxlnGeeBcKISJ+OToHp7cOUlY=",
"owner": "comfyanonymous", "owner": "comfyanonymous",
"repo": "ComfyUI", "repo": "ComfyUI",
"rev": "6453dc1ca2d98d89af7cf312bb48d1e3fd2ca27f", "rev": "1e5f0f66be93182f30d5d453dc8df50f3f7c1826",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -55,11 +55,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1685662779, "lastModified": 1706830856,
"narHash": "sha256-cKDDciXGpMEjP1n6HlzKinN0H+oLmNpgeCTzYnsA2po=", "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "71fb97f0d875fd4de4994dfb849f2c75e17eb6c3", "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -70,14 +70,17 @@
}, },
"flake-parts_2": { "flake-parts_2": {
"inputs": { "inputs": {
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": [
"hercules-ci-effects",
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1685662779, "lastModified": 1701473968,
"narHash": "sha256-cKDDciXGpMEjP1n6HlzKinN0H+oLmNpgeCTzYnsA2po=", "narHash": "sha256-YcVE5emp1qQ8ieHUnxt1wCZCC3ZfAS+SRRWZ2TMda7E=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "71fb97f0d875fd4de4994dfb849f2c75e17eb6c3", "rev": "34fed993f1674c8d06d58b37ce1e0fe5eebcb9f5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -85,77 +88,19 @@
"type": "indirect" "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": { "hercules-ci-effects": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_2", "flake-parts": "flake-parts_2",
"hercules-ci-agent": "hercules-ci-agent",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1686830987, "lastModified": 1708547820,
"narHash": "sha256-1XLTM0lFr3NV+0rd55SQW/8oQ3ACnqlYcda3FelIwHU=", "narHash": "sha256-xU/KC1PWqq5zL9dQ9wYhcdgxAwdeF/dJCLPH3PNZEBg=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "hercules-ci-effects", "repo": "hercules-ci-effects",
"rev": "04e4ab63b9eed2452edee1bb698827e1cb8265c6", "rev": "0ca27bd58e4d5be3135a4bef66b582e57abe8f4a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -184,11 +129,11 @@
"kohya_ss-src": { "kohya_ss-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1699706768, "lastModified": 1708209234,
"narHash": "sha256-/9YWOUbqErxrG5igF7CgUTGzxjSkOPhMA79wekGPfaQ=", "narHash": "sha256-ae/bkcIdSsV4FBnAj0EiBHNoRLJSgSbRnlsK6XZwmGA=",
"owner": "bmaltais", "owner": "bmaltais",
"repo": "kohya_ss", "repo": "kohya_ss",
"rev": "9eb5da23002c6e00f084a19d62da6fc82074c773", "rev": "f8d2673641778ed5b362f107f9f92a20aa15979a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -199,11 +144,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1686501370, "lastModified": 1708655239,
"narHash": "sha256-G0WuM9fqTPRc2URKP9Lgi5nhZMqsfHGrdEbrLvAPJcg=", "narHash": "sha256-ZrP/yACUvDB+zbqYJsln4iwotbH6CTZiTkANJ0AgDv4=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "75a5ebf473cd60148ba9aec0d219f72e5cf52519", "rev": "cbc4211f0afffe6dfd2478a62615dd5175a13f9a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -213,52 +158,18 @@
"type": "github" "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": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1700403855, "lastModified": 1708566995,
"narHash": "sha256-Q0Uzjik9kUTN9pd/kp52XJi5kletBhy29ctBlAG+III=", "narHash": "sha256-e/THimsoxxMAHSbwMKov5f5Yg+utTj6XVGEo24Lhx+0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0c5678df521e1407884205fe3ce3cf1d7df297db", "rev": "3cb4ae6689d2aa3f363516234572613b31212b78",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-23.05", "ref": "nixos-23.11",
"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",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -272,7 +183,7 @@
"hercules-ci-effects": "hercules-ci-effects", "hercules-ci-effects": "hercules-ci-effects",
"invokeai-src": "invokeai-src", "invokeai-src": "invokeai-src",
"kohya_ss-src": "kohya_ss-src", "kohya_ss-src": "kohya_ss-src",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable", "nixpkgs-stable": "nixpkgs-stable",
"sd-src": "sd-src", "sd-src": "sd-src",
"sgm-src": "sgm-src", "sgm-src": "sgm-src",
@ -298,11 +209,11 @@
"sgm-src": { "sgm-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1692287310, "lastModified": 1708536887,
"narHash": "sha256-Gvpjfv5hFEeQl67OeTXVhiB4zvgV5UZ5B/ar4rBW0d0=", "narHash": "sha256-1jGByyT7EDHsCifLjlcvg9Y5BYb7cr3xR3+hsiQOaEA=",
"owner": "Stability-AI", "owner": "Stability-AI",
"repo": "generative-models", "repo": "generative-models",
"rev": "477d8b9a7730d9b2e92b326a770c0420d00308c9", "rev": "1e30a2df801a18c82a24223adfbdc71be0e8ca20",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -1,18 +1,18 @@
{ {
nixConfig = { nixConfig = {
extra-substituters = [ "https://ai.cachix.org" ]; extra-substituters = ["https://ai.cachix.org"];
extra-trusted-public-keys = [ "ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc=" ]; extra-trusted-public-keys = ["ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc="];
}; };
description = "A Nix Flake that makes AI reproducible and easy to run"; description = "A Nix Flake that makes AI reproducible and easy to run";
inputs = { inputs = {
comfyui-src = { comfyui-src = {
url = github:comfyanonymous/ComfyUI; url = "github:comfyanonymous/ComfyUI";
flake = false; flake = false;
}; };
nixpkgs-stable = { nixpkgs-stable = {
url = github:NixOS/nixpkgs/nixos-23.05; url = "github:NixOS/nixpkgs/nixos-23.11";
}; };
bark-gui-src = { bark-gui-src = {
url = "github:C0untFloyd/bark-gui"; url = "github:C0untFloyd/bark-gui";
@ -54,32 +54,21 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
}; };
outputs = { flake-parts, invokeai-src, hercules-ci-effects, ... }@inputs: outputs = {
flake-parts.lib.mkFlake { inherit inputs; } { flake-parts,
perSystem = { system, ... }: { 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 { config.allowUnfree = true; inherit system; config.cudaSupport = true; };
_module.args.pkgs = import inputs.nixpkgs { _module.args.pkgs = import inputs.nixpkgs {
inherit system; inherit system;
/*overlays = [ config = {
( allowUnfree = true;
final: prev: { cudaSupport = true;
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; };
}; };
legacyPackages = { legacyPackages = {
koboldai = builtins.throw '' koboldai = builtins.throw ''
@ -103,8 +92,8 @@
./projects/automatic1111 ./projects/automatic1111
./projects/invokeai ./projects/invokeai
./projects/textgen ./projects/textgen
./projects/kohya_ss #./projects/kohya_ss
./projects/bark-gui #./projects/bark-gui
./website ./website
]; ];
}; };

View file

@ -1,57 +1,65 @@
lib: { lib: {
fixPackages = final: prev: fixPackages = final: prev: let
let relaxProtobuf = pkg:
relaxProtobuf = pkg: pkg.overrideAttrs (old: { pkg.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [ final.pythonRelaxDepsHook ]; nativeBuildInputs = old.nativeBuildInputs ++ [final.pythonRelaxDepsHook];
pythonRelaxDeps = [ "protobuf" ]; pythonRelaxDeps = ["protobuf"];
}); });
in in {
{ invisible-watermark = prev.invisible-watermark.overridePythonAttrs {
invisible-watermark = prev.invisible-watermark.overridePythonAttrs { pythonImportsCheck = [];
pythonImportsCheck = [ ]; };
}; torchsde = prev.torchsde.overridePythonAttrs {
torchsde = prev.torchsde.overridePythonAttrs { doCheck = false;
doCheck = false; pythonImportsCheck = [];
pythonImportsCheck = [ ]; };
}; pytorch-lightning = relaxProtobuf prev.pytorch-lightning;
pytorch-lightning = relaxProtobuf prev.pytorch-lightning; wandb = relaxProtobuf (prev.wandb.overridePythonAttrs {
wandb = relaxProtobuf (prev.wandb.overridePythonAttrs { doCheck = false;
doCheck = false; });
}); anyio = prev.anyio.overridePythonAttrs {
anyio = prev.anyio.overridePythonAttrs { doCheck = false; dontUsePytestCheck = true; }; doCheck = false;
mocket = prev.mocket.overridePythonAttrs { doCheck = false; dontUsePytestCheck = true; }; dontUsePytestCheck = true;
markdown-it-py = prev.markdown-it-py.overrideAttrs (old: { };
nativeBuildInputs = old.nativeBuildInputs ++ [ final.pythonRelaxDepsHook ]; mocket = prev.mocket.overridePythonAttrs {
pythonRelaxDeps = [ "linkify-it-py" ]; doCheck = false;
passthru = old.passthru // { 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; { optional-dependencies = with final; {
linkify = [ linkify-it-py ]; linkify = [linkify-it-py];
plugins = [ mdit-py-plugins ]; plugins = [mdit-py-plugins];
}; };
}; };
}); });
filterpy = prev.filterpy.overrideAttrs (old: { filterpy = prev.filterpy.overrideAttrs (old: {
doInstallCheck = false; doInstallCheck = false;
}); });
shap = prev.shap.overrideAttrs (old: { shap = prev.shap.overrideAttrs (old: {
doInstallCheck = false; doInstallCheck = false;
propagatedBuildInputs = old.propagatedBuildInputs ++ [ final.packaging ]; propagatedBuildInputs = old.propagatedBuildInputs ++ [final.packaging];
pythonImportsCheck = [ "shap" ]; pythonImportsCheck = ["shap"];
meta = old.meta // { meta =
old.meta
// {
broken = false; broken = false;
}; };
}); });
streamlit = streamlit = let
let streamlit = final.callPackage (final.pkgs.path + "/pkgs/applications/science/machine-learning/streamlit") {
streamlit = final.callPackage (final.pkgs.path + "/pkgs/applications/science/machine-learning/streamlit") { protobuf3 = final.protobuf;
protobuf3 = final.protobuf; };
}; in
in final.toPythonModule (relaxProtobuf streamlit);
final.toPythonModule (relaxProtobuf streamlit); opencv-python-headless = final.opencv-python;
opencv-python-headless = final.opencv-python; opencv-python = final.opencv4;
opencv-python = final.opencv4; };
};
torchRocm = final: prev: { torchRocm = final: prev: {
torch = prev.torch.override { torch = prev.torch.override {
@ -60,7 +68,7 @@ lib: {
rocmSupport = true; rocmSupport = true;
}; };
torchvision = prev.torchvision.overridePythonAttrs (old: { torchvision = prev.torchvision.overridePythonAttrs (old: {
patches = (old.patches or [ ]) ++ [ ./torchvision/fix-rocm-build.patch ]; patches = (old.patches or []) ++ [./torchvision/fix-rocm-build.patch];
}); });
}; };

View file

@ -1,22 +1,42 @@
{ config, lib, ... }: {
config,
let lib,
inherit (lib) ...
mkIf mkOption mkEnableOption mkRenamedOptionModule types }: let
escapeShellArgs flatten getExe mapAttrsToList inherit
isBool isFloat isInt isList isString (lib)
floatToString optionalString mkIf
; mkOption
mkEnableOption
mkRenamedOptionModule
types
escapeShellArgs
flatten
getExe
mapAttrsToList
isBool
isFloat
isInt
isList
isString
floatToString
optionalString
;
cfg = config.services.a1111; cfg = config.services.a1111;
in in {
imports = map ({
{ old,
imports = map ({ old, new ? old }: mkRenamedOptionModule [ "services" "a1111" old ] [ "services" "a1111" "settings" new ]) [ new ? old,
{ old = "host"; } }:
{ old = "port"; } mkRenamedOptionModule ["services" "a1111" old] ["services" "a1111" "settings" new]) [
{ old = "dataDir"; new = "root"; } {old = "host";}
{ old = "precision"; } {old = "port";}
{
old = "dataDir";
new = "root";
}
{old = "precision";}
]; ];
options.services.a1111 = { options.services.a1111 = {
enable = mkEnableOption "Automatic1111 UI for Stable Diffusion"; enable = mkEnableOption "Automatic1111 UI for Stable Diffusion";
@ -40,7 +60,7 @@ in
settings = mkOption { settings = mkOption {
description = "Structured command line arguments."; description = "Structured command line arguments.";
default = { }; default = {};
type = types.submodule { type = types.submodule {
freeformType = with types; let freeformType = with types; let
atom = nullOr (oneOf [ atom = nullOr (oneOf [
@ -49,7 +69,8 @@ in
int int
float float
]); ]);
in attrsOf (either atom (listOf atom)); in
attrsOf (either atom (listOf atom));
options = { options = {
#listen = mkOption { #listen = mkOption {
# description = "Launch gradio with 0.0.0.0 as server name, allowing to respond to network requests."; # description = "Launch gradio with 0.0.0.0 as server name, allowing to respond to network requests.";
@ -86,46 +107,55 @@ in
}; };
config = let config = let
cliArgs =
cliArgs = (flatten (mapAttrsToList (n: v: (flatten (mapAttrsToList (
if v == null then [] n: v:
#else if isBool v then [ "--${optionalString (!v) "no-"}${n}" ] if v == null
else if isInt v then [ "--${n}" "${toString v}" ] then []
else if isFloat v then [ "--${n}" "${floatToString v}" ] #else if isBool v then [ "--${optionalString (!v) "no-"}${n}" ]
else if isString v then ["--${n}" v ] else if isInt v
else if isList v then [ "--${n}" (toString v) ] then ["--${n}" "${toString v}"]
else throw "Unhandled type for setting \"${n}\"" else if isFloat v
) cfg.settings)) ++ cfg.extraArgs; then ["--${n}" "${floatToString v}"]
else if isString v
in mkIf cfg.enable { then ["--${n}" v]
users.users = mkIf (cfg.user == "a1111") { else if isList v
a1111 = { then ["--${n}" (toString v)]
isSystemUser = true; else throw "Unhandled type for setting \"${n}\""
inherit (cfg) group; )
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") {
users.groups = mkIf (cfg.group == "a1111") { 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";
}; };
serviceConfig = { systemd.services.a1111 = {
User = cfg.user; after = ["network.target"];
Group = cfg.group; wantedBy = ["multi-user.target"];
ExecStart = "${getExe cfg.package}"; environment = {
PrivateTmp = true; 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} - -"
];
};
} }

View file

@ -1,40 +1,73 @@
{ config, inputs, lib, withSystem, ... }:
{ {
perSystem = { config, pkgs, system, ... }: config,
let inputs,
src = inputs.comfyui-src; lib,
withSystem,
...
}: {
perSystem = {
config,
pkgs,
system,
...
}: let
src = inputs.comfyui-src;
stable-pkgs = import inputs.nixpkgs-stable { stable-pkgs = import inputs.nixpkgs-stable {
allowUnfree = true; allowUnfree = true;
cudaSupport = true; cudaSupport = true;
inherit system; inherit system;
}; inherit overlays;
mkComfyUIVariant = args: pkgs.python310Packages.callPackage ./package.nix ({
inherit src;
} // args);
in
{
packages = {
comfyui-nvidia = mkComfyUIVariant { };
};
}; };
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 = mkComfyUIVariant = args:
/* let stable-pkgs.python310Packages.callPackage ./package.nix ({
packageModule = pkgAttrName: { pkgs, ... }: { inherit src;
services.comfyui.package = withSystem pkgs.system ( }
{ config, ... }: lib.mkOptionDefault config.packages.${pkgAttrName} // 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 = ./nixos;
comfyui-nvidia = { comfyui-nvidia = {
imports = [ imports = [
config.flake.nixosModules.a1111 config.flake.nixosModules.comfyui
(packageModule "comfyui-nvidia") (packageModule "comfyui-nvidia")
]; ];
}; };
};*/ };
} }

View file

@ -1,83 +1,63 @@
{ config, lib, ... }: {
config,
let lib,
inherit (lib) ...
mkIf mkOption mkEnableOption mkRenamedOptionModule types }: let
escapeShellArgs flatten getExe mapAttrsToList inherit
isBool isFloat isInt isList isString (lib)
floatToString optionalString mkIf
; mkOption
mkEnableOption
mkRenamedOptionModule
types
escapeShellArgs
flatten
getExe
mapAttrsToList
isBool
isFloat
isInt
isList
isString
floatToString
optionalString
;
cfg = config.services.comfyui; cfg = config.services.comfyui;
in in {
imports = map ({
{ old,
imports = map ({ old, new ? old }: mkRenamedOptionModule [ "services" "comfyui" old ] [ "services" "comfyui" "settings" new ]) [ new ? old,
{ old = "host"; } }:
{ old = "port"; } mkRenamedOptionModule ["services" "comfyui" old] ["services" "comfyui" "settings" new]) [
{ old = "dataDir"; new = "root"; } {old = "host";}
{ old = "precision"; } {old = "port";}
{
old = "dataDir";
new = "root";
}
{old = "precision";}
]; ];
options.services.a1111 = { options.services.comfyui = {
enable = mkEnableOption "Automatic1111 UI for Stable Diffusion"; enable = mkEnableOption "ComfyUI for Stable Diffusion";
package = mkOption { package = mkOption {
description = "Which Automatic1111 package to use."; description = "Which ComfyUI package to use.";
type = types.package; type = types.package;
}; };
user = mkOption { user = mkOption {
description = "Which user to run A1111 as."; description = "Which user to run ComfyUI as.";
default = "a1111"; default = "comfyui";
type = types.str; type = types.str;
}; };
group = mkOption { group = mkOption {
description = "Which group to run A1111 as."; description = "Which group to run ComfyUI as.";
default = "a1111"; default = "comfyui";
type = types.str; 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 { extraArgs = mkOption {
description = "Additional raw command line arguments."; description = "Additional raw command line arguments.";
default = []; default = [];
@ -86,46 +66,37 @@ in
}; };
config = let config = let
cliArgs = cfg.extraArgs;
cliArgs = (flatten (mapAttrsToList (n: v: in
if v == null then [] mkIf cfg.enable {
#else if isBool v then [ "--${optionalString (!v) "no-"}${n}" ] users.users = mkIf (cfg.user == "comfyui") {
else if isInt v then [ "--${n}" "${toString v}" ] comfyui = {
else if isFloat v then [ "--${n}" "${floatToString v}" ] isSystemUser = true;
else if isString v then ["--${n}" v ] inherit (cfg) group;
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 == "comfyui") {
users.groups = mkIf (cfg.group == "a1111") { comfyui = {};
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";
}; };
serviceConfig = { systemd.services.a1111 = {
User = cfg.user; after = ["network.target"];
Group = cfg.group; wantedBy = ["multi-user.target"];
ExecStart = "${getExe cfg.package}"; environment = {
PrivateTmp = true; 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} - -"
];
};
} }

View file

@ -1,17 +1,16 @@
{ src {
, buildPythonPackage src,
, torchvision-bin buildPythonPackage,
, torch-bin safetensors,
, safetensors psutil,
, psutil einops,
, einops transformers,
, transformers scipy,
, scipy torchsde,
, torchsde pillow,
, pillow torch,
, torch torchvision,
, torchvision accelerate,
, accelerate
}: }:
buildPythonPackage { buildPythonPackage {
pname = "ComfyUI"; pname = "ComfyUI";
@ -29,22 +28,24 @@ buildPythonPackage {
scipy scipy
pillow pillow
torchsde torchsde
]; ];
buildPhase = buildPhase = ''
''
runHook preBuild runHook preBuild
mkdir -p dist mkdir -p dist
cp -R . $out cp -R . $out
chmod -R +w $out chmod -R +w $out
cd $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 #make main.py executable > shebang
mkdir -p $out/bin mkdir -p $out/bin
cat <<-EOF > main.py cat <<-EOF > main.py
$(echo "#!/usr/bin/python") $(echo "#!/usr/bin/python")
$(cat main.py) $(cat main.py)
EOF EOF
chmod +x main.py chmod +x main.py
makeWrapper "$out/main.py" $out/bin/main-wrapped.py \ makeWrapper "$out/main.py" $out/bin/main-wrapped.py \
@ -60,11 +61,4 @@ buildPythonPackage {
homepage = "https://github.com/comfyanonymous/ComfyUI.git"; homepage = "https://github.com/comfyanonymous/ComfyUI.git";
mainProgram = "main-wrapped.py"; 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
} }

View file

@ -1,12 +1,18 @@
{ config, inputs, lib, withSystem, ... }: {
config,
let inputs,
lib,
withSystem,
...
}: let
l = lib // config.flake.lib; l = lib // config.flake.lib;
inherit (config.flake) overlays; inherit (config.flake) overlays;
in in {
perSystem = {
{ config,
perSystem = { config, pkgs, ... }: let pkgs,
...
}: let
commonOverlays = [ commonOverlays = [
overlays.python-fixPackages overlays.python-fixPackages
(l.overlays.callManyPackages [ (l.overlays.callManyPackages [
@ -44,37 +50,43 @@ in
../../packages/mediapipe ../../packages/mediapipe
../../packages/python-engineio ../../packages/python-engineio
]) ])
(final: prev: lib.mapAttrs (
(_: pkg: pkg.overrideAttrs (old: { final: prev:
nativeBuildInputs = old.nativeBuildInputs ++ [ final.pythonRelaxDepsHook ]; lib.mapAttrs
pythonRemoveDeps = [ "opencv-python-headless" "opencv-python" "tb-nightly" "clip" ]; (_: pkg:
})) pkg.overrideAttrs (old: {
{ nativeBuildInputs = old.nativeBuildInputs ++ [final.pythonRelaxDepsHook];
inherit (prev) pythonRemoveDeps = ["opencv-python-headless" "opencv-python" "tb-nightly" "clip"];
albumentations }))
qudida {
gfpgan inherit
basicsr (prev)
facexlib albumentations
realesrgan qudida
clipseg gfpgan
; basicsr
} facexlib
realesrgan
clipseg
;
}
) )
]; ];
python3Variants = { python3Variants = {
amd = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays ++ [ amd = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays
overlays.python-torchRocm ++ [
]); overlays.python-torchRocm
nvidia = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays ++ [ ]);
overlays.python-torchCuda nvidia = l.overlays.applyOverlays pkgs.python3Packages (commonOverlays
]); ++ [
overlays.python-torchCuda
]);
}; };
src = inputs.invokeai-src; src = inputs.invokeai-src;
mkInvokeAIVariant = args: pkgs.callPackage ./package.nix ({ inherit src; } // args); mkInvokeAIVariant = args: pkgs.callPackage ./package.nix ({inherit src;} // args);
in { in {
packages = { packages = {
invokeai-amd = mkInvokeAIVariant { invokeai-amd = mkInvokeAIVariant {
@ -87,9 +99,9 @@ in
}; };
flake.nixosModules = let flake.nixosModules = let
packageModule = pkgAttrName: { pkgs, ... }: { packageModule = pkgAttrName: {pkgs, ...}: {
services.invokeai.package = withSystem pkgs.system ( services.invokeai.package = withSystem pkgs.system (
{ config, ... }: lib.mkOptionDefault config.packages.${pkgAttrName} {config, ...}: lib.mkOptionDefault config.packages.${pkgAttrName}
); );
}; };
in { in {

View file

@ -1,146 +1,144 @@
{ python3Packages {
# misc python3Packages,
, lib # misc
, src lib,
, pkgs src,
# extra deps pkgs,
}: # extra deps
}: let
let
getVersion = lib.flip lib.pipe [ getVersion = lib.flip lib.pipe [
(src: builtins.readFile "${src}/invokeai/version/invokeai_version.py") (src: builtins.readFile "${src}/invokeai/version/invokeai_version.py")
(builtins.match ".*__version__ = \"([^\"]+)\".*") (builtins.match ".*__version__ = \"([^\"]+)\".*")
builtins.head builtins.head
]; ];
in 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 { ''--run 'export INVOKEAI_ROOT="''${INVOKEAI_ROOT:-$HOME/.invokeai}"' ''
pname = "InvokeAI"; '' --run '
format = "pyproject"; if [[ ! -d "$INVOKEAI_ROOT" && "''${0##*/}" != invokeai-configure ]]
version = getVersion src; then
inherit src; echo "State directory does not exist, running invokeai-configure"
propagatedBuildInputs = with python3Packages; [ if [[ "''${NIXIFIED_AI_NONINTERACTIVE:-0}" != 0 ]]; then
semver ${placeholder "out"}/bin/invokeai-configure --yes --skip-sd-weights
mediapipe else
numpy ${placeholder "out"}/bin/invokeai-configure
torchsde fi
uvicorn fi
pyperclip '
invisible-watermark ''
fastapi ];
fastapi-events patchPhase = ''
fastapi-socketio runHook prePatch
timm
scikit-image substituteInPlace ./pyproject.toml \
controlnet-aux --replace 'setuptools~=65.5' 'setuptools' \
compel --replace 'pip~=22.3' 'pip'
python-dotenv
uvloop # Add subprocess to the imports
watchfiles substituteInPlace ./invokeai/backend/install/invokeai_configure.py --replace \
httptools 'import shutil' \
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
' '
'' import shutil
# See note about consumer GPUs: import subprocess
# 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
' '
'' # 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
patchPhase = '' # preserve the mode
runHook prePatch 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 \ substituteInPlace ./pyproject.toml \
--replace 'setuptools~=65.5' 'setuptools' \ --replace 'pip~=22.3' 'pip' \
--replace 'pip~=22.3' 'pip' --replace 'setuptools~=65.5' 'setuptools'
'';
# Add subprocess to the imports meta = {
substituteInPlace ./invokeai/backend/install/invokeai_configure.py --replace \ description = "Fancy Web UI for Stable Diffusion";
'import shutil' \ homepage = "https://invoke-ai.github.io/InvokeAI/";
' mainProgram = "invokeai-web";
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";
};
}