From 2931af507b192d53d49e5c82420a2867bafa85ef Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 18:06:42 -0700 Subject: [PATCH 01/15] feat(pkgs): package spandrel for ComfyUI Co-Authored-By: Claude Opus 4.8 --- flake.lock | 17 +++++++++++ flake.nix | 3 ++ index.json | 5 ++++ pkgs/default.nix | 4 +++ pkgs/python-packages/spandrel/default.nix | 36 +++++++++++++++++++++++ 5 files changed, 65 insertions(+) create mode 100644 pkgs/python-packages/spandrel/default.nix diff --git a/flake.lock b/flake.lock index 061f2bca2..22cefec4e 100644 --- a/flake.lock +++ b/flake.lock @@ -777,6 +777,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 +885,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..d0d7de06a 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,9 @@ 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; + evil-hangman.url = "github:goromal/evil-hangman"; evil-hangman.flake = false; diff --git a/index.json b/index.json index 04eb2e534..1f5753c1b 100644 --- a/index.json +++ b/index.json @@ -334,6 +334,11 @@ "attr": "vdlserver", "ci": true, "docs": false + }, + { + "attr": "spandrel", + "ci": true, + "docs": false } ], "bash": [ diff --git a/pkgs/default.nix b/pkgs/default.nix index ac26c865f..b44498b2f 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -149,6 +149,9 @@ let pkg-src = flakeInputs.jetson-stats; } ); + spandrel = pySelf.callPackage ./python-packages/spandrel { + pkg-src = flakeInputs.spandrel-src; + }; 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 +417,7 @@ 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; jupyter-mcp-server = final.python313.pkgs.jupyter-mcp-server; goromail = final.python313.pkgs.goromail; orchestrator = final.python313.pkgs.orchestrator; 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) + ''; + }; +} From 5cb0112e3c1a1bcb12e286e7d5b104167915676d Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 18:11:55 -0700 Subject: [PATCH 02/15] feat(pkgs): package ComfyUI with bundled CUDA python env Co-Authored-By: Claude Opus 4.8 --- flake.lock | 17 ++++++ flake.nix | 3 + index.json | 5 ++ pkgs/default.nix | 29 ++++++++++ pkgs/python-packages/comfyui/default.nix | 70 ++++++++++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 pkgs/python-packages/comfyui/default.nix diff --git a/flake.lock b/flake.lock index 22cefec4e..4224b7bad 100644 --- a/flake.lock +++ b/flake.lock @@ -83,6 +83,22 @@ "type": "github" } }, + "comfyui-src": { + "flake": false, + "locked": { + "lastModified": 1781462523, + "narHash": "sha256-AmQWUnPQ67Yv7EaQqBIBmPP2r4PBZMXB5UVaWy1TWEQ=", + "owner": "comfyanonymous", + "repo": "ComfyUI", + "rev": "e1b9366898a4657bceea8737d74139406e4ea521", + "type": "github" + }, + "original": { + "owner": "comfyanonymous", + "repo": "ComfyUI", + "type": "github" + } + }, "crowcpp": { "flake": false, "locked": { @@ -736,6 +752,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", diff --git a/flake.nix b/flake.nix index d0d7de06a..810b28c05 100644 --- a/flake.nix +++ b/flake.nix @@ -40,6 +40,9 @@ spandrel-src.url = "github:chaiNNer-org/spandrel"; spandrel-src.flake = false; + comfyui-src.url = "github:comfyanonymous/ComfyUI"; + comfyui-src.flake = false; + evil-hangman.url = "github:goromal/evil-hangman"; evil-hangman.flake = false; diff --git a/index.json b/index.json index 1f5753c1b..886c4a95a 100644 --- a/index.json +++ b/index.json @@ -339,6 +339,11 @@ "attr": "spandrel", "ci": true, "docs": false + }, + { + "attr": "comfyui", + "ci": true, + "docs": false } ], "bash": [ diff --git a/pkgs/default.nix b/pkgs/default.nix index b44498b2f..e51990352 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -418,6 +418,35 @@ rec { 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; + 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; + kornia = pyPkgs.kornia; + spandrel = pyPkgs.spandrel; + soundfile = pyPkgs.soundfile; + av = pyPkgs.av; + 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/python-packages/comfyui/default.nix b/pkgs/python-packages/comfyui/default.nix new file mode 100644 index 000000000..75f9622c5 --- /dev/null +++ b/pkgs/python-packages/comfyui/default.nix @@ -0,0 +1,70 @@ +{ + stdenvNoCC, + makeWrapper, + python313, + torch, + torchsde, + torchvision, + torchaudio, + einops, + transformers, + tokenizers, + sentencepiece, + safetensors, + aiohttp, + yarl, + pyyaml, + pillow, + scipy, + tqdm, + psutil, + kornia, + spandrel, + soundfile, + av, + pkg-src, +}: +let + pythonEnv = python313.withPackages (_ps: [ + torch + torchsde + torchvision + torchaudio + einops + transformers + tokenizers + sentencepiece + safetensors + aiohttp + yarl + pyyaml + pillow + scipy + tqdm + psutil + kornia + spandrel + soundfile + av + ]); +in +stdenvNoCC.mkDerivation { + pname = "comfyui"; + version = "0.0.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) + ''; + }; +} From de40806036fde18ed15cac2c155951d253e22df8 Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 18:15:05 -0700 Subject: [PATCH 03/15] feat(nixos): add services.comfyui module Co-Authored-By: Claude Opus 4.8 --- pkgs/nixos/modules/comfyui/module.nix | 87 +++++++++++++++++++++++++++ pkgs/nixos/pc-base.nix | 1 + pkgs/nixos/service-ports.nix | 1 + 3 files changed, 89 insertions(+) create mode 100644 pkgs/nixos/modules/comfyui/module.nix diff --git a/pkgs/nixos/modules/comfyui/module.nix b/pkgs/nixos/modules/comfyui/module.nix new file mode 100644 index 000000000..c3dbbda97 --- /dev/null +++ b/pkgs/nixos/modules/comfyui/module.nix @@ -0,0 +1,87 @@ +{ + 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 = "palette"; + } + ]; + + services.nginx.virtualHosts."${config.networking.hostName}.local" = { + locations."/comfyui/" = { + proxyPass = "http://127.0.0.1:${builtins.toString cfg.port}/"; + proxyWebsockets = true; + extraConfig = '' + 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} --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; From 843eda8e92f9d547729cfec6578b2dd944b85567 Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 18:16:32 -0700 Subject: [PATCH 04/15] feat(personal-dell): enable ComfyUI service Co-Authored-By: Claude Opus 4.8 --- pkgs/nixos/configurations/personal-dell.nix | 1 + 1 file changed, 1 insertion(+) 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"; From 6045eeea2df2a3c525b7dbbbf60c9f515902c202 Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 18:21:50 -0700 Subject: [PATCH 05/15] fix(nixos): use valid fa6 icon for ComfyUI service Co-Authored-By: Claude Opus 4.8 --- pkgs/nixos/modules/comfyui/module.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/nixos/modules/comfyui/module.nix b/pkgs/nixos/modules/comfyui/module.nix index c3dbbda97..e523f8b64 100644 --- a/pkgs/nixos/modules/comfyui/module.nix +++ b/pkgs/nixos/modules/comfyui/module.nix @@ -34,7 +34,7 @@ in name = "ComfyUI"; path = "/comfyui/"; description = "Stable Diffusion (SDXL) image generation"; - icon = "palette"; + icon = "film"; } ]; From d1821a85509d6fa14e2082ba7acc2bc3374d0050 Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 20:39:18 -0700 Subject: [PATCH 06/15] fix(pkgs): pin ComfyUI to v0.11.0 and package frontend wheels Co-Authored-By: Claude Opus 4.8 --- flake.lock | 7 ++++--- flake.nix | 2 +- index.json | 20 ++++++++++++++++++ pkgs/default.nix | 13 +++++++++++- .../comfyui-embedded-docs/default.nix | 19 +++++++++++++++++ .../comfyui-frontend-package/default.nix | 19 +++++++++++++++++ .../default.nix | 19 +++++++++++++++++ .../comfyui-workflow-templates/default.nix | 21 +++++++++++++++++++ pkgs/python-packages/comfyui/default.nix | 20 +++++++++++++++--- 9 files changed, 132 insertions(+), 8 deletions(-) create mode 100644 pkgs/python-packages/comfyui-embedded-docs/default.nix create mode 100644 pkgs/python-packages/comfyui-frontend-package/default.nix create mode 100644 pkgs/python-packages/comfyui-workflow-templates-core/default.nix create mode 100644 pkgs/python-packages/comfyui-workflow-templates/default.nix diff --git a/flake.lock b/flake.lock index 4224b7bad..5d0a0ed8c 100644 --- a/flake.lock +++ b/flake.lock @@ -86,15 +86,16 @@ "comfyui-src": { "flake": false, "locked": { - "lastModified": 1781462523, - "narHash": "sha256-AmQWUnPQ67Yv7EaQqBIBmPP2r4PBZMXB5UVaWy1TWEQ=", + "lastModified": 1769486881, + "narHash": "sha256-CcA3xTVmBVLGMtM5F74R2LfwafFDxFHZ1uzx5MvrB/4=", "owner": "comfyanonymous", "repo": "ComfyUI", - "rev": "e1b9366898a4657bceea8737d74139406e4ea521", + "rev": "09725967cf76304371c390ca1d6483e04061da48", "type": "github" }, "original": { "owner": "comfyanonymous", + "ref": "refs/tags/v0.11.0", "repo": "ComfyUI", "type": "github" } diff --git a/flake.nix b/flake.nix index 810b28c05..539070104 100644 --- a/flake.nix +++ b/flake.nix @@ -40,7 +40,7 @@ spandrel-src.url = "github:chaiNNer-org/spandrel"; spandrel-src.flake = false; - comfyui-src.url = "github:comfyanonymous/ComfyUI"; + comfyui-src.url = "github:comfyanonymous/ComfyUI?ref=refs/tags/v0.11.0"; comfyui-src.flake = false; evil-hangman.url = "github:goromal/evil-hangman"; diff --git a/index.json b/index.json index 886c4a95a..f32dcd1e6 100644 --- a/index.json +++ b/index.json @@ -340,6 +340,26 @@ "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", + "ci": true, + "docs": false + }, + { + "attr": "comfyui-embedded-docs", + "ci": true, + "docs": false + }, { "attr": "comfyui", "ci": true, diff --git a/pkgs/default.nix b/pkgs/default.nix index e51990352..498c40569 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -152,6 +152,10 @@ let 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 = 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 { }; @@ -429,6 +433,7 @@ rec { torchsde = pyPkgs.torchsde; torchvision = pyPkgs.torchvision; torchaudio = pyPkgs.torchaudio; + numpy = pyPkgs.numpy; einops = pyPkgs.einops; transformers = pyPkgs.transformers; tokenizers = pyPkgs.tokenizers; @@ -441,10 +446,16 @@ rec { scipy = pyPkgs.scipy; tqdm = pyPkgs.tqdm; psutil = pyPkgs.psutil; + alembic = pyPkgs.alembic; + sqlalchemy = pyPkgs.sqlalchemy; + requests = pyPkgs.requests; + pydantic = pyPkgs.pydantic; kornia = pyPkgs.kornia; spandrel = pyPkgs.spandrel; - soundfile = pyPkgs.soundfile; 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; 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/default.nix b/pkgs/python-packages/comfyui-workflow-templates/default.nix new file mode 100644 index 000000000..1c71ad635 --- /dev/null +++ b/pkgs/python-packages/comfyui-workflow-templates/default.nix @@ -0,0 +1,21 @@ +{ + buildPythonPackage, + fetchPypi, + comfyui-workflow-templates-core, +}: +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 ]; + 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 index 75f9622c5..62b6c0173 100644 --- a/pkgs/python-packages/comfyui/default.nix +++ b/pkgs/python-packages/comfyui/default.nix @@ -6,6 +6,7 @@ torchsde, torchvision, torchaudio, + numpy, einops, transformers, tokenizers, @@ -18,10 +19,16 @@ scipy, tqdm, psutil, + alembic, + sqlalchemy, + requests, + pydantic, kornia, spandrel, - soundfile, av, + comfyui-frontend-package, + comfyui-workflow-templates, + comfyui-embedded-docs, pkg-src, }: let @@ -30,6 +37,7 @@ let torchsde torchvision torchaudio + numpy einops transformers tokenizers @@ -42,15 +50,21 @@ let scipy tqdm psutil + alembic + sqlalchemy + requests + pydantic kornia spandrel - soundfile av + comfyui-frontend-package + comfyui-workflow-templates + comfyui-embedded-docs ]); in stdenvNoCC.mkDerivation { pname = "comfyui"; - version = "0.0.0"; + version = "0.11.0"; src = pkg-src; nativeBuildInputs = [ makeWrapper ]; dontConfigure = true; From 9bba5eb5c9b42c09e7d040e6bbcfb66f9cc2a4d5 Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 20:43:10 -0700 Subject: [PATCH 07/15] fix(comfyui): write asset DB to dataDir and add pydantic-settings Co-Authored-By: Claude Opus 4.8 --- pkgs/default.nix | 1 + pkgs/nixos/modules/comfyui/module.nix | 2 +- pkgs/python-packages/comfyui/default.nix | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/default.nix b/pkgs/default.nix index 498c40569..f39845ec7 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -450,6 +450,7 @@ rec { sqlalchemy = pyPkgs.sqlalchemy; requests = pyPkgs.requests; pydantic = pyPkgs.pydantic; + pydantic-settings = pyPkgs.pydantic-settings; kornia = pyPkgs.kornia; spandrel = pyPkgs.spandrel; av = pyPkgs.av; diff --git a/pkgs/nixos/modules/comfyui/module.nix b/pkgs/nixos/modules/comfyui/module.nix index e523f8b64..ac874b21b 100644 --- a/pkgs/nixos/modules/comfyui/module.nix +++ b/pkgs/nixos/modules/comfyui/module.nix @@ -65,7 +65,7 @@ in 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} --lowvram"; + 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" diff --git a/pkgs/python-packages/comfyui/default.nix b/pkgs/python-packages/comfyui/default.nix index 62b6c0173..46fbcb7fd 100644 --- a/pkgs/python-packages/comfyui/default.nix +++ b/pkgs/python-packages/comfyui/default.nix @@ -23,6 +23,7 @@ sqlalchemy, requests, pydantic, + pydantic-settings, kornia, spandrel, av, @@ -54,6 +55,7 @@ let sqlalchemy requests pydantic + pydantic-settings kornia spandrel av From 2ac637dd2ed6d2c071eda5803160225a9b34e3eb Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 21:04:12 -0700 Subject: [PATCH 08/15] style: nixfmt pkgs/default.nix Co-Authored-By: Claude Opus 4.8 --- pkgs/default.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/default.nix b/pkgs/default.nix index f39845ec7..bb9c7200c 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -153,7 +153,9 @@ let 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-core = + pySelf.callPackage ./python-packages/comfyui-workflow-templates-core + { }; 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 { }; From 48374fd67a1224aa507fdf373018c00871e878a5 Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 21:09:53 -0700 Subject: [PATCH 09/15] docs: document ComfyUI service and manual model setup Co-Authored-By: Claude Opus 4.8 --- docs/src/machines.md | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/src/machines.md b/docs/src/machines.md index 7a4720533..42fe46769 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) +- **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 From 366062abe5aeefc19bf3956351bb95cb95b82e5b Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 21:35:54 -0700 Subject: [PATCH 10/15] fix(comfyui): package workflow-template media bundles Co-Authored-By: Claude Opus 4.8 --- index.json | 20 +++++++++++++++++++ pkgs/default.nix | 4 ++++ .../default.nix | 19 ++++++++++++++++++ .../default.nix | 19 ++++++++++++++++++ .../default.nix | 19 ++++++++++++++++++ .../default.nix | 19 ++++++++++++++++++ .../comfyui-workflow-templates/default.nix | 12 ++++++++++- 7 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 pkgs/python-packages/comfyui-workflow-templates-media-api/default.nix create mode 100644 pkgs/python-packages/comfyui-workflow-templates-media-image/default.nix create mode 100644 pkgs/python-packages/comfyui-workflow-templates-media-other/default.nix create mode 100644 pkgs/python-packages/comfyui-workflow-templates-media-video/default.nix diff --git a/index.json b/index.json index f32dcd1e6..349f9e97a 100644 --- a/index.json +++ b/index.json @@ -350,6 +350,26 @@ "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, diff --git a/pkgs/default.nix b/pkgs/default.nix index bb9c7200c..5f4007c1f 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -156,6 +156,10 @@ let 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 { }; 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 index 1c71ad635..32164e73e 100644 --- a/pkgs/python-packages/comfyui-workflow-templates/default.nix +++ b/pkgs/python-packages/comfyui-workflow-templates/default.nix @@ -2,6 +2,10 @@ 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"; @@ -14,7 +18,13 @@ buildPythonPackage rec { python = "py3"; hash = "sha256-y6z8TJc0fFlyEYL5vzUYQkUHbeNo7bruy+qQGlqPhSg="; }; - propagatedBuildInputs = [ comfyui-workflow-templates-core ]; + 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."; From 6e75854ac81ac28e16e509bb11dcbf92c602110c Mon Sep 17 00:00:00 2001 From: "goromal (bot)" Date: Mon, 15 Jun 2026 04:39:45 +0000 Subject: [PATCH 11/15] Lint format --- pkgs/default.nix | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pkgs/default.nix b/pkgs/default.nix index 5f4007c1f..4f7b6dcbd 100755 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -156,10 +156,18 @@ let 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-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 { }; From ac8763f6fd31cc24333f2169a49b8c2b987d6acb Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 22:28:53 -0700 Subject: [PATCH 12/15] fix(comfyui): forward raw URI so encoded slashes survive nginx proxy ComfyUI's /userdata/{file} API encodes subdir slashes as %2F; the prefix-stripping proxy_pass decoded them, breaking the single-segment route (HTTP 405 on workflow save). Forward $request_uri verbatim instead. Co-Authored-By: Claude Opus 4.8 --- pkgs/nixos/modules/comfyui/module.nix | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/nixos/modules/comfyui/module.nix b/pkgs/nixos/modules/comfyui/module.nix index ac874b21b..b1d9accb2 100644 --- a/pkgs/nixos/modules/comfyui/module.nix +++ b/pkgs/nixos/modules/comfyui/module.nix @@ -40,9 +40,15 @@ in services.nginx.virtualHosts."${config.networking.hostName}.local" = { locations."/comfyui/" = { - proxyPass = "http://127.0.0.1:${builtins.toString cfg.port}/"; - proxyWebsockets = true; extraConfig = '' + set $comfyui_fwd $request_uri; + if ($comfyui_fwd ~ ^/comfyui(/.*)$) { + set $comfyui_fwd $1; + } + proxy_pass http://127.0.0.1:${builtins.toString cfg.port}$comfyui_fwd; + 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; From 103b7850c440c6a6aaa9610cfae57c57fe67ec5d Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 22:29:11 -0700 Subject: [PATCH 13/15] docs: note ComfyUI raw-URI nginx forwarding for userdata saves Co-Authored-By: Claude Opus 4.8 --- docs/src/machines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/machines.md b/docs/src/machines.md index 42fe46769..56137b098 100644 --- a/docs/src/machines.md +++ b/docs/src/machines.md @@ -561,7 +561,7 @@ ComfyUI rescans the `checkpoints` folder automatically (no service restart neede ### 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) +- **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_uri` (minus the `/comfyui` prefix) rather than a prefix-stripped path, so the `%2F`-encoded slashes in ComfyUI's `/userdata/{file}` API (e.g. saving `workflows/foo.json`) survive and don't break with HTTP 405. - **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`. From fca9f89a729a6d11716a970b7e0b19a644ac9840 Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 22:42:09 -0700 Subject: [PATCH 14/15] fix(comfyui): preserve query string when forwarding raw URI to ComfyUI The raw-URI fix forwarded $request_uri (incl. query) through a variable proxy_pass, so nginx percent-encoded the '?' into the userdata filename (workflows saved as 'castle1.json?overwrite=...'). Split path and query into custom variables and rejoin as $path?$query; avoids $args so the config still passes the gixy SSRF lint. Co-Authored-By: Claude Opus 4.8 --- docs/src/machines.md | 2 +- pkgs/nixos/modules/comfyui/module.nix | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/src/machines.md b/docs/src/machines.md index 56137b098..f4314cfcd 100644 --- a/docs/src/machines.md +++ b/docs/src/machines.md @@ -561,7 +561,7 @@ ComfyUI rescans the `checkpoints` folder automatically (no service restart neede ### 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_uri` (minus the `/comfyui` prefix) rather than a prefix-stripped path, so the `%2F`-encoded slashes in ComfyUI's `/userdata/{file}` API (e.g. saving `workflows/foo.json`) survive and don't break with HTTP 405. +- **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`. diff --git a/pkgs/nixos/modules/comfyui/module.nix b/pkgs/nixos/modules/comfyui/module.nix index b1d9accb2..07e21042c 100644 --- a/pkgs/nixos/modules/comfyui/module.nix +++ b/pkgs/nixos/modules/comfyui/module.nix @@ -41,11 +41,16 @@ in services.nginx.virtualHosts."${config.networking.hostName}.local" = { locations."/comfyui/" = { extraConfig = '' - set $comfyui_fwd $request_uri; - if ($comfyui_fwd ~ ^/comfyui(/.*)$) { - set $comfyui_fwd $1; + set $comfyui_path $request_uri; + set $comfyui_query ""; + if ($comfyui_path ~ "^/comfyui(/[^?]*)\?(.*)$") { + set $comfyui_path $1; + set $comfyui_query $2; } - proxy_pass http://127.0.0.1:${builtins.toString cfg.port}$comfyui_fwd; + 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; From ba0a4e00bf50e34fd3fc8131b20caf36ddd9fd2a Mon Sep 17 00:00:00 2001 From: Andrew Torgesen Date: Sun, 14 Jun 2026 22:55:08 -0700 Subject: [PATCH 15/15] fix(comfyui): raise nginx upload limit to 100m for source images The default 10m client_max_body_size rejected high-res source-image uploads (img2img/inpaint) with HTTP 413. Match ComfyUI's own 100MB default. Co-Authored-By: Claude Opus 4.8 --- pkgs/nixos/modules/comfyui/module.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/nixos/modules/comfyui/module.nix b/pkgs/nixos/modules/comfyui/module.nix index 07e21042c..b974d22d1 100644 --- a/pkgs/nixos/modules/comfyui/module.nix +++ b/pkgs/nixos/modules/comfyui/module.nix @@ -41,6 +41,7 @@ in 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(/[^?]*)\?(.*)$") {