diff --git a/docs/src/machines.md b/docs/src/machines.md index 7a4720533..f4314cfcd 100644 --- a/docs/src/machines.md +++ b/docs/src/machines.md @@ -530,6 +530,54 @@ getcap $(which sunshine) # Should show: cap_sys_admin=p ``` +## ComfyUI Image Generation (personal-dell) + +`personal-dell` runs [ComfyUI](https://github.com/comfyanonymous/ComfyUI), a node-based Stable Diffusion (SDXL) web UI for creating and modifying digital paintings on the GPU. Enabled via `services.comfyui.enable = true` and accessible at: + +- **Web UI**: `https://atorgesen-dell.local/comfyui/` (also linked from the services landing page as "ComfyUI") + +The service runs in `--lowvram` mode because the RTX 500 Ada has only ~3.7 GB of usable VRAM. SDXL-Turbo / SDXL-Lightning checkpoints are recommended for usable speed; full SDXL base works but is slow. + +### Adding Models (manual step — required before first use) + +Model checkpoints are **not** packaged in Nix (they are large and user-managed). They live under the service's data directory and must be downloaded manually into the `checkpoints` subfolder: + +```bash +mkdir -p /data/andrew/comfyui/models/checkpoints +cd /data/andrew/comfyui/models/checkpoints + +# Example: SDXL-Turbo (~6.9 GB), a good fit for low-VRAM +curl -fL -C - -o sd_xl_turbo_1.0_fp16.safetensors \ + "https://huggingface.co/stabilityai/sdxl-turbo/resolve/main/sd_xl_turbo_1.0_fp16.safetensors" +``` + +ComfyUI rescans the `checkpoints` folder automatically (no service restart needed) — the new model appears in the `Load Checkpoint` node after a page refresh. Other model types go in sibling folders (`models/loras/`, `models/vae/`, `models/controlnet/`, etc.). + +### Creating and Modifying Paintings + +- **Create**: in the web UI, build (or load) a text→image graph — `Load Checkpoint` → `CLIP Text Encode` (positive/negative) → `KSampler` → `VAE Decode` → `Save Image`. For SDXL-Turbo use `cfg ≈ 1.0`, `steps 1–4`, sampler `euler_ancestral`. Generated images are written to `/data/andrew/comfyui/output/`. +- **Modify**: drop an existing painting into `/data/andrew/comfyui/input/`, then run an img2img or inpaint graph (`Load Image` → `VAE Encode` → `KSampler` with reduced `denoise`). + +### Architecture + +- **Service**: `comfyui.service` (systemd, user `andrew:dev`), internal port 8188 (centrally managed in `service-ports.nix`) +- **Nginx proxy**: `/comfyui/` → `http://127.0.0.1:8188` (ComfyUI uses relative asset paths, so the subpath works without a dedicated vhost). The location forwards the raw request path (from `$request_uri`, prefix stripped) plus the query string via custom variables, rather than a normal prefix-stripping `proxy_pass`. This preserves the `%2F`-encoded slashes in ComfyUI's `/userdata/{file}` API (e.g. saving `workflows/foo.json`) — a prefix-stripping proxy decodes them and breaks saves with HTTP 405. The path and query are split (`$path?$query`) rather than passing `$request_uri` whole, so the `?` is not percent-encoded into the filename, and `$args` is avoided so the config passes the `gixy` SSRF lint. +- **Data directory**: `/data/andrew/comfyui/` — `models/`, `input/`, `output/`, `custom_nodes/`, `user/` (created automatically via `systemd.tmpfiles`) +- **Asset database**: `/data/andrew/comfyui/user/comfyui.db` (SQLite) — set explicitly with `--database-url` because ComfyUI's default DB path is relative to the read-only Nix store +- **Version**: pinned to ComfyUI **v0.11.0**, the newest release predating the `comfy-aimdo` dependency (a compiled native wheel that does not package cleanly under Nix on Python 3.13). The three frontend asset packages (`comfyui-frontend-package`, `comfyui-workflow-templates`, `comfyui-embedded-docs`) and `spandrel` are packaged in `anixpkgs`. + +### Troubleshooting + +**Service not running / crash-looping:** +```bash +systemctl status comfyui +journalctl -u comfyui -n 50 +``` + +**Model not showing up:** Confirm the file is in `/data/andrew/comfyui/models/checkpoints/` and refresh the browser. A `comfy_kitchen` import warning in the logs is expected and harmless (fp8/fp4 quantization is disabled; not needed for SDXL). + +**Out-of-memory during generation:** Lower the resolution (SDXL-Turbo was trained at 512×512) or batch size; the service already runs `--lowvram`. + ## Miscellaneous ### Cloud Syncing diff --git a/flake.lock b/flake.lock index 061f2bca2..5d0a0ed8c 100644 --- a/flake.lock +++ b/flake.lock @@ -83,6 +83,23 @@ "type": "github" } }, + "comfyui-src": { + "flake": false, + "locked": { + "lastModified": 1769486881, + "narHash": "sha256-CcA3xTVmBVLGMtM5F74R2LfwafFDxFHZ1uzx5MvrB/4=", + "owner": "comfyanonymous", + "repo": "ComfyUI", + "rev": "09725967cf76304371c390ca1d6483e04061da48", + "type": "github" + }, + "original": { + "owner": "comfyanonymous", + "ref": "refs/tags/v0.11.0", + "repo": "ComfyUI", + "type": "github" + } + }, "crowcpp": { "flake": false, "locked": { @@ -736,6 +753,7 @@ "ardupilot": "ardupilot", "book-notes-sync": "book-notes-sync", "ceres-factors": "ceres-factors", + "comfyui-src": "comfyui-src", "crowcpp": "crowcpp", "daily_tactical_server": "daily_tactical_server", "easy-google-auth": "easy-google-auth", @@ -777,6 +795,7 @@ "signals-cpp": "signals-cpp", "simple-image-editor": "simple-image-editor", "sorting": "sorting", + "spandrel-src": "spandrel-src", "spelling-corrector": "spelling-corrector", "sunnyside": "sunnyside", "symforce": "symforce", @@ -884,6 +903,22 @@ "type": "github" } }, + "spandrel-src": { + "flake": false, + "locked": { + "lastModified": 1776033370, + "narHash": "sha256-ohkI7giaAMvi9RatM11WoA2+Ww53TLmJsB+pRf+RWt0=", + "owner": "chaiNNer-org", + "repo": "spandrel", + "rev": "e1f2ea14b2eb9dc912bdf335803f8a3d481c45b8", + "type": "github" + }, + "original": { + "owner": "chaiNNer-org", + "repo": "spandrel", + "type": "github" + } + }, "spelling-corrector": { "flake": false, "locked": { diff --git a/flake.nix b/flake.nix index 626663db7..539070104 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,12 @@ easy-google-auth.url = "github:goromal/easy-google-auth"; easy-google-auth.flake = false; + spandrel-src.url = "github:chaiNNer-org/spandrel"; + spandrel-src.flake = false; + + comfyui-src.url = "github:comfyanonymous/ComfyUI?ref=refs/tags/v0.11.0"; + comfyui-src.flake = false; + evil-hangman.url = "github:goromal/evil-hangman"; evil-hangman.flake = false; diff --git a/index.json b/index.json index 04eb2e534..349f9e97a 100644 --- a/index.json +++ b/index.json @@ -334,6 +334,56 @@ "attr": "vdlserver", "ci": true, "docs": false + }, + { + "attr": "spandrel", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-frontend-package", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-workflow-templates-core", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-workflow-templates-media-api", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-workflow-templates-media-video", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-workflow-templates-media-image", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-workflow-templates-media-other", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-workflow-templates", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-embedded-docs", + "ci": true, + "docs": false + }, + { + "attr": "comfyui", + "ci": true, + "docs": false } ], "bash": [ diff --git a/pkgs/default.nix b/pkgs/default.nix index ac26c865f..4f7b6dcbd 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -149,6 +149,27 @@ let pkg-src = flakeInputs.jetson-stats; } ); + spandrel = pySelf.callPackage ./python-packages/spandrel { + pkg-src = flakeInputs.spandrel-src; + }; + comfyui-frontend-package = pySelf.callPackage ./python-packages/comfyui-frontend-package { }; + comfyui-workflow-templates-core = + pySelf.callPackage ./python-packages/comfyui-workflow-templates-core + { }; + comfyui-workflow-templates-media-api = + pySelf.callPackage ./python-packages/comfyui-workflow-templates-media-api + { }; + comfyui-workflow-templates-media-video = + pySelf.callPackage ./python-packages/comfyui-workflow-templates-media-video + { }; + comfyui-workflow-templates-media-image = + pySelf.callPackage ./python-packages/comfyui-workflow-templates-media-image + { }; + comfyui-workflow-templates-media-other = + pySelf.callPackage ./python-packages/comfyui-workflow-templates-media-other + { }; + comfyui-workflow-templates = pySelf.callPackage ./python-packages/comfyui-workflow-templates { }; + comfyui-embedded-docs = pySelf.callPackage ./python-packages/comfyui-embedded-docs { }; jupyter-mimetypes = pySelf.callPackage ./python-packages/jupyter-mimetypes { }; jupyter-kernel-client = pySelf.callPackage ./python-packages/jupyter-kernel-client { }; jupyter-server-client = pySelf.callPackage ./python-packages/jupyter-server-client { }; @@ -414,6 +435,44 @@ rec { book-notes-sync = final.python313.pkgs.book-notes-sync; gmail-parser = final.python313.pkgs.gmail-parser; jetson-stats = final.python313.pkgs.jetson-stats; + spandrel = final.python313.pkgs.spandrel; + comfyui = + let + py = final.python313; + pyPkgs = py.pkgs; + in + prev.callPackage ./python-packages/comfyui { + python313 = py; + torch = pyPkgs.torch; + torchsde = pyPkgs.torchsde; + torchvision = pyPkgs.torchvision; + torchaudio = pyPkgs.torchaudio; + numpy = pyPkgs.numpy; + einops = pyPkgs.einops; + transformers = pyPkgs.transformers; + tokenizers = pyPkgs.tokenizers; + sentencepiece = pyPkgs.sentencepiece; + safetensors = pyPkgs.safetensors; + aiohttp = pyPkgs.aiohttp; + yarl = pyPkgs.yarl; + pyyaml = pyPkgs.pyyaml; + pillow = pyPkgs.pillow; + scipy = pyPkgs.scipy; + tqdm = pyPkgs.tqdm; + psutil = pyPkgs.psutil; + alembic = pyPkgs.alembic; + sqlalchemy = pyPkgs.sqlalchemy; + requests = pyPkgs.requests; + pydantic = pyPkgs.pydantic; + pydantic-settings = pyPkgs.pydantic-settings; + kornia = pyPkgs.kornia; + spandrel = pyPkgs.spandrel; + av = pyPkgs.av; + comfyui-frontend-package = pyPkgs.comfyui-frontend-package; + comfyui-workflow-templates = pyPkgs.comfyui-workflow-templates; + comfyui-embedded-docs = pyPkgs.comfyui-embedded-docs; + pkg-src = flakeInputs.comfyui-src; + }; jupyter-mcp-server = final.python313.pkgs.jupyter-mcp-server; goromail = final.python313.pkgs.goromail; orchestrator = final.python313.pkgs.orchestrator; diff --git a/pkgs/nixos/configurations/personal-dell.nix b/pkgs/nixos/configurations/personal-dell.nix index 645eb47f5..b5881c39d 100644 --- a/pkgs/nixos/configurations/personal-dell.nix +++ b/pkgs/nixos/configurations/personal-dell.nix @@ -13,6 +13,7 @@ machines.base.wifiInterfaceName = "wlp0s13f0u1u4"; machines.base.acceptRemoteBuilds = true; machines.cudaNode.enable = true; + services.comfyui.enable = true; machines.base.timedOrchJobs = [ { name = "launchpad-sync"; diff --git a/pkgs/nixos/modules/comfyui/module.nix b/pkgs/nixos/modules/comfyui/module.nix new file mode 100644 index 000000000..b974d22d1 --- /dev/null +++ b/pkgs/nixos/modules/comfyui/module.nix @@ -0,0 +1,99 @@ +{ + pkgs, + config, + lib, + ... +}: +let + service-ports = import ../../service-ports.nix; + cfg = config.services.comfyui; + extendedPkgs = pkgs.extend (import ../../../../overlay.nix); +in +{ + options.services.comfyui = { + enable = lib.mkEnableOption "ComfyUI Stable Diffusion server"; + port = lib.mkOption { + type = lib.types.port; + default = service-ports.comfyui; + }; + dataDir = lib.mkOption { + type = lib.types.str; + default = "/data/andrew/comfyui"; + }; + package = lib.mkOption { + type = lib.types.package; + default = extendedPkgs.comfyui; + }; + }; + + config = lib.mkIf cfg.enable { + machines.base.runWebServer = true; + + machines.base.webServices = [ + { + name = "ComfyUI"; + path = "/comfyui/"; + description = "Stable Diffusion (SDXL) image generation"; + icon = "film"; + } + ]; + + services.nginx.virtualHosts."${config.networking.hostName}.local" = { + locations."/comfyui/" = { + extraConfig = '' + client_max_body_size 100m; + set $comfyui_path $request_uri; + set $comfyui_query ""; + if ($comfyui_path ~ "^/comfyui(/[^?]*)\?(.*)$") { + set $comfyui_path $1; + set $comfyui_query $2; + } + if ($comfyui_path ~ "^/comfyui(/[^?]*)$") { + set $comfyui_path $1; + } + proxy_pass http://127.0.0.1:${builtins.toString cfg.port}$comfyui_path?$comfyui_query; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${cfg.dataDir} 0755 andrew dev -" + "d ${cfg.dataDir}/models 0755 andrew dev -" + "d ${cfg.dataDir}/input 0755 andrew dev -" + "d ${cfg.dataDir}/output 0755 andrew dev -" + "d ${cfg.dataDir}/custom_nodes 0755 andrew dev -" + ]; + + systemd.services.comfyui = { + enable = true; + description = "ComfyUI Stable Diffusion Server"; + unitConfig.StartLimitIntervalSec = 0; + serviceConfig = { + Type = "simple"; + ExecStart = "${cfg.package}/bin/comfyui --listen 127.0.0.1 --port ${builtins.toString cfg.port} --base-directory ${cfg.dataDir} --database-url sqlite:///${cfg.dataDir}/user/comfyui.db --lowvram"; + ReadWritePaths = [ + cfg.dataDir + "/tmp" + ]; + WorkingDirectory = cfg.dataDir; + Restart = "always"; + RestartSec = 5; + User = "andrew"; + Group = "dev"; + Environment = [ + "HOME=/data/andrew" + ]; + }; + wantedBy = [ "multi-user.target" ]; + }; + + networking.firewall.allowedTCPPorts = [ cfg.port ]; + }; +} diff --git a/pkgs/nixos/pc-base.nix b/pkgs/nixos/pc-base.nix index 9c0d704da..3ae58daaa 100644 --- a/pkgs/nixos/pc-base.nix +++ b/pkgs/nixos/pc-base.nix @@ -238,6 +238,7 @@ in ./modules/claude-agent/module.nix ./modules/webserverNode/module.nix ./modules/cudaNode/module.nix + ./modules/comfyui/module.nix ../modules/notes-wiki/module.nix ../modules/metricsNode/module.nix ../modules/plexNode/module.nix diff --git a/pkgs/nixos/service-ports.nix b/pkgs/nixos/service-ports.nix index 1b16cba54..55e845dac 100644 --- a/pkgs/nixos/service-ports.nix +++ b/pkgs/nixos/service-ports.nix @@ -27,6 +27,7 @@ la-quiz-web = 5656; tester = 5757; launchpad = 8888; + comfyui = 8188; anix_upgrade_ui = 5858; tasks_ui = 5959; videodl = 6060; diff --git a/pkgs/python-packages/comfyui-embedded-docs/default.nix b/pkgs/python-packages/comfyui-embedded-docs/default.nix new file mode 100644 index 000000000..1d1cc25ad --- /dev/null +++ b/pkgs/python-packages/comfyui-embedded-docs/default.nix @@ -0,0 +1,19 @@ +{ + buildPythonPackage, + fetchPypi, +}: +buildPythonPackage rec { + pname = "comfyui-embedded-docs"; + version = "0.4.0"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_embedded_docs"; + dist = "py3"; + python = "py3"; + hash = "sha256-l8T4zcrOHpSnVBKMTvU+3ODj3wMI354MmYCA68Slv7I="; + }; + doCheck = false; + pythonImportsCheck = [ "comfyui_embedded_docs" ]; + meta.description = "ComfyUI embedded documentation package."; +} diff --git a/pkgs/python-packages/comfyui-frontend-package/default.nix b/pkgs/python-packages/comfyui-frontend-package/default.nix new file mode 100644 index 000000000..c4484e2d7 --- /dev/null +++ b/pkgs/python-packages/comfyui-frontend-package/default.nix @@ -0,0 +1,19 @@ +{ + buildPythonPackage, + fetchPypi, +}: +buildPythonPackage rec { + pname = "comfyui-frontend-package"; + version = "1.37.11"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_frontend_package"; + dist = "py3"; + python = "py3"; + hash = "sha256-b+0TnslCsFQwVZ+o5FtYQCmz7WI4mSEuxv+1sJzcBCw="; + }; + doCheck = false; + pythonImportsCheck = [ "comfyui_frontend_package" ]; + meta.description = "ComfyUI frontend static assets package."; +} diff --git a/pkgs/python-packages/comfyui-workflow-templates-core/default.nix b/pkgs/python-packages/comfyui-workflow-templates-core/default.nix new file mode 100644 index 000000000..bad2f1e20 --- /dev/null +++ b/pkgs/python-packages/comfyui-workflow-templates-core/default.nix @@ -0,0 +1,19 @@ +{ + buildPythonPackage, + fetchPypi, +}: +buildPythonPackage rec { + pname = "comfyui-workflow-templates-core"; + version = "0.3.112"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_workflow_templates_core"; + dist = "py3"; + python = "py3"; + hash = "sha256-jKOeIhb6aN5ehHq0r8mpWFISqrTg8CRuXurHl3bdKhE="; + }; + doCheck = false; + pythonImportsCheck = [ "comfyui_workflow_templates_core" ]; + meta.description = "Core helpers for ComfyUI workflow templates."; +} diff --git a/pkgs/python-packages/comfyui-workflow-templates-media-api/default.nix b/pkgs/python-packages/comfyui-workflow-templates-media-api/default.nix new file mode 100644 index 000000000..972a24195 --- /dev/null +++ b/pkgs/python-packages/comfyui-workflow-templates-media-api/default.nix @@ -0,0 +1,19 @@ +{ + buildPythonPackage, + fetchPypi, +}: +buildPythonPackage rec { + pname = "comfyui-workflow-templates-media-api"; + version = "0.3.47"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_workflow_templates_media_api"; + dist = "py3"; + python = "py3"; + hash = "sha256-D3aZRzP4tbkI3yEh/WZM3H4E6yUmMD2d8i3x5BricRI="; + }; + doCheck = false; + pythonImportsCheck = [ "comfyui_workflow_templates_media_api" ]; + meta.description = "ComfyUI workflow template media assets (api bundle)."; +} diff --git a/pkgs/python-packages/comfyui-workflow-templates-media-image/default.nix b/pkgs/python-packages/comfyui-workflow-templates-media-image/default.nix new file mode 100644 index 000000000..3ea9cf4a8 --- /dev/null +++ b/pkgs/python-packages/comfyui-workflow-templates-media-image/default.nix @@ -0,0 +1,19 @@ +{ + buildPythonPackage, + fetchPypi, +}: +buildPythonPackage rec { + pname = "comfyui-workflow-templates-media-image"; + version = "0.3.73"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_workflow_templates_media_image"; + dist = "py3"; + python = "py3"; + hash = "sha256-fK78KKCtIZPOYElWGkWHPIi07NFs3sZFFUzuB5LUFPA="; + }; + doCheck = false; + pythonImportsCheck = [ "comfyui_workflow_templates_media_image" ]; + meta.description = "ComfyUI workflow template media assets (image bundle)."; +} diff --git a/pkgs/python-packages/comfyui-workflow-templates-media-other/default.nix b/pkgs/python-packages/comfyui-workflow-templates-media-other/default.nix new file mode 100644 index 000000000..8aebe19d8 --- /dev/null +++ b/pkgs/python-packages/comfyui-workflow-templates-media-other/default.nix @@ -0,0 +1,19 @@ +{ + buildPythonPackage, + fetchPypi, +}: +buildPythonPackage rec { + pname = "comfyui-workflow-templates-media-other"; + version = "0.3.95"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_workflow_templates_media_other"; + dist = "py3"; + python = "py3"; + hash = "sha256-Fi0OZnnUlIo0ebnnHN7XrjkenEYGSb5BdrZik9Ey6CY="; + }; + doCheck = false; + pythonImportsCheck = [ "comfyui_workflow_templates_media_other" ]; + meta.description = "ComfyUI workflow template media assets (other bundle)."; +} diff --git a/pkgs/python-packages/comfyui-workflow-templates-media-video/default.nix b/pkgs/python-packages/comfyui-workflow-templates-media-video/default.nix new file mode 100644 index 000000000..1487852da --- /dev/null +++ b/pkgs/python-packages/comfyui-workflow-templates-media-video/default.nix @@ -0,0 +1,19 @@ +{ + buildPythonPackage, + fetchPypi, +}: +buildPythonPackage rec { + pname = "comfyui-workflow-templates-media-video"; + version = "0.3.41"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_workflow_templates_media_video"; + dist = "py3"; + python = "py3"; + hash = "sha256-NGUMPbb2patwhXJ/apMDLOxksI1z8Iwc0OsIPqYv4/U="; + }; + doCheck = false; + pythonImportsCheck = [ "comfyui_workflow_templates_media_video" ]; + meta.description = "ComfyUI workflow template media assets (video bundle)."; +} diff --git a/pkgs/python-packages/comfyui-workflow-templates/default.nix b/pkgs/python-packages/comfyui-workflow-templates/default.nix new file mode 100644 index 000000000..32164e73e --- /dev/null +++ b/pkgs/python-packages/comfyui-workflow-templates/default.nix @@ -0,0 +1,31 @@ +{ + buildPythonPackage, + fetchPypi, + comfyui-workflow-templates-core, + comfyui-workflow-templates-media-api, + comfyui-workflow-templates-media-video, + comfyui-workflow-templates-media-image, + comfyui-workflow-templates-media-other, +}: +buildPythonPackage rec { + pname = "comfyui-workflow-templates"; + version = "0.8.24"; + format = "wheel"; + src = fetchPypi { + inherit version format; + pname = "comfyui_workflow_templates"; + dist = "py3"; + python = "py3"; + hash = "sha256-y6z8TJc0fFlyEYL5vzUYQkUHbeNo7bruy+qQGlqPhSg="; + }; + propagatedBuildInputs = [ + comfyui-workflow-templates-core + comfyui-workflow-templates-media-api + comfyui-workflow-templates-media-video + comfyui-workflow-templates-media-image + comfyui-workflow-templates-media-other + ]; + doCheck = false; + pythonImportsCheck = [ "comfyui_workflow_templates" ]; + meta.description = "ComfyUI workflow templates package."; +} diff --git a/pkgs/python-packages/comfyui/default.nix b/pkgs/python-packages/comfyui/default.nix new file mode 100644 index 000000000..46fbcb7fd --- /dev/null +++ b/pkgs/python-packages/comfyui/default.nix @@ -0,0 +1,86 @@ +{ + stdenvNoCC, + makeWrapper, + python313, + torch, + torchsde, + torchvision, + torchaudio, + numpy, + einops, + transformers, + tokenizers, + sentencepiece, + safetensors, + aiohttp, + yarl, + pyyaml, + pillow, + scipy, + tqdm, + psutil, + alembic, + sqlalchemy, + requests, + pydantic, + pydantic-settings, + kornia, + spandrel, + av, + comfyui-frontend-package, + comfyui-workflow-templates, + comfyui-embedded-docs, + pkg-src, +}: +let + pythonEnv = python313.withPackages (_ps: [ + torch + torchsde + torchvision + torchaudio + numpy + einops + transformers + tokenizers + sentencepiece + safetensors + aiohttp + yarl + pyyaml + pillow + scipy + tqdm + psutil + alembic + sqlalchemy + requests + pydantic + pydantic-settings + kornia + spandrel + av + comfyui-frontend-package + comfyui-workflow-templates + comfyui-embedded-docs + ]); +in +stdenvNoCC.mkDerivation { + pname = "comfyui"; + version = "0.11.0"; + src = pkg-src; + nativeBuildInputs = [ makeWrapper ]; + dontConfigure = true; + dontBuild = true; + installPhase = '' + mkdir -p $out/share/comfyui $out/bin + cp -r . $out/share/comfyui + makeWrapper ${pythonEnv}/bin/python $out/bin/comfyui \ + --add-flags "$out/share/comfyui/main.py" + ''; + meta = { + description = "ComfyUI — node-based Stable Diffusion (SDXL) web UI."; + longDescription = '' + [Repository](https://github.com/comfyanonymous/ComfyUI) + ''; + }; +} diff --git a/pkgs/python-packages/spandrel/default.nix b/pkgs/python-packages/spandrel/default.nix new file mode 100644 index 000000000..de112fb30 --- /dev/null +++ b/pkgs/python-packages/spandrel/default.nix @@ -0,0 +1,36 @@ +{ + buildPythonPackage, + setuptools, + torch, + torchvision, + numpy, + safetensors, + einops, + typing-extensions, + pkg-src, +}: +buildPythonPackage rec { + pname = "spandrel"; + version = "0.4.2"; + pyproject = true; + build-system = [ setuptools ]; + src = pkg-src; + postPatch = '' + substituteInPlace pyproject.toml --replace 'backend-path = ["."]' "" + ''; + propagatedBuildInputs = [ + torch + torchvision + numpy + safetensors + einops + typing-extensions + ]; + doCheck = false; + meta = { + description = "Neural network model loader for super-resolution and restoration (ComfyUI dep)."; + longDescription = '' + [Repository](https://github.com/chaiNNer-org/spandrel) + ''; + }; +}