From 382c544488b5b3f689d3875b151b6323b78182eb Mon Sep 17 00:00:00 2001 From: James Brink Date: Wed, 31 Dec 2025 20:44:03 -0700 Subject: [PATCH 01/12] feat: Update ComfyUI to v0.7.0 with latest dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ComfyUI: 0.6.0 → 0.7.0 (released 2025-12-31) - Frontend package: 1.34.9 → 1.37.1 - Manager: 4.0.2 → 4.0.4 - Workflow templates: 0.7.59 → 0.7.65 - Workflow templates core: 0.3.43 → 0.3.65 - Workflow templates media API: 0.3.22 → 0.3.34 - Workflow templates media video: 0.3.19 → 0.3.22 - Workflow templates media image: 0.3.36 → 0.3.47 - Workflow templates media other: 0.3.47 → 0.3.63 - KJNodes: 2025-12-21 → 2025-12-28 - WanVideoWrapper: 2025-12-24 → 2025-12-31 --- nix/versions.nix | 68 ++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/nix/versions.nix b/nix/versions.nix index 28797df..cfea89b 100644 --- a/nix/versions.nix +++ b/nix/versions.nix @@ -1,9 +1,9 @@ { comfyui = { - version = "0.6.0"; - releaseDate = "2025-12-24T03:32:16Z"; - rev = "e4c61d75555036fa28b6bb34e5fd67b007c9f391"; - hash = "sha256-gd02tXWjFJ7kTGF8GT1RfVdzhXu4mM2EoQnAVt83qjQ="; + version = "0.7.0"; + releaseDate = "2025-12-31T07:50:53Z"; + rev = "f59f71cf34067d46713f6243312f7f0b360d061f"; + hash = "sha256-cMi27y1KCiZTjzx3J6FuHqEYjZjL/VChPtlUnTxHVAg="; }; vendored = { @@ -14,45 +14,45 @@ }; frontendPackage = { - version = "1.34.9"; - url = "https://files.pythonhosted.org/packages/c8/1b/0d61705cc7e74cbf98f73219ba4e643495e72ba8e13633bbd3bfcd9bb371/comfyui_frontend_package-1.34.9-py3-none-any.whl"; - hash = "sha256-g2ypUoTVcFc5RjJAw8SCanqKdycpJlanfL8LQaOa7HY="; + version = "1.37.1"; + url = "https://files.pythonhosted.org/packages/b4/2c/d398ac619998788533a3f13572c358c6db9bf19830049d04314f7414f967/comfyui_frontend_package-1.37.1-py3-none-any.whl"; + hash = "sha256-qjgzFd+FSEvYjqdXUDep8mG1sac40s6miwe6Sp6Do3Q="; }; workflowTemplates = { - version = "0.7.59"; - url = "https://files.pythonhosted.org/packages/fd/f5/6d861fa649ea1c58e410d6e8d0bd068db3677a5c057539f4a05e947a6844/comfyui_workflow_templates-0.7.59-py3-none-any.whl"; - hash = "sha256-erNdXjtaKJOkZdLGmJkLFXzSOf7knD+0rDDbDgTI/tM="; + version = "0.7.65"; + url = "https://files.pythonhosted.org/packages/d7/4e/7bf0afd53f29b0339615fff5987f205b9f0038f86079812d6e00b1c70972/comfyui_workflow_templates-0.7.65-py3-none-any.whl"; + hash = "sha256-RWdfcM4z0JE29NM7RIY9TQCK5YYR5D3zSsQzti1Ur3o="; }; workflowTemplatesCore = { - version = "0.3.43"; - url = "https://files.pythonhosted.org/packages/4f/f7/4188d3482c322986ea4be3f64ca1f3a2dad32b92746535409efa0dd63c8d/comfyui_workflow_templates_core-0.3.43-py3-none-any.whl"; - hash = "sha256-Yw5s20oVXqGlVDH4h/qmhiNCRuk+XDlSPPj1yHR2Y0w="; + version = "0.3.65"; + url = "https://files.pythonhosted.org/packages/08/d6/39686f2208c01d611267aeeaa23482abc13bce8e2b168a2a452b4e17a845/comfyui_workflow_templates_core-0.3.65-py3-none-any.whl"; + hash = "sha256-D7MwujlEAmawa0QewlwjTxgkdNu756PVaqxT/+mOtPU="; }; workflowTemplatesMediaApi = { - version = "0.3.22"; - url = "https://files.pythonhosted.org/packages/2c/ac/eeca4a06026f473fe294e6cf46b42b25ece230289bb0c9619028284670eb/comfyui_workflow_templates_media_api-0.3.22-py3-none-any.whl"; - hash = "sha256-7DuNvZpHCraEtGRaz8bQVM2BCgei5cErUSWRIeF5MXU="; + version = "0.3.34"; + url = "https://files.pythonhosted.org/packages/ab/95/3ad3a007aee5866aa99953c52d5f6111e82ff8e9273763ab23810424d89d/comfyui_workflow_templates_media_api-0.3.34-py3-none-any.whl"; + hash = "sha256-7gMGVwo1x/XN98eP5GoR4eQh62JoosJIFplKGS1QBrM="; }; workflowTemplatesMediaVideo = { - version = "0.3.19"; - url = "https://files.pythonhosted.org/packages/78/f6/1e12cfae3c41d55100916f03dffb32041fe15e805aebd4ca4a445886b624/comfyui_workflow_templates_media_video-0.3.19-py3-none-any.whl"; - hash = "sha256-+VfMz3VtbZJ722NCURNgJPGMBiIgt7yxPu3e5ENZPC0="; + version = "0.3.22"; + url = "https://files.pythonhosted.org/packages/74/be/72e7e1c6fd7b27aeb016a4d1ab96d0246dd41d8b41d9b95007b00df9578a/comfyui_workflow_templates_media_video-0.3.22-py3-none-any.whl"; + hash = "sha256-jcDfKcbpO5jgkUtxSEUTG84cgJNGISCrzG6tMecf09s="; }; workflowTemplatesMediaImage = { - version = "0.3.36"; - url = "https://files.pythonhosted.org/packages/6c/61/e3b3f2df32628fb3a42598f481a26a729512d5fd472a9eeda95757b858d5/comfyui_workflow_templates_media_image-0.3.36-py3-none-any.whl"; - hash = "sha256-D4yUfLfK4rOW6cw4Q5ryedsWUZYlPm3wqGFUm5YBbIs="; + version = "0.3.47"; + url = "https://files.pythonhosted.org/packages/30/9a/bba708199512ea0d4c03cb2248b178c847f4f158c19723e2eee76294590a/comfyui_workflow_templates_media_image-0.3.47-py3-none-any.whl"; + hash = "sha256-YbNxK5XXgXCwW7N7viaQtQuI6LLs1Cjc7fXWloPvGKc="; }; workflowTemplatesMediaOther = { - version = "0.3.47"; - url = "https://files.pythonhosted.org/packages/3b/cc/548f5fc42d8cdd8c03458baad8d17385f2e21741f8f73f7d26edaced3f80/comfyui_workflow_templates_media_other-0.3.47-py3-none-any.whl"; - hash = "sha256-CwSnKkz9PSAgLiLV6SjHjNY7u9l+N0LcicZXAkOHRd8="; + version = "0.3.63"; + url = "https://files.pythonhosted.org/packages/92/27/7959fe6008fc0bee3a360292b0ff7d47e600aad1c33b74aafad514ac643c/comfyui_workflow_templates_media_other-0.3.63-py3-none-any.whl"; + hash = "sha256-9i5pxESyYeEtFif8Q4FeU7M/zsjayO0O7tTb0/b05lg="; }; embeddedDocs = { @@ -62,9 +62,9 @@ }; manager = { - version = "4.0.2"; - url = "https://files.pythonhosted.org/packages/2e/45/42fdbe83f6fa2daf9981cd10c024197644c731db99032634bb7efc0da69a/comfyui_manager-4.0.2-py3-none-any.whl"; - hash = "sha256-W5l22ZijI0vohlgjygsaqR/zXmINxlAUKbRFOtLmsj8="; + version = "4.0.4"; + url = "https://files.pythonhosted.org/packages/24/52/ecc15ce24f7ed9c336a13553e6b4dc0777e2082f1e6afca0ecbe5e02564f/comfyui_manager-4.0.4-py3-none-any.whl"; + hash = "sha256-H08Wrr2ZDk5NfeQhF5Csr1QUBa/Ohmpvkwrp1tuRu50="; }; # Python packages not in nixpkgs (vendored for custom nodes) @@ -113,11 +113,11 @@ }; kjnodes = { - version = "2025-12-21"; + version = "2025-12-28"; owner = "kijai"; repo = "ComfyUI-KJNodes"; - rev = "79f529a84a8c20fe5dcdfa984c6be7a94102c014"; - hash = "sha256-TMaKLAeXPDM1nPCpgern6N9Ea8xHSfizzQ3PZSQN1vQ="; + rev = "7b1327192e4729085788a3020a9cbb095e0c7811"; + hash = "sha256-5poI2WQb8ZDfFFqL/INVQICgkshD61YUL2lcXw/nS+U="; }; gguf = { @@ -177,11 +177,11 @@ }; wanvideo = { - version = "2025-12-24"; + version = "2025-12-31"; owner = "kijai"; repo = "ComfyUI-WanVideoWrapper"; - rev = "95255c7ffa29d90af6b0597b10d59a7946618b61"; - hash = "sha256-i3bZ+0wTTPJbPUvIweqmmWFip0q+BuxX8qxI+xDxGqk="; + rev = "bf1d77fe155c0bdbefd3d48bf5b320dce8c55849"; + hash = "sha256-H7YMFd0LVCgY3ZpTBu1a47DQ6R25ulJkuteRV2/zgD8="; }; }; } From 34e9b3aa01dedb4dd93597774b6b874826af7913 Mon Sep 17 00:00:00 2001 From: James Brink Date: Wed, 31 Dec 2025 21:01:55 -0700 Subject: [PATCH 02/12] fix: Add ultralytics and improve ComfyUI-Manager package handling - Add ultralytics for Impact Subpack's UltralyticsDetectorProvider node - Create PEP 405 compliant venv structure for mutable package installs - Add version constraints to prevent Manager from overriding vendored packages - Set UV_CONSTRAINT alongside PIP_CONSTRAINT for uv compatibility --- nix/packages.nix | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/nix/packages.nix b/nix/packages.nix index 36f85ff..ce7e9b3 100644 --- a/nix/packages.nix +++ b/nix/packages.nix @@ -47,7 +47,7 @@ let # Pip constraints to prevent conflicts with Nix-provided packages pipConstraints = pkgs.writeText "pip-constraints.txt" '' # Auto-generated by comfyui-nix - # Prevents pip from overwriting Nix-provided packages with incompatible versions + # Prevents pip/uv from overwriting Nix-provided packages with incompatible versions huggingface-hub<1.0 transformers>=4.0.0 torch>=2.0.0 @@ -55,6 +55,11 @@ let numpy>=1.24.0 pillow>=9.0.0 safetensors>=0.3.0 + # Prevent ComfyUI-Manager from trying to "restore" vendored packages + comfyui-frontend-package>=${versions.vendored.frontendPackage.version} + comfyui-workflow-templates>=${versions.vendored.workflowTemplates.version} + comfyui-embedded-docs>=${versions.vendored.embeddedDocs.version} + comfyui-manager>=${versions.vendored.manager.version} ''; # Default ComfyUI-Manager configuration @@ -117,6 +122,8 @@ let dill # Extended pickling segment-anything # Meta AI SAM model sam2 # Meta AI SAM 2 model + # Impact Subpack dependencies + ultralytics # YOLO object detection (for UltralyticsDetectorProvider) # KJNodes dependencies mss # Screen capture # General ML utilities @@ -354,15 +361,42 @@ let # Set platform-specific library paths for GPU support ${libraryPathSetup} - # Configure pip to install packages to a mutable location - # This allows ComfyUI-Manager to install custom node dependencies + # Create a mutable PEP 405 venv structure for ComfyUI-Manager package installs + # This allows both pip and uv to install packages to a writable location # while keeping the Nix store read-only - export PIP_TARGET="$BASE_DIR/.pip-packages" - export PYTHONPATH="''${PYTHONPATH:+$PYTHONPATH:}$BASE_DIR/.pip-packages" - mkdir -p "$PIP_TARGET" + VENV_DIR="$BASE_DIR/.venv" + SITE_PACKAGES="$VENV_DIR/lib/python3.12/site-packages" + mkdir -p "$SITE_PACKAGES" + mkdir -p "$VENV_DIR/bin" + + # Create pyvenv.cfg if it doesn't exist (required for PEP 405 compliance) + if [[ ! -e "$VENV_DIR/pyvenv.cfg" ]]; then + cat > "$VENV_DIR/pyvenv.cfg" << PYVENV +home = ${pythonRuntime}/bin +include-system-site-packages = true +version = 3.12.9 +PYVENV + fi + + # Symlink Python executable into venv bin (some tools expect this) + if [[ ! -e "$VENV_DIR/bin/python" ]]; then + ln -sf "${pythonRuntime}/bin/python" "$VENV_DIR/bin/python" + ln -sf "${pythonRuntime}/bin/python3" "$VENV_DIR/bin/python3" + ln -sf "${pythonRuntime}/bin/python3.12" "$VENV_DIR/bin/python3.12" + fi + + # Set VIRTUAL_ENV so uv installs to our mutable venv instead of Nix store + export VIRTUAL_ENV="$VENV_DIR" + + # Also set PIP_TARGET for pip compatibility + export PIP_TARGET="$SITE_PACKAGES" + + # Add our mutable site-packages to Python path + export PYTHONPATH="''${PYTHONPATH:+$PYTHONPATH:}$SITE_PACKAGES" - # Prevent pip from installing packages that conflict with Nix-provided ones + # Prevent pip/uv from installing packages that conflict with Nix-provided ones export PIP_CONSTRAINT="${pipConstraints}" + export UV_CONSTRAINT="${pipConstraints}" # Set model path for custom nodes that check this env var # (prevents them from trying to write to the read-only Nix store) From c958adce0fbfd338dd1595f0df7ba24c42eebe3d Mon Sep 17 00:00:00 2001 From: James Brink Date: Wed, 31 Dec 2025 22:11:07 -0700 Subject: [PATCH 03/12] fix: Update to latest nixpkgs and fix compatibility issues - Update nixpkgs from April 2025 to December 2025 - Migrate from legacy darwin.apple_sdk.frameworks.Metal to apple-sdk_14 - Disable failing imageio test_process_termination (exit code 6 vs 2) --- flake.lock | 6 +++--- flake.nix | 2 +- nix/python-overrides.nix | 7 +++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 90c9144..c2cc24a 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1744463964, - "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", + "lastModified": 1766902085, + "narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", + "rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 38ed9b9..62429b9 100644 --- a/flake.nix +++ b/flake.nix @@ -285,7 +285,7 @@ pkgs.shellcheck pkgs.jq pkgs.curl - ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.darwin.apple_sdk.frameworks.Metal ]; + ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.apple-sdk_14 ]; shellHook = let diff --git a/nix/python-overrides.nix b/nix/python-overrides.nix index 55e8aac..c4bbaf3 100644 --- a/nix/python-overrides.nix +++ b/nix/python-overrides.nix @@ -146,6 +146,13 @@ lib.optionalAttrs (useCuda && prev ? torch) { }); } +# Disable failing ffmpeg test for imageio (test_process_termination expects exit code 2 but gets 6) +// lib.optionalAttrs (prev ? imageio) { + imageio = prev.imageio.overridePythonAttrs (old: { + disabledTests = (old.disabledTests or [ ]) ++ [ "test_process_termination" ]; + }); +} + # color-matcher - not in older nixpkgs, needed for KJNodes // { "color-matcher" = final.buildPythonPackage rec { From 03177ddbe4cda8667cec90e88fba71bcce4c9027 Mon Sep 17 00:00:00 2001 From: James Brink Date: Wed, 31 Dec 2025 22:32:11 -0700 Subject: [PATCH 04/12] fix: Increase file descriptor limit for aiohttp/grpc DNS resolver The nixpkgs update brought aiohttp 3.13.2 which uses grpc/c-ares for async DNS resolution. This consumes significantly more file descriptors per connection. Combined with ComfyUI-Manager's concurrent HTTP requests during startup, this exhausts the default macOS limit of 256 FDs. Add ulimit -n 10240 to the launcher to prevent "Too many open files" errors on both macOS and Linux. --- nix/packages.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nix/packages.nix b/nix/packages.nix index ce7e9b3..43de911 100644 --- a/nix/packages.nix +++ b/nix/packages.nix @@ -230,6 +230,11 @@ let pkgs.xdg-utils # Provides xdg-open for --open flag on Linux ]; text = '' + # Increase file descriptor limit for aiohttp/grpc DNS resolver + # macOS default (256) is too low; Linux (1024) may also be insufficient + # ComfyUI-Manager's concurrent HTTP requests with c-ares DNS can exhaust FDs + ulimit -n 10240 2>/dev/null || true + # Parse arguments - extract --base-directory, --open, --port, pass rest to ComfyUI BASE_DIR="''${COMFY_USER_DIR:-${defaultDataDir}}" OPEN_BROWSER=false From 862270d917035a506244400ee83a6db8dbc1d815 Mon Sep 17 00:00:00 2001 From: James Brink Date: Wed, 31 Dec 2025 23:37:51 -0700 Subject: [PATCH 05/12] fix: Filter Rust build artifacts from Cachix push Skip Cargo.lock, Cargo.toml, and .cargo-checksum.json files when pushing build dependencies. These intermediate files cause upload retries and aren't useful for cache consumers who pull pre-built packages. --- scripts/push-to-cachix.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/push-to-cachix.sh b/scripts/push-to-cachix.sh index fb692d9..a35ce74 100755 --- a/scripts/push-to-cachix.sh +++ b/scripts/push-to-cachix.sh @@ -149,6 +149,10 @@ if [[ "$PUSH_BUILD_DEPS" == true ]]; then else ALL_PATHS="$RUNTIME_PATHS" fi + +# Filter out Rust/Cargo build artifacts that aren't useful for consumers +# These are intermediate files that cause upload issues and aren't needed +ALL_PATHS=$(echo "$ALL_PATHS" | grep -vE '(Cargo\.lock|Cargo\.toml|\.cargo-checksum\.json)$') TOTAL_COUNT=$(echo "$ALL_PATHS" | grep -c '^' || echo 0) echo "" From 644ed3ddbef8975e6fcf912e8caab37253d1553d Mon Sep 17 00:00:00 2001 From: James Brink Date: Thu, 1 Jan 2026 00:29:54 -0700 Subject: [PATCH 06/12] fix: Add allowUnsupportedSystem for nixpkgs badPlatforms workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Work around nixpkgs-unstable issues where certain packages are marked in meta.badPlatforms even though they work: - cudnn 9.13.0 for CUDA 12.8 on x86_64-linux - kornia-rs on aarch64-linux Added allowUnsupportedSystem = true to: - mkCudaPkgs helper (CUDA builds) - pkgsLinuxX86 (x86_64 Docker images) - pkgsLinuxArm64 (aarch64 Docker images) See: https://github.com/NixOS/nixpkgs/issues/458799 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- flake.nix | 69 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/flake.nix b/flake.nix index 62429b9..6fab8c4 100644 --- a/flake.nix +++ b/flake.nix @@ -98,6 +98,9 @@ config = { allowUnfree = true; allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; + # Allow unsupported system to work around nixpkgs cudnn badPlatforms issue + # See: https://github.com/NixOS/nixpkgs/issues/458799 + allowUnsupportedSystem = true; cudaSupport = true; cudaCapabilities = capabilities; cudaForwardCompat = false; # Don't add PTX for forward compat @@ -122,6 +125,8 @@ config = { allowUnfree = true; allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; + # Allow unsupported system to work around nixpkgs badPlatforms issues + allowUnsupportedSystem = true; }; }; # Docker images use same capabilities as #cuda for cache sharing @@ -131,6 +136,8 @@ config = { allowUnfree = true; allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; + # Allow unsupported system to work around nixpkgs kornia-rs badPlatforms issue + allowUnsupportedSystem = true; }; }; @@ -216,38 +223,37 @@ && !pkgs.lib.hasPrefix "result" rel; }; - packages = + packages = { + default = nativePackages.default; + comfyui = nativePackages.default; + # Cross-platform Docker image builds (use remote builder on non-Linux) + # These are always available regardless of host system + dockerImageLinux = linuxX86Packages.dockerImage; + dockerImageLinuxCuda = linuxX86PackagesCuda.dockerImageCuda; + dockerImageLinuxArm64 = linuxArm64Packages.dockerImage; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux ( { - default = nativePackages.default; - comfyui = nativePackages.default; - # Cross-platform Docker image builds (use remote builder on non-Linux) - # These are always available regardless of host system - dockerImageLinux = linuxX86Packages.dockerImage; - dockerImageLinuxCuda = linuxX86PackagesCuda.dockerImageCuda; - dockerImageLinuxArm64 = linuxArm64Packages.dockerImage; + # Default CUDA includes all GPU architectures for max compatibility + cuda = nativePackagesCuda.default; + dockerImage = nativePackages.dockerImage; + dockerImageCuda = nativePackagesCuda.dockerImageCuda; } - // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux ( - { - # Default CUDA includes all GPU architectures for max compatibility - cuda = nativePackagesCuda.default; - dockerImage = nativePackages.dockerImage; - dockerImageCuda = nativePackagesCuda.dockerImageCuda; - } - # Architecture-specific CUDA packages - # Consumer GPUs - // { - cuda-sm61 = archPackages.sm61.default; # Pascal (GTX 1080) - cuda-sm75 = archPackages.sm75.default; # Turing (RTX 2080) - cuda-sm86 = archPackages.sm86.default; # Ampere (RTX 3080) - cuda-sm89 = archPackages.sm89.default; # Ada (RTX 4080) - } - # Data center GPUs - // { - cuda-sm70 = archPackages.sm70.default; # Volta (V100) - cuda-sm80 = archPackages.sm80.default; # Ampere DC (A100) - cuda-sm90 = archPackages.sm90.default; # Hopper (H100) - } - ); + # Architecture-specific CUDA packages + # Consumer GPUs + // { + cuda-sm61 = archPackages.sm61.default; # Pascal (GTX 1080) + cuda-sm75 = archPackages.sm75.default; # Turing (RTX 2080) + cuda-sm86 = archPackages.sm86.default; # Ampere (RTX 3080) + cuda-sm89 = archPackages.sm89.default; # Ada (RTX 4080) + } + # Data center GPUs + // { + cuda-sm70 = archPackages.sm70.default; # Volta (V100) + cuda-sm80 = archPackages.sm80.default; # Ampere DC (A100) + cuda-sm90 = archPackages.sm90.default; # Hopper (H100) + } + ); in { inherit packages; @@ -285,7 +291,8 @@ pkgs.shellcheck pkgs.jq pkgs.curl - ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.apple-sdk_14 ]; + ] + ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.apple-sdk_14 ]; shellHook = let From b724253db72b48496fbb8474c6d8ba981d27cc4e Mon Sep 17 00:00:00 2001 From: James Brink Date: Thu, 1 Jan 2026 00:46:29 -0700 Subject: [PATCH 07/12] fix: Disable cuda_compat on x86_64-linux to fix CUDA build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cuda_compat is only available for aarch64-linux (Jetson devices) but was incorrectly being pulled into the dependency tree on x86_64-linux builds. This adds an overlay to set cuda_compat = null on x86_64-linux systems, preventing the build failure "variable $src or $srcs should point to source". Combined with allowUnsupportedSystem for the cudnn badPlatforms workaround, CUDA builds now work correctly on x86_64-linux. See: https://github.com/NixOS/nixpkgs/issues/458799 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- flake.nix | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index 6fab8c4..95d7219 100644 --- a/flake.nix +++ b/flake.nix @@ -98,13 +98,26 @@ config = { allowUnfree = true; allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; - # Allow unsupported system to work around nixpkgs cudnn badPlatforms issue - # See: https://github.com/NixOS/nixpkgs/issues/458799 + # Work around nixpkgs cudnn badPlatforms issue + # cudnn 9.13.0 is incorrectly marked as unsupported on x86_64-linux allowUnsupportedSystem = true; cudaSupport = true; cudaCapabilities = capabilities; cudaForwardCompat = false; # Don't add PTX for forward compat }; + overlays = [ + # Disable cuda_compat on x86_64-linux - it's only for aarch64 Jetson devices + # and incorrectly gets pulled into dependency tree on x86_64 + # See: https://github.com/NixOS/nixpkgs/issues/458799 + (final: prev: { + cudaPackages = prev.cudaPackages.overrideScope ( + cfinal: cprev: + nixpkgs.lib.optionalAttrs (targetSystem == "x86_64-linux") { + cuda_compat = null; + } + ); + }) + ]; }; # Base pkgs without CUDA (for CPU builds and non-CUDA deps) @@ -125,8 +138,6 @@ config = { allowUnfree = true; allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; - # Allow unsupported system to work around nixpkgs badPlatforms issues - allowUnsupportedSystem = true; }; }; # Docker images use same capabilities as #cuda for cache sharing @@ -136,7 +147,7 @@ config = { allowUnfree = true; allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; - # Allow unsupported system to work around nixpkgs kornia-rs badPlatforms issue + # Work around nixpkgs kornia-rs badPlatforms issue on aarch64-linux allowUnsupportedSystem = true; }; }; From 78a41e0050e80492935b8e516b5408041b942650 Mon Sep 17 00:00:00 2001 From: James Brink Date: Fri, 2 Jan 2026 14:06:39 -0700 Subject: [PATCH 08/12] feat: Use pre-built PyTorch CUDA wheels to avoid OOM during builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch from compiling PyTorch from source to using pre-built wheels from pytorch.org for CUDA builds. This provides: - Fast builds (~2GB download vs hours of compilation) - Low memory usage (no 30-60GB RAM requirement) - All GPU architectures (Pascal through Hopper) in one package - CUDA 12.4 runtime bundled in wheels Also removes architecture-specific packages (cuda-sm61, etc.) since the wheel-based approach supports all architectures universally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 13 +- README.md | 144 +++---------- flake.nix | 200 ++--------------- nix/docker.nix | 6 +- nix/modules/comfyui.nix | 21 +- nix/packages.nix | 454 +++++++++++++++++++-------------------- nix/python-overrides.nix | 284 ++++++++++++++++++++---- nix/versions.nix | 23 ++ pyproject.toml | 3 +- 9 files changed, 562 insertions(+), 586 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index ac8ade3..8c6a74b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Build/Run Commands - **Run application**: `nix run` (default) - **Run with browser**: `nix run -- --open` (automatically opens browser) -- **Run with CUDA**: `nix run .#cuda` (Linux/NVIDIA only, uses Nix-provided CUDA PyTorch) +- **Run with CUDA**: `nix run .#cuda` (Linux/NVIDIA only, uses pre-built PyTorch CUDA wheels) - **Run with custom port**: `nix run -- --port=8080` (specify custom port) - **Run with network access**: `nix run -- --listen 0.0.0.0` (allow external connections) - **Run with debug logging**: `nix run -- --debug` or `nix run -- --verbose` @@ -30,13 +30,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - **Dev shell**: `nix develop` provides ruff and pyright for manual linting/type-checking ## Version Management -- Current ComfyUI version: v0.6.0 (pinned in `nix/versions.nix`) +- Current ComfyUI version: v0.7.0 (pinned in `nix/versions.nix`) - To update ComfyUI: modify `version`, `rev`, and `hash` in `nix/versions.nix` - Frontend/docs/template packages: vendored wheels pinned in `nix/versions.nix` - Template input files: auto-generated in `nix/template-inputs.nix` - Update with: `./scripts/update-template-inputs.sh && git add nix/template-inputs.nix` - Python version: 3.12 (stable for ML workloads) -- PyTorch: Stable releases (no nightly builds), provided by Nix +- PyTorch: CPU builds use nixpkgs; CUDA builds use pre-built wheels from pytorch.org ## Project Architecture @@ -85,8 +85,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - `DYLD_LIBRARY_PATH`: (macOS) Set automatically to include dynamic libraries ### Platform-Specific Configuration -- Uses Nix-provided PyTorch packages (no runtime detection or installs) -- CUDA support via `nix run .#cuda` (Linux/NVIDIA only) +- CPU builds use Nix-provided PyTorch packages (no runtime detection or installs) +- CUDA support via `nix run .#cuda` (Linux/NVIDIA only): + - Uses pre-built PyTorch wheels from pytorch.org (fast builds, ~2GB download) + - Supports all GPU architectures (Pascal through Hopper) in a single build + - CUDA 12.4 runtime bundled in wheels (no separate toolkit needed) - Library Paths: Automatically includes `/run/opengl-driver/lib` on Linux for NVIDIA drivers ### Data Persistence Structure diff --git a/README.md b/README.md index 2ff4586..c4947ad 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,11 @@ nix run github:utensils/comfyui-nix -- --open For CUDA (Linux/NVIDIA): -> **⚠️ Important:** CUDA builds compile PyTorch, triton, and other large packages from source, which can take **multiple hours** and requires significant RAM. **[Set up the binary cache](#binary-cache) first** to download pre-built binaries instead. - ```bash -# RTX GPUs (2000/3000/4000 series) - default nix run github:utensils/comfyui-nix#cuda - -# GTX 1080/1070/1060 (Pascal) -nix run github:utensils/comfyui-nix#cuda-sm61 - -# Data center GPUs (H100) -nix run github:utensils/comfyui-nix#cuda-sm90 ``` -See [CUDA GPU Support](#cuda-gpu-support) for all available architectures. +CUDA builds use pre-built PyTorch wheels from pytorch.org, so builds are fast (~2GB download) and support all GPU architectures from Pascal (GTX 1080) through Hopper (H100) in a single package. ## Options @@ -56,46 +47,18 @@ All [ComfyUI CLI options] are supported. Common examples: ## CUDA GPU Support -CUDA builds are available for Linux with NVIDIA GPUs. The default `#cuda` includes all GPU architectures for maximum compatibility and cache sharing with Docker images. For optimized builds targeting your specific GPU, use architecture-specific packages. - -> **📦 Before running any CUDA package:** [Set up the binary cache](#binary-cache) to avoid hours of compilation. - -### Available Architectures +CUDA builds are available for Linux with NVIDIA GPUs. The `#cuda` package uses pre-built PyTorch wheels from pytorch.org which: -| Package | SM | GPU Generation | Example GPUs | -| ------------ | --- | -------------- | ------------------------ | -| `#cuda` | All | All GPUs | Works on any NVIDIA GPU | -| `#cuda-sm61` | 6.1 | Pascal | GTX 1080, 1070, 1060 | -| `#cuda-sm75` | 7.5 | Turing | RTX 2080, 2070, GTX 1660 | -| `#cuda-sm86` | 8.6 | Ampere | RTX 3080, 3090, A10, A40 | -| `#cuda-sm89` | 8.9 | Ada Lovelace | RTX 4090, 4080, L4, L40s | -| `#cuda-sm70` | 7.0 | Volta | V100 (data center) | -| `#cuda-sm80` | 8.0 | Ampere DC | A100 (data center) | -| `#cuda-sm90` | 9.0 | Hopper | H100 (data center) | - -### Usage +- **Fast builds**: Downloads ~2GB of pre-built wheels instead of compiling for hours +- **Low memory**: No 30-60GB RAM requirement for compilation +- **All architectures**: Supports Pascal (GTX 1080) through Hopper (H100) in one package +- **Bundled runtime**: CUDA 12.4 libraries included in wheels (no separate toolkit needed) ```bash -# All GPUs (default - works everywhere, best cache hits) nix run github:utensils/comfyui-nix#cuda - -# GTX 1080 (Pascal architecture) -nix run github:utensils/comfyui-nix#cuda-sm61 - -# A100 data center GPU -nix run github:utensils/comfyui-nix#cuda-sm80 - -# H100 data center GPU -nix run github:utensils/comfyui-nix#cuda-sm90 ``` -### Why Architecture-Specific Builds? - -- **Faster builds**: Building for one architecture is much faster than all architectures -- **Better cache hits**: Pre-built packages for each architecture in the binary cache -- **Smaller closures**: Only the kernels you need are included - -The [cuda-maintainers cache](https://github.com/SomeoneSerge/nixpkgs-cuda-ci) builds for common architectures. Using matching architecture-specific packages maximizes cache hits and minimizes build time. +This single package works on any NVIDIA GPU from the past ~8 years. ## Why a Nix Flake? @@ -292,17 +255,10 @@ Add ComfyUI as a package in your system configuration: The overlay provides these packages: -| Package | Description | -| ------------------------ | -------------------------------------------------- | -| `pkgs.comfy-ui` | CPU + Apple Silicon (Metal) - use this for macOS | -| `pkgs.comfy-ui-cuda` | All NVIDIA GPU architectures (Linux only) | -| `pkgs.comfy-ui-cuda-sm61`| Pascal (GTX 1080, 1070, 1060) | -| `pkgs.comfy-ui-cuda-sm70`| Volta (V100) | -| `pkgs.comfy-ui-cuda-sm75`| Turing (RTX 2080, 2070, GTX 1660) | -| `pkgs.comfy-ui-cuda-sm80`| Ampere DC (A100) | -| `pkgs.comfy-ui-cuda-sm86`| Ampere (RTX 3080, 3090) | -| `pkgs.comfy-ui-cuda-sm89`| Ada Lovelace (RTX 4090, 4080) | -| `pkgs.comfy-ui-cuda-sm90`| Hopper (H100) | +| Package | Description | +| -------------------- | ------------------------------------------------ | +| `pkgs.comfy-ui` | CPU + Apple Silicon (Metal) - use this for macOS | +| `pkgs.comfy-ui-cuda` | NVIDIA GPUs (Linux only, all architectures) | > **Note:** On macOS with Apple Silicon, the base `comfy-ui` package automatically uses Metal for GPU acceleration. No separate CUDA package is needed. @@ -343,50 +299,22 @@ nix profile add github:utensils/comfyui-nix#cuda ### Module Options -| Option | Default | Description | -| ------------------ | -------------------- | ------------------------------------------------------------------------------ | -| `enable` | `false` | Enable the ComfyUI service | -| `cuda` | `false` | Enable NVIDIA GPU acceleration (targets RTX by default) | -| `cudaArch` | `null` | Pre-built architecture: `sm61`, `sm70`, `sm75`, `sm80`, `sm86`, `sm89`, `sm90` | -| `cudaCapabilities` | `null` | Custom CUDA capabilities list (triggers source build) | -| `enableManager` | `false` | Enable the built-in ComfyUI Manager | -| `port` | `8188` | Port for the web interface | -| `listenAddress` | `"127.0.0.1"` | Listen address (`"0.0.0.0"` for network access) | -| `dataDir` | `"/var/lib/comfyui"` | Data directory for models, outputs, custom nodes | -| `user` | `"comfyui"` | User account to run ComfyUI under | -| `group` | `"comfyui"` | Group to run ComfyUI under | -| `createUser` | `true` | Create the comfyui system user/group | -| `openFirewall` | `false` | Open the port in the firewall | -| `extraArgs` | `[]` | Additional CLI arguments | -| `environment` | `{}` | Environment variables for the service | -| `customNodes` | `{}` | Declarative custom nodes (see below) | -| `requiresMounts` | `[]` | Mount units to wait for before starting | - -### GPU Architecture Selection - -The module provides three ways to configure CUDA support: - -```nix -# Option 1: Default build (all GPU architectures) -services.comfyui = { - enable = true; - cuda = true; -}; - -# Option 2: Pre-built architecture-specific package (fast, cached) -services.comfyui = { - enable = true; - cudaArch = "sm61"; # GTX 1080 -}; - -# Option 3: Custom capabilities (compiles from source) -services.comfyui = { - enable = true; - cudaCapabilities = [ "6.1" "8.6" ]; # Pascal + Ampere -}; -``` - -Priority order: `cudaCapabilities` > `cudaArch` > `cuda` > CPU +| Option | Default | Description | +| --------------- | -------------------- | ------------------------------------------------ | +| `enable` | `false` | Enable the ComfyUI service | +| `cuda` | `false` | Enable NVIDIA GPU acceleration | +| `enableManager` | `false` | Enable the built-in ComfyUI Manager | +| `port` | `8188` | Port for the web interface | +| `listenAddress` | `"127.0.0.1"` | Listen address (`"0.0.0.0"` for network access) | +| `dataDir` | `"/var/lib/comfyui"` | Data directory for models, outputs, custom nodes | +| `user` | `"comfyui"` | User account to run ComfyUI under | +| `group` | `"comfyui"` | Group to run ComfyUI under | +| `createUser` | `true` | Create the comfyui system user/group | +| `openFirewall` | `false` | Open the port in the firewall | +| `extraArgs` | `[]` | Additional CLI arguments | +| `environment` | `{}` | Environment variables for the service | +| `customNodes` | `{}` | Declarative custom nodes (see below) | +| `requiresMounts`| `[]` | Mount units to wait for before starting | **Note:** When `dataDir` is under `/home/`, `ProtectHome` is automatically disabled to allow access. @@ -490,22 +418,6 @@ nix flake check # Run all checks (build, lint, type-check, nixfmt) nix run .#update # Check for ComfyUI updates ``` -### Building CUDA Packages from Source - -CUDA builds (PyTorch, magma, triton, bitsandbytes) are memory-intensive. If you're building from source and experience OOM kills, limit parallelism: - -```bash -# Recommended for 32-64GB RAM -nix build .#cuda --max-jobs 2 --cores 12 - -# Conservative for 16-32GB RAM -nix build .#cuda --max-jobs 1 --cores 8 - -# Minimal for <16GB RAM (slow but safe) -nix build .#cuda --max-jobs 1 --cores 4 -``` - -Use the [binary cache](#binary-cache) when possible to avoid building CUDA packages entirely. ## Data Structure @@ -524,7 +436,7 @@ ComfyUI runs from the Nix store; only user data lives in your data directory. ## Binary Cache -> **⚠️ Highly recommended for CUDA users:** Without the binary cache, CUDA builds compile PyTorch, magma, triton, bitsandbytes, and other CUDA packages from source. This can take **multiple hours** and requires significant RAM (32GB+ recommended). With the cache, you download pre-built binaries in minutes. +The binary cache speeds up builds by downloading pre-built packages instead of compiling from source. **Quick setup (recommended):** diff --git a/flake.nix b/flake.nix index 95d7219..42467da 100644 --- a/flake.nix +++ b/flake.nix @@ -32,95 +32,18 @@ system: let # ======================================================================= - # CUDA Architecture Configuration + # CUDA Support via Pre-built Wheels # ======================================================================= - # Define CUDA compute capabilities for different GPU generations. - # - # Default (#cuda) includes ALL architectures for maximum compatibility - # and cache sharing with Docker images. - # - # Users wanting optimized builds for specific GPUs can use: - # nix run .#cuda-sm86 (for RTX 3080, etc.) + # CUDA support uses pre-built PyTorch wheels from pytorch.org instead of + # compiling from source. This provides: + # - Fast builds (download ~2GB vs compile for hours) + # - Low memory usage (no 30-60GB RAM requirement) + # - All GPU architectures supported (Pascal through Hopper) + # - CUDA 12.4 runtime bundled in wheels # ======================================================================= - # All common CUDA architectures - used for both #cuda and Docker images - # This ensures cache sharing between local builds and Docker - # Users wanting optimized builds can use #cuda-sm* variants - allCudaCapabilities = [ - "6.1" # Pascal (GTX 1080, 1070, 1060) - "7.0" # Volta (V100) - "7.5" # Turing (RTX 2080, 2070, GTX 1660) - "8.0" # Ampere Datacenter (A100) - "8.6" # Ampere (RTX 3080, 3090, 3070) - "8.9" # Ada Lovelace (RTX 4090, 4080, 4070) - "9.0" # Hopper (H100) - ]; - - # Architecture-specific capabilities for targeted/optimized builds - cudaArchitectures = { - # Consumer GPUs - sm61 = { - capabilities = [ "6.1" ]; - description = "Pascal (GTX 1080, 1070, 1060)"; - }; - sm75 = { - capabilities = [ "7.5" ]; - description = "Turing (RTX 2080, 2070, GTX 1660)"; - }; - sm86 = { - capabilities = [ "8.6" ]; - description = "Ampere (RTX 3080, 3090, 3070)"; - }; - sm89 = { - capabilities = [ "8.9" ]; - description = "Ada Lovelace (RTX 4090, 4080, 4070)"; - }; - # Data center GPUs - sm70 = { - capabilities = [ "7.0" ]; - description = "Volta (V100)"; - }; - sm80 = { - capabilities = [ "8.0" ]; - description = "Ampere Datacenter (A100)"; - }; - sm90 = { - capabilities = [ "9.0" ]; - description = "Hopper (H100)"; - }; - }; - - # Helper to create nixpkgs with specific CUDA capabilities - mkCudaPkgs = - targetSystem: capabilities: - import nixpkgs { - system = targetSystem; - config = { - allowUnfree = true; - allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; - # Work around nixpkgs cudnn badPlatforms issue - # cudnn 9.13.0 is incorrectly marked as unsupported on x86_64-linux - allowUnsupportedSystem = true; - cudaSupport = true; - cudaCapabilities = capabilities; - cudaForwardCompat = false; # Don't add PTX for forward compat - }; - overlays = [ - # Disable cuda_compat on x86_64-linux - it's only for aarch64 Jetson devices - # and incorrectly gets pulled into dependency tree on x86_64 - # See: https://github.com/NixOS/nixpkgs/issues/458799 - (final: prev: { - cudaPackages = prev.cudaPackages.overrideScope ( - cfinal: cprev: - nixpkgs.lib.optionalAttrs (targetSystem == "x86_64-linux") { - cuda_compat = null; - } - ); - }) - ]; - }; - - # Base pkgs without CUDA (for CPU builds and non-CUDA deps) + # Base pkgs (used for both CPU and CUDA builds) + # CUDA support comes from pre-built wheels, not nixpkgs cudaPackages pkgs = import nixpkgs { inherit system; config = { @@ -129,9 +52,6 @@ }; }; - # CUDA pkgs with all capabilities (default for #cuda, same as Docker) - pkgsCuda = mkCudaPkgs system allCudaCapabilities; - # Linux pkgs for cross-building Docker images from any system pkgsLinuxX86 = import nixpkgs { system = "x86_64-linux"; @@ -140,8 +60,6 @@ allowBrokenPredicate = pkg: (pkg.pname or "") == "open-clip-torch"; }; }; - # Docker images use same capabilities as #cuda for cache sharing - pkgsLinuxX86Cuda = mkCudaPkgs "x86_64-linux" allCudaCapabilities; pkgsLinuxArm64 = import nixpkgs { system = "aarch64-linux"; config = { @@ -187,23 +105,13 @@ # Linux packages for Docker image cross-builds linuxX86Packages = mkComfyPackages pkgsLinuxX86 { }; - # Docker CUDA images include all architectures for broad compatibility - linuxX86PackagesCuda = mkComfyPackages pkgsLinuxX86Cuda { cudaSupport = true; }; + # Docker CUDA images use pre-built wheels (all architectures supported) + linuxX86PackagesCuda = mkComfyPackages pkgsLinuxX86 { cudaSupport = true; }; linuxArm64Packages = mkComfyPackages pkgsLinuxArm64 { }; nativePackages = mkComfyPackages pkgs { }; - # Default CUDA uses all capabilities (same as Docker for cache sharing) - nativePackagesCuda = mkComfyPackages pkgsCuda { cudaSupport = true; }; - - # Architecture-specific CUDA packages (only on Linux) - mkArchPackage = - arch: - let - archPkgs = mkCudaPkgs system arch.capabilities; - in - mkComfyPackages archPkgs { cudaSupport = true; }; - - archPackages = pkgs.lib.mapAttrs (name: arch: mkArchPackage arch) cudaArchitectures; + # CUDA uses pre-built wheels (supports all GPU architectures) + nativePackagesCuda = mkComfyPackages pkgs { cudaSupport = true; }; pythonEnv = mkPythonEnv pkgs; @@ -243,46 +151,19 @@ dockerImageLinuxCuda = linuxX86PackagesCuda.dockerImageCuda; dockerImageLinuxArm64 = linuxArm64Packages.dockerImage; } - // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux ( - { - # Default CUDA includes all GPU architectures for max compatibility - cuda = nativePackagesCuda.default; - dockerImage = nativePackages.dockerImage; - dockerImageCuda = nativePackagesCuda.dockerImageCuda; - } - # Architecture-specific CUDA packages - # Consumer GPUs - // { - cuda-sm61 = archPackages.sm61.default; # Pascal (GTX 1080) - cuda-sm75 = archPackages.sm75.default; # Turing (RTX 2080) - cuda-sm86 = archPackages.sm86.default; # Ampere (RTX 3080) - cuda-sm89 = archPackages.sm89.default; # Ada (RTX 4080) - } - # Data center GPUs - // { - cuda-sm70 = archPackages.sm70.default; # Volta (V100) - cuda-sm80 = archPackages.sm80.default; # Ampere DC (A100) - cuda-sm90 = archPackages.sm90.default; # Hopper (H100) - } - ); + // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux { + # CUDA package uses pre-built wheels (supports all GPU architectures) + cuda = nativePackagesCuda.default; + dockerImage = nativePackages.dockerImage; + dockerImageCuda = nativePackagesCuda.dockerImageCuda; + }; in { inherit packages; - # Expose custom nodes and CUDA helpers for direct use + # Expose custom nodes for direct use legacyPackages = { customNodes = customNodes; - # Expose CUDA architecture info for module/overlay consumers - cudaArchitectures = cudaArchitectures; - allCudaCapabilities = allCudaCapabilities; - # Helper function to build ComfyUI with custom CUDA capabilities - # Usage: mkComfyUIWithCuda [ "6.1" "8.6" ] - mkComfyUIWithCuda = - capabilities: - let - customPkgs = mkCudaPkgs system capabilities; - in - (mkComfyPackages customPkgs { cudaSupport = true; }).default; }; apps = import ./nix/apps.nix { @@ -342,51 +223,12 @@ comfyui-nix = self.legacyPackages.${final.system}; comfyui = self.packages.${final.system}.default; comfy-ui = self.packages.${final.system}.default; - # CUDA variant (Linux only) - includes all GPU architectures - # Use comfy-ui-cuda-sm* for optimized single-architecture builds + # CUDA variant (Linux only) - uses pre-built wheels supporting all GPU architectures comfy-ui-cuda = if final.stdenv.isLinux then self.packages.${final.system}.cuda else throw "comfy-ui-cuda is only available on Linux"; - # Architecture-specific CUDA packages (Linux only) - # Consumer GPUs - comfy-ui-cuda-sm61 = - if final.stdenv.isLinux then - self.packages.${final.system}.cuda-sm61 - else - throw "CUDA packages are only available on Linux"; - comfy-ui-cuda-sm75 = - if final.stdenv.isLinux then - self.packages.${final.system}.cuda-sm75 - else - throw "CUDA packages are only available on Linux"; - comfy-ui-cuda-sm86 = - if final.stdenv.isLinux then - self.packages.${final.system}.cuda-sm86 - else - throw "CUDA packages are only available on Linux"; - comfy-ui-cuda-sm89 = - if final.stdenv.isLinux then - self.packages.${final.system}.cuda-sm89 - else - throw "CUDA packages are only available on Linux"; - # Data center GPUs - comfy-ui-cuda-sm70 = - if final.stdenv.isLinux then - self.packages.${final.system}.cuda-sm70 - else - throw "CUDA packages are only available on Linux"; - comfy-ui-cuda-sm80 = - if final.stdenv.isLinux then - self.packages.${final.system}.cuda-sm80 - else - throw "CUDA packages are only available on Linux"; - comfy-ui-cuda-sm90 = - if final.stdenv.isLinux then - self.packages.${final.system}.cuda-sm90 - else - throw "CUDA packages are only available on Linux"; # Add custom nodes to overlay comfyui-custom-nodes = self.legacyPackages.${final.system}.customNodes; }; diff --git a/nix/docker.nix b/nix/docker.nix index eed79ae..333c58f 100644 --- a/nix/docker.nix +++ b/nix/docker.nix @@ -36,7 +36,8 @@ "ComfyUI - The most powerful and modular diffusion model GUI"; "org.opencontainers.image.source" = "https://github.com/utensils/comfyui-nix"; "org.opencontainers.image.licenses" = "GPL-3.0"; - } // extraLabels; + } + // extraLabels; in pkgs.dockerTools.buildImage { inherit name tag; @@ -71,7 +72,8 @@ Cmd = [ "--listen" "0.0.0.0" - ] ++ lib.optionals (!cudaSupport) [ "--cpu" ]; + ] + ++ lib.optionals (!cudaSupport) [ "--cpu" ]; Env = baseEnv ++ cudaEnv; ExposedPorts = { "8188/tcp" = { }; diff --git a/nix/modules/comfyui.nix b/nix/modules/comfyui.nix index bf1999b..98cbfb0 100644 --- a/nix/modules/comfyui.nix +++ b/nix/modules/comfyui.nix @@ -34,17 +34,16 @@ let else # CPU-only pkgs.comfy-ui; - args = - [ - "--listen" - cfg.listenAddress - "--port" - (toString cfg.port) - "--base-directory" - cfg.dataDir - ] - ++ lib.optional cfg.enableManager "--enable-manager" - ++ cfg.extraArgs; + args = [ + "--listen" + cfg.listenAddress + "--port" + (toString cfg.port) + "--base-directory" + cfg.dataDir + ] + ++ lib.optional cfg.enableManager "--enable-manager" + ++ cfg.extraArgs; env = cfg.environment; escapedArgs = lib.concatStringsSep " " (map lib.escapeShellArg args); execStart = "${cfg.package}/bin/comfy-ui ${escapedArgs}"; diff --git a/nix/packages.nix b/nix/packages.nix index 43de911..4149481 100644 --- a/nix/packages.nix +++ b/nix/packages.nix @@ -219,219 +219,218 @@ let # Minimal launcher using writeShellApplication (Nix best practice) comfyUiLauncher = pkgs.writeShellApplication { name = "comfy-ui"; - runtimeInputs = - [ - pkgs.coreutils - pkgs.findutils - pkgs.gnused - pkgs.git # Required for ComfyUI Manager to clone custom nodes - ] - ++ lib.optionals (!pkgs.stdenv.isDarwin) [ - pkgs.xdg-utils # Provides xdg-open for --open flag on Linux - ]; + runtimeInputs = [ + pkgs.coreutils + pkgs.findutils + pkgs.gnused + pkgs.git # Required for ComfyUI Manager to clone custom nodes + ] + ++ lib.optionals (!pkgs.stdenv.isDarwin) [ + pkgs.xdg-utils # Provides xdg-open for --open flag on Linux + ]; text = '' - # Increase file descriptor limit for aiohttp/grpc DNS resolver - # macOS default (256) is too low; Linux (1024) may also be insufficient - # ComfyUI-Manager's concurrent HTTP requests with c-ares DNS can exhaust FDs - ulimit -n 10240 2>/dev/null || true - - # Parse arguments - extract --base-directory, --open, --port, pass rest to ComfyUI - BASE_DIR="''${COMFY_USER_DIR:-${defaultDataDir}}" - OPEN_BROWSER=false - PORT=8188 - COMFY_ARGS=() - - while [[ $# -gt 0 ]]; do - case "$1" in - --base-directory=*) - BASE_DIR="''${1#*=}" - shift - ;; - --base-directory) - BASE_DIR="$2" - shift 2 - ;; - --port=*) - PORT="''${1#*=}" - COMFY_ARGS+=("$1") - shift - ;; - --port) - PORT="$2" - COMFY_ARGS+=("$1" "$2") - shift 2 - ;; - --open) - OPEN_BROWSER=true - shift - ;; - *) - COMFY_ARGS+=("$1") - shift - ;; - esac - done - - # Expand ~ in BASE_DIR (handles both ~/path and ~user/path) - BASE_DIR="''${BASE_DIR/#\~/$HOME}" - - # Create directory structure (idempotent) - mkdir -p "$BASE_DIR"/{models,output,input,user,custom_nodes,temp} - mkdir -p "$BASE_DIR/models"/{checkpoints,loras,vae,controlnet,embeddings,upscale_models,clip,clip_vision,diffusion_models,text_encoders,unet,configs,diffusers,vae_approx,gligen,hypernetworks,photomaker,style_models} - - # Link template input files for workflow templates - # These are pre-fetched at Nix build time for pure, reproducible builds - if [[ -d "${templateInputs}/input" ]]; then - for input_file in "${templateInputs}"/input/*; do - if [[ -e "$input_file" ]]; then - filename=$(basename "$input_file") - target="$BASE_DIR/input/$filename" - # Only create symlink if file doesn't exist (don't overwrite user files) - if [[ ! -e "$target" ]]; then - ln -sf "$input_file" "$target" + # Increase file descriptor limit for aiohttp/grpc DNS resolver + # macOS default (256) is too low; Linux (1024) may also be insufficient + # ComfyUI-Manager's concurrent HTTP requests with c-ares DNS can exhaust FDs + ulimit -n 10240 2>/dev/null || true + + # Parse arguments - extract --base-directory, --open, --port, pass rest to ComfyUI + BASE_DIR="''${COMFY_USER_DIR:-${defaultDataDir}}" + OPEN_BROWSER=false + PORT=8188 + COMFY_ARGS=() + + while [[ $# -gt 0 ]]; do + case "$1" in + --base-directory=*) + BASE_DIR="''${1#*=}" + shift + ;; + --base-directory) + BASE_DIR="$2" + shift 2 + ;; + --port=*) + PORT="''${1#*=}" + COMFY_ARGS+=("$1") + shift + ;; + --port) + PORT="$2" + COMFY_ARGS+=("$1" "$2") + shift 2 + ;; + --open) + OPEN_BROWSER=true + shift + ;; + *) + COMFY_ARGS+=("$1") + shift + ;; + esac + done + + # Expand ~ in BASE_DIR (handles both ~/path and ~user/path) + BASE_DIR="''${BASE_DIR/#\~/$HOME}" + + # Create directory structure (idempotent) + mkdir -p "$BASE_DIR"/{models,output,input,user,custom_nodes,temp} + mkdir -p "$BASE_DIR/models"/{checkpoints,loras,vae,controlnet,embeddings,upscale_models,clip,clip_vision,diffusion_models,text_encoders,unet,configs,diffusers,vae_approx,gligen,hypernetworks,photomaker,style_models} + + # Link template input files for workflow templates + # These are pre-fetched at Nix build time for pure, reproducible builds + if [[ -d "${templateInputs}/input" ]]; then + for input_file in "${templateInputs}"/input/*; do + if [[ -e "$input_file" ]]; then + filename=$(basename "$input_file") + target="$BASE_DIR/input/$filename" + # Only create symlink if file doesn't exist (don't overwrite user files) + if [[ ! -e "$target" ]]; then + ln -sf "$input_file" "$target" + fi + fi + done fi - fi - done - fi - - # Link our bundled custom nodes - # Remove stale directories if they exist but aren't symlinks - for node_dir in "model_downloader" "ComfyUI-Impact-Pack" "rgthree-comfy" "ComfyUI-KJNodes" "ComfyUI-GGUF" "ComfyUI-LTXVideo" "ComfyUI-Florence2" "ComfyUI_bitsandbytes_NF4" "x-flux-comfyui" "ComfyUI-MMAudio" "PuLID_ComfyUI" "ComfyUI-WanVideoWrapper"; do - if [[ -e "$BASE_DIR/custom_nodes/$node_dir" && ! -L "$BASE_DIR/custom_nodes/$node_dir" ]]; then - rm -rf "$BASE_DIR/custom_nodes/$node_dir" - fi - done - - # On macOS, remove Linux-only nodes if they were linked previously - # Note: PuLID now works on macOS via CoreML (insightface override removes mxnet dependency) - if [[ "$(uname)" == "Darwin" ]]; then - rm -f "$BASE_DIR/custom_nodes/ComfyUI_bitsandbytes_NF4" 2>/dev/null || true - fi - - # Clean up stale read-only web extension directories (from Nix store) - if [[ -d "$BASE_DIR/web/extensions" ]]; then - find "$BASE_DIR/web/extensions" -maxdepth 1 -type d ! -writable -exec rm -rf {} \; 2>/dev/null || true - fi - - # Link bundled nodes - if [[ ! -e "$BASE_DIR/custom_nodes/model_downloader" ]]; then - ln -sf "${modelDownloaderDir}" "$BASE_DIR/custom_nodes/model_downloader" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-Impact-Pack" ]]; then - ln -sf "${customNodes.impact-pack}" "$BASE_DIR/custom_nodes/ComfyUI-Impact-Pack" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/rgthree-comfy" ]]; then - ln -sf "${customNodes.rgthree-comfy}" "$BASE_DIR/custom_nodes/rgthree-comfy" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-KJNodes" ]]; then - ln -sf "${customNodes.kjnodes}" "$BASE_DIR/custom_nodes/ComfyUI-KJNodes" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-GGUF" ]]; then - ln -sf "${customNodes.gguf}" "$BASE_DIR/custom_nodes/ComfyUI-GGUF" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-LTXVideo" ]]; then - ln -sf "${customNodes.ltxvideo}" "$BASE_DIR/custom_nodes/ComfyUI-LTXVideo" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-Florence2" ]]; then - ln -sf "${customNodes.florence2}" "$BASE_DIR/custom_nodes/ComfyUI-Florence2" - fi - # bitsandbytes requires CUDA (Linux-only) - if [[ "$(uname)" != "Darwin" && ! -e "$BASE_DIR/custom_nodes/ComfyUI_bitsandbytes_NF4" ]]; then - ln -sf "${customNodes.bitsandbytes-nf4}" "$BASE_DIR/custom_nodes/ComfyUI_bitsandbytes_NF4" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/x-flux-comfyui" ]]; then - ln -sf "${customNodes.x-flux}" "$BASE_DIR/custom_nodes/x-flux-comfyui" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-MMAudio" ]]; then - ln -sf "${customNodes.mmaudio}" "$BASE_DIR/custom_nodes/ComfyUI-MMAudio" - fi - # PuLID - face ID for consistent face generation - # Works on all platforms: Linux uses CUDA, macOS uses CoreML via onnxruntime - if [[ ! -e "$BASE_DIR/custom_nodes/PuLID_ComfyUI" ]]; then - ln -sf "${customNodes.pulid}" "$BASE_DIR/custom_nodes/PuLID_ComfyUI" - fi - if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-WanVideoWrapper" ]]; then - ln -sf "${customNodes.wanvideo}" "$BASE_DIR/custom_nodes/ComfyUI-WanVideoWrapper" - fi - - # Create default ComfyUI-Manager config if it doesn't exist - MANAGER_CONFIG_DIR="$BASE_DIR/user/default/ComfyUI-Manager" - MANAGER_CONFIG="$MANAGER_CONFIG_DIR/config.ini" - if [[ ! -e "$MANAGER_CONFIG" ]]; then - mkdir -p "$MANAGER_CONFIG_DIR" - cp "${managerConfig}" "$MANAGER_CONFIG" - echo "Created default ComfyUI-Manager config at $MANAGER_CONFIG" - fi - - # Set platform-specific library paths for GPU support - ${libraryPathSetup} - - # Create a mutable PEP 405 venv structure for ComfyUI-Manager package installs - # This allows both pip and uv to install packages to a writable location - # while keeping the Nix store read-only - VENV_DIR="$BASE_DIR/.venv" - SITE_PACKAGES="$VENV_DIR/lib/python3.12/site-packages" - mkdir -p "$SITE_PACKAGES" - mkdir -p "$VENV_DIR/bin" - - # Create pyvenv.cfg if it doesn't exist (required for PEP 405 compliance) - if [[ ! -e "$VENV_DIR/pyvenv.cfg" ]]; then - cat > "$VENV_DIR/pyvenv.cfg" << PYVENV -home = ${pythonRuntime}/bin -include-system-site-packages = true -version = 3.12.9 -PYVENV - fi - - # Symlink Python executable into venv bin (some tools expect this) - if [[ ! -e "$VENV_DIR/bin/python" ]]; then - ln -sf "${pythonRuntime}/bin/python" "$VENV_DIR/bin/python" - ln -sf "${pythonRuntime}/bin/python3" "$VENV_DIR/bin/python3" - ln -sf "${pythonRuntime}/bin/python3.12" "$VENV_DIR/bin/python3.12" - fi - - # Set VIRTUAL_ENV so uv installs to our mutable venv instead of Nix store - export VIRTUAL_ENV="$VENV_DIR" - - # Also set PIP_TARGET for pip compatibility - export PIP_TARGET="$SITE_PACKAGES" - - # Add our mutable site-packages to Python path - export PYTHONPATH="''${PYTHONPATH:+$PYTHONPATH:}$SITE_PACKAGES" - - # Prevent pip/uv from installing packages that conflict with Nix-provided ones - export PIP_CONSTRAINT="${pipConstraints}" - export UV_CONSTRAINT="${pipConstraints}" - - # Set model path for custom nodes that check this env var - # (prevents them from trying to write to the read-only Nix store) - export COMFYUI_MODEL_PATH="$BASE_DIR/models" - - # Redirect PyTorch hub downloads to data directory - # This prevents attempts to write to the read-only Nix store - export TORCH_HOME="$BASE_DIR/.cache/torch" - mkdir -p "$TORCH_HOME" - - # Redirect HuggingFace cache to data directory for model downloads - export HF_HOME="$BASE_DIR/.cache/huggingface" - mkdir -p "$HF_HOME" - - # Redirect facexlib model downloads to data directory - # (facexlib is patched to respect this env var) - export FACEXLIB_MODELPATH="$BASE_DIR/.cache/facexlib" - mkdir -p "$FACEXLIB_MODELPATH/facexlib/weights" - - # Open browser if requested (background, after short delay) - if [[ "$OPEN_BROWSER" == "true" ]]; then - (sleep 3 && ${browserCommand} "http://127.0.0.1:$PORT" 2>/dev/null) & - fi - - # Run ComfyUI directly from Nix store - exec "${pythonRuntime}/bin/python" "${comfyuiSrc}/main.py" \ - --base-directory "$BASE_DIR" \ - --front-end-root "${frontendRoot}" \ - --database-url "sqlite:///$BASE_DIR/user/comfyui.db" \ - "''${COMFY_ARGS[@]}" + + # Link our bundled custom nodes + # Remove stale directories if they exist but aren't symlinks + for node_dir in "model_downloader" "ComfyUI-Impact-Pack" "rgthree-comfy" "ComfyUI-KJNodes" "ComfyUI-GGUF" "ComfyUI-LTXVideo" "ComfyUI-Florence2" "ComfyUI_bitsandbytes_NF4" "x-flux-comfyui" "ComfyUI-MMAudio" "PuLID_ComfyUI" "ComfyUI-WanVideoWrapper"; do + if [[ -e "$BASE_DIR/custom_nodes/$node_dir" && ! -L "$BASE_DIR/custom_nodes/$node_dir" ]]; then + rm -rf "$BASE_DIR/custom_nodes/$node_dir" + fi + done + + # On macOS, remove Linux-only nodes if they were linked previously + # Note: PuLID now works on macOS via CoreML (insightface override removes mxnet dependency) + if [[ "$(uname)" == "Darwin" ]]; then + rm -f "$BASE_DIR/custom_nodes/ComfyUI_bitsandbytes_NF4" 2>/dev/null || true + fi + + # Clean up stale read-only web extension directories (from Nix store) + if [[ -d "$BASE_DIR/web/extensions" ]]; then + find "$BASE_DIR/web/extensions" -maxdepth 1 -type d ! -writable -exec rm -rf {} \; 2>/dev/null || true + fi + + # Link bundled nodes + if [[ ! -e "$BASE_DIR/custom_nodes/model_downloader" ]]; then + ln -sf "${modelDownloaderDir}" "$BASE_DIR/custom_nodes/model_downloader" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-Impact-Pack" ]]; then + ln -sf "${customNodes.impact-pack}" "$BASE_DIR/custom_nodes/ComfyUI-Impact-Pack" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/rgthree-comfy" ]]; then + ln -sf "${customNodes.rgthree-comfy}" "$BASE_DIR/custom_nodes/rgthree-comfy" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-KJNodes" ]]; then + ln -sf "${customNodes.kjnodes}" "$BASE_DIR/custom_nodes/ComfyUI-KJNodes" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-GGUF" ]]; then + ln -sf "${customNodes.gguf}" "$BASE_DIR/custom_nodes/ComfyUI-GGUF" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-LTXVideo" ]]; then + ln -sf "${customNodes.ltxvideo}" "$BASE_DIR/custom_nodes/ComfyUI-LTXVideo" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-Florence2" ]]; then + ln -sf "${customNodes.florence2}" "$BASE_DIR/custom_nodes/ComfyUI-Florence2" + fi + # bitsandbytes requires CUDA (Linux-only) + if [[ "$(uname)" != "Darwin" && ! -e "$BASE_DIR/custom_nodes/ComfyUI_bitsandbytes_NF4" ]]; then + ln -sf "${customNodes.bitsandbytes-nf4}" "$BASE_DIR/custom_nodes/ComfyUI_bitsandbytes_NF4" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/x-flux-comfyui" ]]; then + ln -sf "${customNodes.x-flux}" "$BASE_DIR/custom_nodes/x-flux-comfyui" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-MMAudio" ]]; then + ln -sf "${customNodes.mmaudio}" "$BASE_DIR/custom_nodes/ComfyUI-MMAudio" + fi + # PuLID - face ID for consistent face generation + # Works on all platforms: Linux uses CUDA, macOS uses CoreML via onnxruntime + if [[ ! -e "$BASE_DIR/custom_nodes/PuLID_ComfyUI" ]]; then + ln -sf "${customNodes.pulid}" "$BASE_DIR/custom_nodes/PuLID_ComfyUI" + fi + if [[ ! -e "$BASE_DIR/custom_nodes/ComfyUI-WanVideoWrapper" ]]; then + ln -sf "${customNodes.wanvideo}" "$BASE_DIR/custom_nodes/ComfyUI-WanVideoWrapper" + fi + + # Create default ComfyUI-Manager config if it doesn't exist + MANAGER_CONFIG_DIR="$BASE_DIR/user/default/ComfyUI-Manager" + MANAGER_CONFIG="$MANAGER_CONFIG_DIR/config.ini" + if [[ ! -e "$MANAGER_CONFIG" ]]; then + mkdir -p "$MANAGER_CONFIG_DIR" + cp "${managerConfig}" "$MANAGER_CONFIG" + echo "Created default ComfyUI-Manager config at $MANAGER_CONFIG" + fi + + # Set platform-specific library paths for GPU support + ${libraryPathSetup} + + # Create a mutable PEP 405 venv structure for ComfyUI-Manager package installs + # This allows both pip and uv to install packages to a writable location + # while keeping the Nix store read-only + VENV_DIR="$BASE_DIR/.venv" + SITE_PACKAGES="$VENV_DIR/lib/python3.12/site-packages" + mkdir -p "$SITE_PACKAGES" + mkdir -p "$VENV_DIR/bin" + + # Create pyvenv.cfg if it doesn't exist (required for PEP 405 compliance) + if [[ ! -e "$VENV_DIR/pyvenv.cfg" ]]; then + cat > "$VENV_DIR/pyvenv.cfg" << PYVENV + home = ${pythonRuntime}/bin + include-system-site-packages = true + version = 3.12.9 + PYVENV + fi + + # Symlink Python executable into venv bin (some tools expect this) + if [[ ! -e "$VENV_DIR/bin/python" ]]; then + ln -sf "${pythonRuntime}/bin/python" "$VENV_DIR/bin/python" + ln -sf "${pythonRuntime}/bin/python3" "$VENV_DIR/bin/python3" + ln -sf "${pythonRuntime}/bin/python3.12" "$VENV_DIR/bin/python3.12" + fi + + # Set VIRTUAL_ENV so uv installs to our mutable venv instead of Nix store + export VIRTUAL_ENV="$VENV_DIR" + + # Also set PIP_TARGET for pip compatibility + export PIP_TARGET="$SITE_PACKAGES" + + # Add our mutable site-packages to Python path + export PYTHONPATH="''${PYTHONPATH:+$PYTHONPATH:}$SITE_PACKAGES" + + # Prevent pip/uv from installing packages that conflict with Nix-provided ones + export PIP_CONSTRAINT="${pipConstraints}" + export UV_CONSTRAINT="${pipConstraints}" + + # Set model path for custom nodes that check this env var + # (prevents them from trying to write to the read-only Nix store) + export COMFYUI_MODEL_PATH="$BASE_DIR/models" + + # Redirect PyTorch hub downloads to data directory + # This prevents attempts to write to the read-only Nix store + export TORCH_HOME="$BASE_DIR/.cache/torch" + mkdir -p "$TORCH_HOME" + + # Redirect HuggingFace cache to data directory for model downloads + export HF_HOME="$BASE_DIR/.cache/huggingface" + mkdir -p "$HF_HOME" + + # Redirect facexlib model downloads to data directory + # (facexlib is patched to respect this env var) + export FACEXLIB_MODELPATH="$BASE_DIR/.cache/facexlib" + mkdir -p "$FACEXLIB_MODELPATH/facexlib/weights" + + # Open browser if requested (background, after short delay) + if [[ "$OPEN_BROWSER" == "true" ]]; then + (sleep 3 && ${browserCommand} "http://127.0.0.1:$PORT" 2>/dev/null) & + fi + + # Run ComfyUI directly from Nix store + exec "${pythonRuntime}/bin/python" "${comfyuiSrc}/main.py" \ + --base-directory "$BASE_DIR" \ + --front-end-root "${frontendRoot}" \ + --database-url "sqlite:///$BASE_DIR/user/comfyui.db" \ + "''${COMFY_ARGS[@]}" ''; }; @@ -462,23 +461,22 @@ PYVENV version = versions.comfyui.version; # Expose heavy packages for Docker layer optimization # These are added to contents separately so buildLayeredImage creates distinct layers - heavyDeps = - [ - python.pkgs.torch - python.pkgs.torchvision - python.pkgs.torchaudio - python.pkgs.transformers - python.pkgs.numpy - python.pkgs.pillow - python.pkgs.scipy - python.pkgs.opencv4 - python.pkgs.huggingface-hub - python.pkgs.safetensors - python.pkgs.accelerate - ] - ++ lib.optionals (python.pkgs ? xformers) [ python.pkgs.xformers ] - ++ lib.optionals (python.pkgs ? bitsandbytes) [ python.pkgs.bitsandbytes ] - ++ lib.optionals (python.pkgs ? triton) [ python.pkgs.triton ]; + heavyDeps = [ + python.pkgs.torch + python.pkgs.torchvision + python.pkgs.torchaudio + python.pkgs.transformers + python.pkgs.numpy + python.pkgs.pillow + python.pkgs.scipy + python.pkgs.opencv4 + python.pkgs.huggingface-hub + python.pkgs.safetensors + python.pkgs.accelerate + ] + ++ lib.optionals (python.pkgs ? xformers) [ python.pkgs.xformers ] + ++ lib.optionals (python.pkgs ? bitsandbytes) [ python.pkgs.bitsandbytes ] + ++ lib.optionals (python.pkgs ? triton) [ python.pkgs.triton ]; }; meta = with lib; { diff --git a/nix/python-overrides.nix b/nix/python-overrides.nix index c4bbaf3..0eb3263 100644 --- a/nix/python-overrides.nix +++ b/nix/python-overrides.nix @@ -7,13 +7,202 @@ let lib = pkgs.lib; useCuda = cudaSupport && pkgs.stdenv.isLinux; sentencepieceNoGperf = pkgs.sentencepiece.override { withGPerfTools = false; }; + + # Pre-built PyTorch CUDA wheels from pytorch.org + # These avoid compiling PyTorch from source (which requires 30-60GB RAM and hours of build time) + # The wheels bundle CUDA 12.4 libraries, so no separate CUDA toolkit needed at runtime + cudaWheels = versions.pytorchWheels.cu124; + + # Common build inputs for PyTorch wheels (manylinux compatibility) + wheelBuildInputs = [ + pkgs.stdenv.cc.cc.lib + pkgs.zlib + pkgs.libGL + pkgs.glib + ]; + + # CUDA libraries needed by PyTorch wheels (for auto-patchelf) + cudaLibs = pkgs.lib.optionals useCuda ( + with pkgs.cudaPackages; + [ + cuda_cudart # libcudart.so.12 + cuda_cupti # libcupti.so.12 + libcublas # libcublas.so.12, libcublasLt.so.12 + libcufft # libcufft.so.11 + libcurand # libcurand.so.10 + libcusolver # libcusolver.so.11 + libcusparse # libcusparse.so.12 + cudnn # libcudnn.so.9 + nccl # libnccl.so.2 + cuda_nvrtc # libnvrtc.so.12 + ] + ); in final: prev: -# CUDA torch base override - this is the key fix! -# By overriding torch at the base level, ALL packages that reference self.torch -# will automatically get the CUDA version. This prevents torch version collisions. -lib.optionalAttrs (useCuda && prev ? torch) { - torch = prev.torch.override { cudaSupport = true; }; +# CUDA torch from pre-built wheels - avoids 30-60GB RAM compilation +# The wheels bundle CUDA libraries internally, providing full GPU support +lib.optionalAttrs useCuda { + torch = final.buildPythonPackage { + pname = "torch"; + version = cudaWheels.torch.version; + format = "wheel"; + src = pkgs.fetchurl { + url = cudaWheels.torch.url; + hash = cudaWheels.torch.hash; + }; + dontBuild = true; + dontConfigure = true; + nativeBuildInputs = [ + pkgs.autoPatchelfHook + pkgs.gnused + ]; + buildInputs = wheelBuildInputs ++ cudaLibs; + # libcuda.so.1 comes from the NVIDIA driver at runtime, not from cudaPackages + autoPatchelfIgnoreMissingDeps = [ "libcuda.so.1" ]; + + # Remove nvidia-* and triton dependencies from wheel metadata + # These are provided by nixpkgs cudaPackages, not PyPI packages + postInstall = '' + for metadata in "$out/${final.python.sitePackages}"/torch-*.dist-info/METADATA; do + if [[ -f "$metadata" ]]; then + sed -i '/^Requires-Dist: nvidia-/d' "$metadata" + sed -i '/^Requires-Dist: triton/d' "$metadata" + fi + done + ''; + + propagatedBuildInputs = with final; [ + filelock + typing-extensions + sympy + networkx + jinja2 + fsspec + ]; + # Don't check for CUDA at import time (requires GPU) + pythonImportsCheck = [ ]; + doCheck = false; + + # Passthru attributes expected by downstream packages (xformers, bitsandbytes, etc.) + # The wheel bundles CUDA 12.4 and supports all GPU architectures + passthru = { + cudaSupport = true; + rocmSupport = false; + # All architectures supported by pre-built wheel (Pascal through Hopper) + cudaCapabilities = [ + "6.1" + "7.0" + "7.5" + "8.0" + "8.6" + "8.9" + "9.0" + ]; + # Provide cudaPackages for packages that need it (use default version) + cudaPackages = pkgs.cudaPackages; + rocmPackages = { }; + }; + + meta = { + description = "PyTorch with CUDA ${cudaWheels.torch.version} (pre-built wheel)"; + homepage = "https://pytorch.org"; + license = lib.licenses.bsd3; + platforms = [ "x86_64-linux" ]; + }; + }; + + torchvision = final.buildPythonPackage { + pname = "torchvision"; + version = cudaWheels.torchvision.version; + format = "wheel"; + src = pkgs.fetchurl { + url = cudaWheels.torchvision.url; + hash = cudaWheels.torchvision.hash; + }; + dontBuild = true; + dontConfigure = true; + nativeBuildInputs = [ pkgs.autoPatchelfHook ]; + buildInputs = wheelBuildInputs ++ cudaLibs ++ [ final.torch ]; + # Ignore torch libs (loaded via Python import) + autoPatchelfIgnoreMissingDeps = [ + "libcuda.so.1" + "libtorch.so" + "libtorch_cpu.so" + "libtorch_cuda.so" + "libtorch_python.so" + "libc10.so" + "libc10_cuda.so" + ]; + propagatedBuildInputs = with final; [ + torch + numpy + pillow + ]; + pythonImportsCheck = [ ]; + doCheck = false; + meta = { + description = "TorchVision with CUDA (pre-built wheel)"; + homepage = "https://pytorch.org/vision"; + license = lib.licenses.bsd3; + platforms = [ "x86_64-linux" ]; + }; + }; + + torchaudio = final.buildPythonPackage { + pname = "torchaudio"; + version = cudaWheels.torchaudio.version; + format = "wheel"; + src = pkgs.fetchurl { + url = cudaWheels.torchaudio.url; + hash = cudaWheels.torchaudio.hash; + }; + dontBuild = true; + dontConfigure = true; + nativeBuildInputs = [ pkgs.autoPatchelfHook ]; + buildInputs = wheelBuildInputs ++ cudaLibs ++ [ final.torch ]; + # Ignore torch libs (loaded via Python) and FFmpeg/sox libs (optional, multiple versions bundled) + autoPatchelfIgnoreMissingDeps = [ + "libcuda.so.1" + # Torch libs (loaded via Python import) + "libtorch.so" + "libtorch_cpu.so" + "libtorch_cuda.so" + "libtorch_python.so" + "libc10.so" + "libc10_cuda.so" + # Sox (optional audio backend) + "libsox.so" + # FFmpeg 4.x + "libavutil.so.56" + "libavcodec.so.58" + "libavformat.so.58" + "libavfilter.so.7" + "libavdevice.so.58" + # FFmpeg 5.x + "libavutil.so.57" + "libavcodec.so.59" + "libavformat.so.59" + "libavfilter.so.8" + "libavdevice.so.59" + # FFmpeg 6.x + "libavutil.so.58" + "libavcodec.so.60" + "libavformat.so.60" + "libavfilter.so.9" + "libavdevice.so.60" + ]; + propagatedBuildInputs = with final; [ + torch + ]; + pythonImportsCheck = [ ]; + doCheck = false; + meta = { + description = "TorchAudio with CUDA (pre-built wheel)"; + homepage = "https://pytorch.org/audio"; + license = lib.licenses.bsd2; + platforms = [ "x86_64-linux" ]; + }; + }; } # Spandrel and other packages that need explicit torch handling // lib.optionalAttrs (prev ? torch) { @@ -32,47 +221,21 @@ lib.optionalAttrs (useCuda && prev ? torch) { final.wheel final.ninja ]; - propagatedBuildInputs = - [ final.torch ] # Use final.torch - will be CUDA torch when cudaSupport=true - ++ lib.optionals (prev ? torchvision) [ final.torchvision ] - ++ lib.optionals (prev ? safetensors) [ final.safetensors ] - ++ lib.optionals (prev ? numpy) [ final.numpy ] - ++ lib.optionals (prev ? einops) [ final.einops ] - ++ lib.optionals (prev ? typing-extensions) [ final.typing-extensions ]; + propagatedBuildInputs = [ + final.torch + ] # Use final.torch - will be CUDA torch when cudaSupport=true + ++ lib.optionals (prev ? torchvision) [ final.torchvision ] + ++ lib.optionals (prev ? safetensors) [ final.safetensors ] + ++ lib.optionals (prev ? numpy) [ final.numpy ] + ++ lib.optionals (prev ? einops) [ final.einops ] + ++ lib.optionals (prev ? typing-extensions) [ final.typing-extensions ]; pythonImportsCheck = [ ]; doCheck = false; }; } -# CUDA-specific package overrides - use final.torch (our overridden CUDA torch) -// lib.optionalAttrs useCuda ( - lib.optionalAttrs (prev ? torchvision) { - torchvision = prev.torchvision.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? torchaudio) { - torchaudio = prev.torchaudio.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? torchsde) { - torchsde = prev.torchsde.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? kornia) { - kornia = prev.kornia.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? accelerate) { - accelerate = prev.accelerate.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? timm) { - timm = prev.timm.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? peft) { - peft = prev.peft.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? torchdiffeq) { - torchdiffeq = prev.torchdiffeq.override { torch = final.torch; }; - } - // lib.optionalAttrs (prev ? open-clip-torch) { - open-clip-torch = prev.open-clip-torch.override { torch = final.torch; }; - } -) +# Note: When useCuda=true, torch/torchvision/torchaudio are replaced with pre-built wheels +# above. Packages that depend on torch (kornia, accelerate, etc.) will automatically +# use our wheel-based torch via final.torch since we've overridden it in the overlay. // lib.optionalAttrs (pkgs.stdenv.isDarwin && prev ? sentencepiece) { sentencepiece = prev.sentencepiece.overridePythonAttrs (old: { buildInputs = [ sentencepieceNoGperf.dev ]; @@ -146,6 +309,21 @@ lib.optionalAttrs (useCuda && prev ? torch) { }); } +# Disable failing timm test (torch dynamo/inductor test needs setuptools at runtime) +// lib.optionalAttrs (prev ? timm) { + timm = prev.timm.overridePythonAttrs (old: { + disabledTests = (old.disabledTests or [ ]) ++ [ "test_kron" ]; + }); +} + +# Relax xformers torch version requirement (0.0.30 wants torch>=2.7, we have 2.5.1) +// lib.optionalAttrs (prev ? xformers) { + xformers = prev.xformers.overridePythonAttrs (old: { + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ final.pythonRelaxDepsHook ]; + pythonRelaxDeps = (old.pythonRelaxDeps or [ ]) ++ [ "torch" ]; + }); +} + # Disable failing ffmpeg test for imageio (test_process_termination expects exit code 2 but gets 6) // lib.optionalAttrs (prev ? imageio) { imageio = prev.imageio.overridePythonAttrs (old: { @@ -153,6 +331,13 @@ lib.optionalAttrs (useCuda && prev ? torch) { }); } +# Fix bitsandbytes build - needs ninja for wheel building phase +// lib.optionalAttrs (prev ? bitsandbytes) { + bitsandbytes = prev.bitsandbytes.overridePythonAttrs (old: { + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ final.ninja ]; + }); +} + # color-matcher - not in older nixpkgs, needed for KJNodes // { "color-matcher" = final.buildPythonPackage rec { @@ -291,6 +476,12 @@ lib.optionalAttrs (useCuda && prev ? torch) { hash = versions.vendored.sam2.hash; }; + # Patch pyproject.toml to remove torch from build dependencies + # (we provide torch via Nix, pip can't resolve our wheel's metadata) + postPatch = '' + sed -i '/"torch>=2.5.1"/d' pyproject.toml + ''; + nativeBuildInputs = [ final.setuptools final.wheel @@ -305,10 +496,15 @@ lib.optionalAttrs (useCuda && prev ? torch) { final.tqdm final.hydra-core final.iopath + final.sympy ]; - # Relax version checks - nixpkgs torchvision is 0.20.1a0 which satisfies >=0.20.1 - pythonRelaxDeps = [ "torchvision" ]; + # Relax version checks + pythonRelaxDeps = [ + "torchvision" + "torch" + "sympy" + ]; doCheck = false; pythonImportsCheck = [ "sam2" ]; diff --git a/nix/versions.nix b/nix/versions.nix index cfea89b..13d5ac6 100644 --- a/nix/versions.nix +++ b/nix/versions.nix @@ -94,6 +94,29 @@ }; }; + # Pre-built PyTorch CUDA wheels from pytorch.org + # These avoid compiling PyTorch from source (which requires 30-60GB RAM) + # Wheels bundle CUDA libraries, so no separate CUDA toolkit needed at runtime + pytorchWheels = { + cu124 = { + torch = { + version = "2.5.1"; + url = "https://download.pytorch.org/whl/cu124/torch-2.5.1%2Bcu124-cp312-cp312-linux_x86_64.whl"; + hash = "sha256-v2SEv+W8T5KkoaG/VTBBUF4ZqRH3FwZTMOsGGv4OFNc="; + }; + torchvision = { + version = "0.20.1"; + url = "https://download.pytorch.org/whl/cu124/torchvision-0.20.1%2Bcu124-cp312-cp312-linux_x86_64.whl"; + hash = "sha256-0QU+xQVFSefawmE7FRv/4yPzySSTnSlt9NfTSSWq860="; + }; + torchaudio = { + version = "2.5.1"; + url = "https://download.pytorch.org/whl/cu124/torchaudio-2.5.1%2Bcu124-cp312-cp312-linux_x86_64.whl"; + hash = "sha256-mQJZjgMwrurQvBVFg3gE6yaFSbm0zkGuPKUbI4SQTok="; + }; + }; + }; + # Custom nodes with pinned versions customNodes = { impact-pack = { diff --git a/pyproject.toml b/pyproject.toml index 76b38e9..5e542c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "comfyui-nix" -version = "0.6.0" +version = "0.7.0" description = "A Nix flake for ComfyUI with Python 3.12" requires-python = ">=3.12" @@ -85,6 +85,7 @@ ignore = [ # Model downloader: Allow module loading errors and complex download logic "src/custom_nodes/model_downloader/__init__.py" = [ "TRY301", # Inline raise acceptable for module loading errors + "PLC0415", # Lazy imports of aiohttp.web - intentional to defer loading ] "src/custom_nodes/model_downloader/model_downloader_patch.py" = [ "PLR0912", # Complex download_model and download_file functions From 2c95a2c8431d27f86ca512b9fb80a7efdbb0f4f9 Mon Sep 17 00:00:00 2001 From: James Brink Date: Fri, 2 Jan 2026 15:42:54 -0700 Subject: [PATCH 09/12] fix: Use PyTorch 2.5.1 on macOS to fix MPS crash on macOS 26 PyTorch 2.9.x in nixpkgs has MPS bugs on macOS 26 (Tahoe) that cause trace trap crashes during SDXL inference. Pin to 2.5.1 pre-built wheels from pytorch.org for macOS Apple Silicon. - Add darwinArm64 wheel pins in nix/versions.nix - Add macOS-specific torch/torchvision/torchaudio overrides - Exclude kornia on macOS (Cargo build issues unrelated to torch) Fixes: https://github.com/pytorch/pytorch/issues/167679 --- nix/packages.nix | 2 +- nix/python-overrides.nix | 91 ++++++++++++++++++++++++++++++++++++++++ nix/versions.nix | 24 ++++++++++- 3 files changed, 114 insertions(+), 3 deletions(-) diff --git a/nix/packages.nix b/nix/packages.nix index 4149481..aeef5aa 100644 --- a/nix/packages.nix +++ b/nix/packages.nix @@ -155,7 +155,7 @@ let ++ lib.optionals (ps ? torchvision && available ps.torchvision) [ ps.torchvision ] ++ lib.optionals (ps ? torchaudio && available ps.torchaudio) [ ps.torchaudio ] ++ lib.optionals (ps ? torchsde && available ps.torchsde) [ ps.torchsde ] - ++ lib.optionals (ps ? kornia && available ps.kornia) [ ps.kornia ] + ++ lib.optionals (pkgs.stdenv.isLinux && ps ? kornia && available ps.kornia) [ ps.kornia ] ++ lib.optionals (ps ? pydantic && available ps.pydantic) [ ps.pydantic ] ++ lib.optionals (ps ? spandrel && available ps.spandrel) [ ps.spandrel ] ++ lib.optionals (ps ? gitpython && available ps.gitpython) [ ps.gitpython ] diff --git a/nix/python-overrides.nix b/nix/python-overrides.nix index 0eb3263..ba6ea02 100644 --- a/nix/python-overrides.nix +++ b/nix/python-overrides.nix @@ -6,6 +6,7 @@ let lib = pkgs.lib; useCuda = cudaSupport && pkgs.stdenv.isLinux; + useDarwinArm64 = pkgs.stdenv.isDarwin && pkgs.stdenv.hostPlatform.isAarch64; sentencepieceNoGperf = pkgs.sentencepiece.override { withGPerfTools = false; }; # Pre-built PyTorch CUDA wheels from pytorch.org @@ -13,6 +14,11 @@ let # The wheels bundle CUDA 12.4 libraries, so no separate CUDA toolkit needed at runtime cudaWheels = versions.pytorchWheels.cu124; + # Pre-built PyTorch wheels for macOS Apple Silicon + # PyTorch 2.5.1 is used instead of 2.9.x due to MPS bugs on macOS 26 (Tahoe) + # See: https://github.com/pytorch/pytorch/issues/167679 + darwinWheels = versions.pytorchWheels.darwinArm64; + # Common build inputs for PyTorch wheels (manylinux compatibility) wheelBuildInputs = [ pkgs.stdenv.cc.cc.lib @@ -204,6 +210,91 @@ lib.optionalAttrs useCuda { }; }; } +# macOS Apple Silicon - use PyTorch 2.5.1 wheels to avoid MPS bugs on macOS 26 (Tahoe) +# PyTorch 2.9.x in nixpkgs has known issues with MPS on macOS 26 +// lib.optionalAttrs useDarwinArm64 { + torch = final.buildPythonPackage { + pname = "torch"; + version = darwinWheels.torch.version; + format = "wheel"; + src = pkgs.fetchurl { + url = darwinWheels.torch.url; + hash = darwinWheels.torch.hash; + }; + dontBuild = true; + dontConfigure = true; + propagatedBuildInputs = with final; [ + filelock + typing-extensions + sympy + networkx + jinja2 + fsspec + ]; + pythonImportsCheck = [ "torch" ]; + doCheck = false; + + passthru = { + cudaSupport = false; + rocmSupport = false; + }; + + meta = { + description = "PyTorch ${darwinWheels.torch.version} for macOS Apple Silicon (MPS)"; + homepage = "https://pytorch.org"; + license = lib.licenses.bsd3; + platforms = [ "aarch64-darwin" ]; + }; + }; + + torchvision = final.buildPythonPackage { + pname = "torchvision"; + version = darwinWheels.torchvision.version; + format = "wheel"; + src = pkgs.fetchurl { + url = darwinWheels.torchvision.url; + hash = darwinWheels.torchvision.hash; + }; + dontBuild = true; + dontConfigure = true; + propagatedBuildInputs = with final; [ + torch + numpy + pillow + ]; + pythonImportsCheck = [ "torchvision" ]; + doCheck = false; + meta = { + description = "TorchVision ${darwinWheels.torchvision.version} for macOS Apple Silicon"; + homepage = "https://pytorch.org/vision"; + license = lib.licenses.bsd3; + platforms = [ "aarch64-darwin" ]; + }; + }; + + torchaudio = final.buildPythonPackage { + pname = "torchaudio"; + version = darwinWheels.torchaudio.version; + format = "wheel"; + src = pkgs.fetchurl { + url = darwinWheels.torchaudio.url; + hash = darwinWheels.torchaudio.hash; + }; + dontBuild = true; + dontConfigure = true; + propagatedBuildInputs = with final; [ + torch + ]; + pythonImportsCheck = [ "torchaudio" ]; + doCheck = false; + meta = { + description = "TorchAudio ${darwinWheels.torchaudio.version} for macOS Apple Silicon"; + homepage = "https://pytorch.org/audio"; + license = lib.licenses.bsd2; + platforms = [ "aarch64-darwin" ]; + }; + }; +} # Spandrel and other packages that need explicit torch handling // lib.optionalAttrs (prev ? torch) { spandrel = final.buildPythonPackage rec { diff --git a/nix/versions.nix b/nix/versions.nix index 13d5ac6..f5a683b 100644 --- a/nix/versions.nix +++ b/nix/versions.nix @@ -94,10 +94,30 @@ }; }; - # Pre-built PyTorch CUDA wheels from pytorch.org + # Pre-built PyTorch wheels from pytorch.org # These avoid compiling PyTorch from source (which requires 30-60GB RAM) - # Wheels bundle CUDA libraries, so no separate CUDA toolkit needed at runtime + # CUDA wheels bundle CUDA libraries, so no separate CUDA toolkit needed at runtime + # macOS wheels use PyTorch 2.5.1 to avoid MPS issues on macOS 26 (Tahoe) pytorchWheels = { + # macOS Apple Silicon (arm64) - PyTorch 2.5.1 (2.9.x has MPS bugs on macOS 26) + darwinArm64 = { + torch = { + version = "2.5.1"; + url = "https://download.pytorch.org/whl/cpu/torch-2.5.1-cp312-none-macosx_11_0_arm64.whl"; + hash = "sha256-jHEt9hEBlk6xGRCoRlFAEfC29ZIMVdv1Z7/4o0Fj1bE="; + }; + torchvision = { + version = "0.20.1"; + url = "https://download.pytorch.org/whl/cpu/torchvision-0.20.1-cp312-cp312-macosx_11_0_arm64.whl"; + hash = "sha256-GjElb/lF1k8Aa7MGgTp8laUx/ha/slNcg33UwQRTPXo="; + }; + torchaudio = { + version = "2.5.1"; + url = "https://download.pytorch.org/whl/cpu/torchaudio-2.5.1-cp312-cp312-macosx_11_0_arm64.whl"; + hash = "sha256-8cv9/Ru9++conUenTzb/bF2HwyBWBiAv71p/tpP2HPA="; + }; + }; + # Linux x86_64 CUDA 12.4 cu124 = { torch = { version = "2.5.1"; From d6eb87ca70ff47a8f1d0836908da438743657295 Mon Sep 17 00:00:00 2001 From: James Brink Date: Fri, 2 Jan 2026 15:59:52 -0700 Subject: [PATCH 10/12] fix: Address PR review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use exact version pinning (==) for vendored packages instead of >= - Add comment explaining kornia exclusion on macOS with issue reference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- nix/packages.nix | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/nix/packages.nix b/nix/packages.nix index aeef5aa..874a748 100644 --- a/nix/packages.nix +++ b/nix/packages.nix @@ -56,10 +56,11 @@ let pillow>=9.0.0 safetensors>=0.3.0 # Prevent ComfyUI-Manager from trying to "restore" vendored packages - comfyui-frontend-package>=${versions.vendored.frontendPackage.version} - comfyui-workflow-templates>=${versions.vendored.workflowTemplates.version} - comfyui-embedded-docs>=${versions.vendored.embeddedDocs.version} - comfyui-manager>=${versions.vendored.manager.version} + # Use exact pinning to ensure reproducibility + comfyui-frontend-package==${versions.vendored.frontendPackage.version} + comfyui-workflow-templates==${versions.vendored.workflowTemplates.version} + comfyui-embedded-docs==${versions.vendored.embeddedDocs.version} + comfyui-manager==${versions.vendored.manager.version} ''; # Default ComfyUI-Manager configuration @@ -155,6 +156,8 @@ let ++ lib.optionals (ps ? torchvision && available ps.torchvision) [ ps.torchvision ] ++ lib.optionals (ps ? torchaudio && available ps.torchaudio) [ ps.torchaudio ] ++ lib.optionals (ps ? torchsde && available ps.torchsde) [ ps.torchsde ] + # kornia excluded on macOS: kornia-rs has Cargo build issues unrelated to torch + # See: https://github.com/NixOS/nixpkgs/issues/458799 ++ lib.optionals (pkgs.stdenv.isLinux && ps ? kornia && available ps.kornia) [ ps.kornia ] ++ lib.optionals (ps ? pydantic && available ps.pydantic) [ ps.pydantic ] ++ lib.optionals (ps ? spandrel && available ps.spandrel) [ ps.spandrel ] From 9881b549933ca6338de89b6315c8e10c447508d1 Mon Sep 17 00:00:00 2001 From: James Brink Date: Fri, 2 Jan 2026 16:07:43 -0700 Subject: [PATCH 11/12] fix: Exclude kornia on aarch64-linux due to badPlatforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - kornia-rs has aarch64-linux in badPlatforms, causing CI failures - Also improve Cachix filter regex to be more defensive 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- nix/packages.nix | 6 ++++-- scripts/push-to-cachix.sh | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/nix/packages.nix b/nix/packages.nix index 874a748..e0aee82 100644 --- a/nix/packages.nix +++ b/nix/packages.nix @@ -156,9 +156,11 @@ let ++ lib.optionals (ps ? torchvision && available ps.torchvision) [ ps.torchvision ] ++ lib.optionals (ps ? torchaudio && available ps.torchaudio) [ ps.torchaudio ] ++ lib.optionals (ps ? torchsde && available ps.torchsde) [ ps.torchsde ] - # kornia excluded on macOS: kornia-rs has Cargo build issues unrelated to torch + # kornia excluded on macOS and aarch64-linux: kornia-rs has Cargo/badPlatforms issues # See: https://github.com/NixOS/nixpkgs/issues/458799 - ++ lib.optionals (pkgs.stdenv.isLinux && ps ? kornia && available ps.kornia) [ ps.kornia ] + ++ lib.optionals ( + pkgs.stdenv.isLinux && pkgs.stdenv.isx86_64 && ps ? kornia && available ps.kornia + ) [ ps.kornia ] ++ lib.optionals (ps ? pydantic && available ps.pydantic) [ ps.pydantic ] ++ lib.optionals (ps ? spandrel && available ps.spandrel) [ ps.spandrel ] ++ lib.optionals (ps ? gitpython && available ps.gitpython) [ ps.gitpython ] diff --git a/scripts/push-to-cachix.sh b/scripts/push-to-cachix.sh index a35ce74..a314473 100755 --- a/scripts/push-to-cachix.sh +++ b/scripts/push-to-cachix.sh @@ -152,7 +152,7 @@ fi # Filter out Rust/Cargo build artifacts that aren't useful for consumers # These are intermediate files that cause upload issues and aren't needed -ALL_PATHS=$(echo "$ALL_PATHS" | grep -vE '(Cargo\.lock|Cargo\.toml|\.cargo-checksum\.json)$') +ALL_PATHS=$(echo "$ALL_PATHS" | grep -vE '/(Cargo\.lock|Cargo\.toml|\.cargo-checksum\.json)$') TOTAL_COUNT=$(echo "$ALL_PATHS" | grep -c '^' || echo 0) echo "" From 293458a6838c93e59131dd084e5480d2b370ac29 Mon Sep 17 00:00:00 2001 From: James Brink Date: Fri, 2 Jan 2026 16:14:14 -0700 Subject: [PATCH 12/12] fix: Remove obsolete cudaArch/cudaCapabilities from NixOS module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wheel-based CUDA approach supports all GPU architectures in a single package, so architecture-specific options are no longer needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- nix/modules/comfyui.nix | 106 +++------------------------------------- 1 file changed, 7 insertions(+), 99 deletions(-) diff --git a/nix/modules/comfyui.nix b/nix/modules/comfyui.nix index 98cbfb0..7315ef4 100644 --- a/nix/modules/comfyui.nix +++ b/nix/modules/comfyui.nix @@ -7,33 +7,9 @@ let cfg = config.services.comfyui; - # Architecture-to-package mapping for cudaArch option - archPackages = { - # Consumer GPUs - sm61 = pkgs.comfy-ui-cuda-sm61; # Pascal (GTX 1080, 1070, 1060) - sm75 = pkgs.comfy-ui-cuda-sm75; # Turing (RTX 2080, 2070, GTX 1660) - sm86 = pkgs.comfy-ui-cuda-sm86; # Ampere (RTX 3080, 3090, 3070) - sm89 = pkgs.comfy-ui-cuda-sm89; # Ada Lovelace (RTX 4090, 4080, 4070) - # Data center GPUs - sm70 = pkgs.comfy-ui-cuda-sm70; # Volta (V100) - sm80 = pkgs.comfy-ui-cuda-sm80; # Ampere Datacenter (A100) - sm90 = pkgs.comfy-ui-cuda-sm90; # Hopper (H100) - }; - # Determine which package to use based on configuration - resolvePackage = - if cfg.cudaCapabilities != null then - # Custom capabilities - build on demand - pkgs.comfyui-nix.mkComfyUIWithCuda cfg.cudaCapabilities - else if cfg.cudaArch != null then - # Pre-built architecture-specific package - archPackages.${cfg.cudaArch} - else if cfg.cuda then - # Default CUDA (RTX: SM 7.5, 8.6, 8.9) - pkgs.comfy-ui-cuda - else - # CPU-only - pkgs.comfy-ui; + # CUDA package uses pre-built wheels supporting all GPU architectures (Pascal through Hopper) + resolvePackage = if cfg.cuda then pkgs.comfy-ui-cuda else pkgs.comfy-ui; args = [ "--listen" cfg.listenAddress @@ -99,71 +75,10 @@ in Enable CUDA support for NVIDIA GPUs. This is recommended for most users with NVIDIA graphics cards as it provides significant performance improvements. - When enabled, uses the CUDA-enabled PyTorch and enables GPU acceleration. + When enabled, uses pre-built PyTorch CUDA wheels that support all GPU + architectures from Pascal (GTX 1080) through Hopper (H100) in a single package. Requires NVIDIA drivers to be installed on the system. - - By default, CUDA builds target RTX consumer GPUs (SM 7.5, 8.6, 8.9). - For other GPUs, use `cudaArch` or `cudaCapabilities` options. - ''; - }; - - cudaArch = lib.mkOption { - type = lib.types.nullOr ( - lib.types.enum [ - "sm61" - "sm70" - "sm75" - "sm80" - "sm86" - "sm89" - "sm90" - ] - ); - default = null; - description = '' - Select a pre-built CUDA architecture-specific package. - This is faster than `cudaCapabilities` as it uses cached builds. - - Available architectures: - - `sm61`: Pascal (GTX 1080, 1070, 1060) - - `sm70`: Volta (V100) - data center - - `sm75`: Turing (RTX 2080, 2070, GTX 1660) - - `sm80`: Ampere Datacenter (A100) - - `sm86`: Ampere Consumer (RTX 3080, 3090, 3070) - - `sm89`: Ada Lovelace (RTX 4090, 4080, 4070) - - `sm90`: Hopper (H100) - data center - - When set, overrides the default RTX build. Implies `cuda = true`. ''; - example = "sm61"; - }; - - cudaCapabilities = lib.mkOption { - type = lib.types.nullOr (lib.types.listOf lib.types.str); - default = null; - description = '' - Custom list of CUDA compute capabilities to build for. - This triggers an on-demand build with the specified architectures. - - Use this when you need multiple architectures or a specific combination - not covered by pre-built packages. Note: this will compile from source - which can take significant time. - - Common capability values: - - "6.1": Pascal (GTX 1080, 1070) - - "7.0": Volta (V100) - - "7.5": Turing (RTX 2080, GTX 1660) - - "8.0": Ampere Datacenter (A100) - - "8.6": Ampere Consumer (RTX 3090, 3080) - - "8.9": Ada Lovelace (RTX 4090, 4080) - - "9.0": Hopper (H100) - - When set, this takes precedence over `cuda` and `cudaArch`. - ''; - example = [ - "6.1" - "8.6" - ]; }; enableManager = lib.mkOption { @@ -182,19 +97,12 @@ in type = lib.types.package; default = resolvePackage; defaultText = lib.literalExpression '' - # Resolved based on cudaCapabilities > cudaArch > cuda > CPU - if cudaCapabilities != null then mkComfyUIWithCuda cudaCapabilities - else if cudaArch != null then pkgs.comfy-ui-cuda-''${cudaArch} - else if cuda then pkgs.comfy-ui-cuda - else pkgs.comfy-ui + if cuda then pkgs.comfy-ui-cuda else pkgs.comfy-ui ''; description = '' ComfyUI package to run. Automatically set based on CUDA configuration: - - 1. `cudaCapabilities` set: builds with custom CUDA capabilities - 2. `cudaArch` set: uses pre-built architecture-specific package - 3. `cuda = true`: uses default RTX package (SM 7.5, 8.6, 8.9) - 4. Otherwise: CPU-only build + - `cuda = true`: CUDA package (supports all GPU architectures) + - Otherwise: CPU-only build Can be overridden for fully custom builds. '';