|
6 | 6 | }: |
7 | 7 |
|
8 | 8 | let |
9 | | - python = pkgs.python312; |
| 9 | + comfyHome = "/store/comfyui"; |
| 10 | + comfyVersion = "v0.3.76"; |
10 | 11 |
|
11 | | - # Library dependencies needed at runtime |
| 12 | + # All runtime libraries needed by PyTorch and other compiled Python packages |
12 | 13 | libPath = lib.makeLibraryPath ( |
13 | 14 | with pkgs; |
14 | 15 | [ |
15 | | - gcc-unwrapped.lib |
| 16 | + stdenv.cc.cc.lib # libstdc++.so.6 |
16 | 17 | glib |
17 | 18 | glibc |
18 | 19 | libGL |
19 | 20 | libGLU |
20 | 21 | ncurses5 |
21 | | - rocmPackages.clr |
22 | | - rocmPackages.clr.icd |
23 | | - rocmPackages.rocm-runtime |
| 22 | + zlib |
| 23 | + zstd |
24 | 24 | xorg.libX11 |
25 | 25 | xorg.libXext |
26 | 26 | xorg.libXfixes |
27 | 27 | xorg.libXrender |
28 | | - zlib |
29 | | - zstd |
| 28 | + rocmPackages.clr |
| 29 | + rocmPackages.clr.icd |
| 30 | + rocmPackages.rocm-runtime |
30 | 31 | ] |
31 | 32 | ); |
32 | 33 |
|
33 | | - # Create a wrapper script with all dependencies available |
34 | | - # NOTE: Using Bash instead of Fish because Python venv activation requires Bash/POSIX shell |
35 | | - comfyuiScript = pkgs.writeShellScript "comfyui-start" '' |
36 | | - #!${pkgs.bash}/bin/bash |
| 34 | + # Startup script (Bash required for venv activation) |
| 35 | + comfyScript = pkgs.writeShellScript "comfyui-start" '' |
37 | 36 | set -e |
| 37 | + cd "${comfyHome}" |
38 | 38 |
|
39 | | - COMFYUI_HOME="''${COMFYUI_HOME:-/store/comfyui}" |
40 | | - COMFYUI_VERSION="''${COMFYUI_VERSION:-v0.3.57}" |
41 | | -
|
42 | | - cd "$COMFYUI_HOME" |
| 39 | + # Set library path before anything else |
| 40 | + export LD_LIBRARY_PATH="${libPath}:''${LD_LIBRARY_PATH:-}" |
43 | 41 |
|
44 | | - # Create virtual environment if it doesn't exist |
45 | | - if [ ! -d "$COMFYUI_HOME/venv" ]; then |
46 | | - echo "Creating Python virtual environment..." |
47 | | - ${python}/bin/python3.12 -m venv "$COMFYUI_HOME/venv" |
| 42 | + # Initialize venv if needed |
| 43 | + if [ ! -d "${comfyHome}/venv" ]; then |
| 44 | + echo "Creating Python virtual environment..." |
| 45 | + ${pkgs.python312}/bin/python3 -m venv "${comfyHome}/venv" |
48 | 46 | fi |
49 | 47 |
|
50 | | - # Activate virtual environment |
51 | | - source "$COMFYUI_HOME/venv/bin/activate" |
| 48 | + source "${comfyHome}/venv/bin/activate" |
52 | 49 |
|
53 | | - # Set library paths AFTER activating venv (venv activation can reset these) |
| 50 | + # Re-export after venv activation (it can reset LD_LIBRARY_PATH) |
54 | 51 | export LD_LIBRARY_PATH="${libPath}:''${LD_LIBRARY_PATH:-}" |
55 | 52 |
|
56 | | - # Upgrade pip |
| 53 | + # Use venv's pip (not Nix's, which has PEP 668 protection) |
57 | 54 | pip install --upgrade pip --quiet |
58 | 55 |
|
59 | | - # Install/upgrade PyTorch for ROCm if needed |
| 56 | + # Install PyTorch for ROCm if missing |
60 | 57 | if ! python -c "import torch" 2>/dev/null || [ "''${FORCE_REINSTALL:-0}" = "1" ]; then |
61 | | - echo "Installing PyTorch nightly for ROCm 6.4..." |
62 | | - pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/rocm6.4/ |
| 58 | + echo "Installing PyTorch nightly for ROCm 6.4..." |
| 59 | + pip install --pre torch torchvision torchaudio \ |
| 60 | + --index-url https://download.pytorch.org/whl/nightly/rocm6.4/ |
63 | 61 | fi |
64 | 62 |
|
65 | | - # Clone/update ComfyUI if needed |
66 | | - if [ ! -f "$COMFYUI_HOME/main.py" ]; then |
67 | | - echo "Downloading ComfyUI ''${COMFYUI_VERSION}..." |
68 | | - ${pkgs.git}/bin/git clone https://github.com/comfyanonymous/ComfyUI.git "$COMFYUI_HOME/temp" |
69 | | - cd "$COMFYUI_HOME/temp" |
70 | | - ${pkgs.git}/bin/git checkout "''${COMFYUI_VERSION}" |
71 | | - cp -r ./* "$COMFYUI_HOME/" |
72 | | - cd "$COMFYUI_HOME" |
73 | | - rm -rf "$COMFYUI_HOME/temp" |
| 63 | + # Clone ComfyUI if missing |
| 64 | + if [ ! -d "${comfyHome}/.git" ]; then |
| 65 | + echo "Downloading ComfyUI ${comfyVersion}..." |
| 66 | + # Clone to temp, then move everything including .git |
| 67 | + ${pkgs.git}/bin/git clone https://github.com/comfyanonymous/ComfyUI.git "${comfyHome}/temp" |
| 68 | + cd "${comfyHome}/temp" && ${pkgs.git}/bin/git checkout "${comfyVersion}" |
| 69 | + shopt -s dotglob # Include hidden files in glob |
| 70 | + cp -r "${comfyHome}/temp"/* "${comfyHome}/" |
| 71 | + shopt -u dotglob |
| 72 | + rm -rf "${comfyHome}/temp" |
74 | 73 | fi |
75 | 74 |
|
76 | | - # Install ComfyUI requirements |
77 | | - if [ -f "$COMFYUI_HOME/requirements.txt" ]; then |
78 | | - echo "Installing ComfyUI requirements..." |
79 | | - pip install -r requirements.txt --quiet |
80 | | - fi |
| 75 | + # Install requirements |
| 76 | + [ -f requirements.txt ] && pip install -r requirements.txt --quiet |
81 | 77 |
|
82 | | - # Set up compiler environment for building packages |
| 78 | + # Build tools for compiling packages like insightface |
83 | 79 | export CC="${pkgs.gcc}/bin/gcc" |
84 | 80 | export CXX="${pkgs.gcc}/bin/g++" |
85 | | - export CMAKE_C_COMPILER="${pkgs.gcc}/bin/gcc" |
86 | | - export CMAKE_CXX_COMPILER="${pkgs.gcc}/bin/g++" |
87 | 81 | export PATH="${pkgs.gcc}/bin:${pkgs.cmake}/bin:$PATH" |
88 | 82 |
|
89 | | - # Install missing dependencies for custom nodes |
90 | | - echo "Installing custom node dependencies..." |
| 83 | + # Install common custom node dependencies |
91 | 84 | pip install --quiet \ |
92 | | - bitsandbytes \ |
93 | | - Cython \ |
94 | | - deepdiff \ |
95 | | - diffusers \ |
96 | | - docstring-parser \ |
97 | | - ftfy \ |
98 | | - gguf \ |
99 | | - GitPython \ |
100 | | - imageio-ffmpeg \ |
101 | | - llama-cpp-agent \ |
102 | | - llama-cpp-python \ |
103 | | - mkdocs \ |
104 | | - mkdocs-material \ |
105 | | - "mkdocstrings[python]" \ |
106 | | - numpy \ |
107 | | - opencv-contrib-python \ |
108 | | - opencv-python \ |
109 | | - piexif \ |
110 | | - py-cpuinfo \ |
111 | | - pynvml \ |
112 | | - simpleeval \ |
113 | | - timm \ |
114 | | - toml \ |
115 | | - "transformers==4.38.2" \ |
116 | | - uv \ |
117 | | - yt-dlp |
118 | | -
|
119 | | - # Install insightface with proper library path and compiler path for compilation |
120 | | - echo "Installing insightface..." |
121 | | - PATH="${pkgs.gcc}/bin:$PATH" \ |
122 | | - LD_LIBRARY_PATH="${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH" \ |
123 | | - pip install --no-build-isolation insightface --quiet || \ |
124 | | - echo "Warning: insightface installation failed, pulid node may not work" |
125 | | -
|
126 | | - # Create necessary directories |
127 | | - mkdir -p "$COMFYUI_HOME"/{input,output,models,custom_nodes,user,cache} |
128 | | -
|
129 | | - # Handle UV cache directory - remove if problematic and let uv recreate it |
130 | | - if [ -d "$COMFYUI_HOME/cache/uv" ]; then |
131 | | - # Check if we can write to it |
132 | | - if ! touch "$COMFYUI_HOME/cache/uv/.test" 2>/dev/null; then |
133 | | - echo "UV cache has permission issues, removing and recreating..." |
134 | | - rm -rf "$COMFYUI_HOME/cache/uv" 2>/dev/null || { |
135 | | - echo "Cannot remove UV cache, moving to backup..." |
136 | | - mv "$COMFYUI_HOME/cache/uv" "$COMFYUI_HOME/cache/uv.backup.$(date +%s)" 2>/dev/null || true |
137 | | - } |
138 | | - else |
139 | | - rm -f "$COMFYUI_HOME/cache/uv/.test" |
140 | | - fi |
141 | | - fi |
142 | | -
|
143 | | - # Set UV cache environment variable to ensure it uses the right location |
144 | | - export UV_CACHE_DIR="$COMFYUI_HOME/cache/uv" |
| 85 | + bitsandbytes Cython deepdiff diffusers docstring-parser ftfy gguf \ |
| 86 | + GitPython imageio-ffmpeg llama-cpp-agent llama-cpp-python \ |
| 87 | + mkdocs mkdocs-material "mkdocstrings[python]" numpy \ |
| 88 | + opencv-contrib-python opencv-python piexif py-cpuinfo pynvml \ |
| 89 | + simpleeval timm toml "transformers==4.38.2" uv yt-dlp |
145 | 90 |
|
146 | | - # Set library path for compilation |
147 | | - export LD_LIBRARY_PATH="${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH" |
148 | | -
|
149 | | - # Set environment variables for ROCm |
150 | | - export HSA_OVERRIDE_GFX_VERSION="''${HSA_OVERRIDE_GFX_VERSION:-11.0.0}" |
151 | | - export HIP_VISIBLE_DEVICES="''${HIP_VISIBLE_DEVICES:-0}" |
152 | | - # More aggressive memory management for AMD GPUs |
153 | | - export PYTORCH_HIP_ALLOC_CONF="garbage_collection_threshold:0.6,max_split_size_mb:256" |
154 | | - export PYTORCH_TUNABLEOP_ENABLED="1" |
155 | | - # Force PyTorch to use less aggressive memory allocation |
156 | | - export PYTORCH_CUDA_ALLOC_CONF="max_split_size_mb:256,garbage_collection_threshold:0.6" |
157 | | - export TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL="1" |
158 | | - export CUDA_VISIBLE_DEVICES="" # Disable CUDA |
159 | | - export MIOPEN_DISABLE_CACHE="1" # Helps with miopenStatusUnknownError |
160 | | - export MIOPEN_USER_DB_PATH="$COMFYUI_HOME/cache/miopen" # Custom MIOpen cache location |
161 | | -
|
162 | | - # Set ComfyUI paths |
163 | | - export COMFYUI_MODEL_PATH="$COMFYUI_HOME/models" |
164 | | - export COMFYUI_INPUT_PATH="$COMFYUI_HOME/input" |
165 | | - export COMFYUI_OUTPUT_PATH="$COMFYUI_HOME/output" |
166 | | - export HOME="$COMFYUI_HOME" |
167 | | - export XDG_CACHE_HOME="$COMFYUI_HOME/cache" |
| 91 | + # insightface needs special handling |
| 92 | + pip install --no-build-isolation insightface --quiet 2>/dev/null || \ |
| 93 | + echo "Warning: insightface installation failed (pulid node may not work)" |
168 | 94 |
|
169 | 95 | echo "Starting ComfyUI..." |
170 | 96 | exec python main.py \ |
171 | | - --listen "''${COMFYUI_HOST:-0.0.0.0}" \ |
172 | | - --port "''${COMFYUI_PORT:-8188}" \ |
173 | | - --highvram \ |
174 | | - --use-pytorch-cross-attention \ |
175 | | - "$@" |
| 97 | + --listen "''${COMFYUI_HOST:-0.0.0.0}" \ |
| 98 | + --port "''${COMFYUI_PORT:-8188}" \ |
| 99 | + --reserve-vram 0.5 \ |
| 100 | + --lowvram \ |
| 101 | + --use-pytorch-cross-attention \ |
| 102 | + --disable-xformers \ |
| 103 | + --bf16-unet \ |
| 104 | + --fast \ |
| 105 | + "$@" |
176 | 106 | ''; |
177 | 107 | in |
178 | 108 | { |
179 | | - # System packages - these will be available globally |
| 109 | + # System packages for debugging/monitoring |
180 | 110 | environment.systemPackages = with pkgs; [ |
181 | | - python312 |
182 | | - python312Packages.pip |
183 | | - python312Packages.virtualenv |
184 | | - git |
185 | | - ffmpeg_8-full # Required for video processing nodes |
186 | | - gcc # Required for building some Python packages |
187 | | - cmake # Required for llama-cpp-python |
188 | | - |
189 | | - # ROCm tools |
190 | 111 | rocmPackages.rocm-smi |
191 | 112 | rocmPackages.rocminfo |
192 | 113 | ]; |
193 | 114 |
|
194 | | - # Install fonts system-wide for ComfyUI nodes |
| 115 | + # Fonts for ComfyUI text nodes |
195 | 116 | fonts.packages = with pkgs; [ |
196 | 117 | noto-fonts |
197 | 118 | liberation_ttf |
198 | 119 | dejavu_fonts |
199 | 120 | ]; |
200 | 121 |
|
201 | | - # Enable AMD GPU support |
| 122 | + # AMD GPU support |
202 | 123 | hardware.graphics = { |
203 | 124 | enable = true; |
204 | 125 | extraPackages = with pkgs; [ |
|
209 | 130 | ]; |
210 | 131 | }; |
211 | 132 |
|
212 | | - # Ensure directories exist (owned by uid 1000, gid 1004) |
| 133 | + # Directory structure |
213 | 134 | systemd.tmpfiles.rules = [ |
214 | | - "d /store/comfyui 0755 1000 1004 -" |
215 | | - "d /store/comfyui/input 0755 1000 1004 -" |
216 | | - "d /store/comfyui/output 0755 1000 1004 -" |
217 | | - "d /store/comfyui/models 0755 1000 1004 -" |
218 | | - "d /store/comfyui/custom_nodes 0755 1000 1004 -" |
219 | | - "d /store/comfyui/user 0755 1000 1004 -" |
220 | | - "d /store/comfyui/cache 0755 1000 1004 -" |
221 | | - "d /store/comfyui/temp 0755 1000 1004 -" |
| 135 | + "d ${comfyHome} 0755 1000 1004 -" |
| 136 | + "d ${comfyHome}/input 0755 1000 1004 -" |
| 137 | + "d ${comfyHome}/output 0755 1000 1004 -" |
| 138 | + "d ${comfyHome}/models 0755 1000 1004 -" |
| 139 | + "d ${comfyHome}/custom_nodes 0755 1000 1004 -" |
| 140 | + "d ${comfyHome}/user 0755 1000 1004 -" |
| 141 | + "d ${comfyHome}/cache 0755 1000 1004 -" |
222 | 142 | ]; |
223 | 143 |
|
224 | | - # Simple systemd service |
225 | 144 | systemd.services.comfyui = { |
226 | 145 | description = "ComfyUI - Stable Diffusion GUI"; |
227 | 146 | after = [ "network.target" ]; |
228 | 147 | wantedBy = [ "multi-user.target" ]; |
229 | 148 |
|
| 149 | + path = with pkgs; [ |
| 150 | + coreutils |
| 151 | + findutils |
| 152 | + gnugrep |
| 153 | + gnused |
| 154 | + git |
| 155 | + python312 |
| 156 | + bash |
| 157 | + ffmpeg_8-full |
| 158 | + gcc |
| 159 | + cmake |
| 160 | + ]; |
| 161 | + |
230 | 162 | serviceConfig = { |
231 | 163 | Type = "simple"; |
232 | 164 | User = "1000"; |
233 | | - Group = "1004"; # ryot |
234 | | - WorkingDirectory = "/store/comfyui"; |
| 165 | + Group = "1004"; |
| 166 | + WorkingDirectory = comfyHome; |
| 167 | + ExecStart = "${comfyScript}"; |
235 | 168 |
|
236 | | - # Use our Nix-provided script |
237 | | - ExecStart = "${comfyuiScript}"; |
238 | | - |
239 | | - # Restart on failure |
240 | 169 | Restart = "on-failure"; |
241 | 170 | RestartSec = "10s"; |
242 | 171 |
|
243 | | - # Memory limits |
244 | 172 | MemoryMax = "32G"; |
245 | 173 | MemorySwapMax = "8G"; |
246 | 174 |
|
247 | | - # Security settings - more permissive for dynamic Python env |
248 | | - PrivateTmp = false; # Allow access to /tmp for pip |
249 | | - ProtectSystem = false; # Allow pip to install packages |
250 | | - ProtectHome = false; # User might need home access |
251 | | - ReadWritePaths = [ "/store/comfyui" ]; |
| 175 | + PrivateTmp = false; |
| 176 | + ProtectSystem = false; |
| 177 | + ProtectHome = false; |
| 178 | + ReadWritePaths = [ comfyHome ]; |
252 | 179 | }; |
253 | 180 |
|
254 | 181 | environment = { |
255 | | - PATH = lib.mkForce ( |
256 | | - lib.makeBinPath ( |
257 | | - with pkgs; |
258 | | - [ |
259 | | - coreutils |
260 | | - findutils |
261 | | - gnugrep |
262 | | - gnused |
263 | | - systemd |
264 | | - git # Critical for ComfyUI-Manager |
265 | | - python312 |
266 | | - bash |
267 | | - ffmpeg_8-full # For video processing nodes |
268 | | - ] |
269 | | - ) |
270 | | - ); |
271 | | - |
272 | 182 | LD_LIBRARY_PATH = libPath; |
273 | 183 |
|
274 | | - GIT_PYTHON_GIT_EXECUTABLE = "${pkgs.git}/bin/git"; |
275 | | - PYTHONUNBUFFERED = "1"; |
276 | | - |
277 | | - COMFYUI_HOME = "/store/comfyui"; |
278 | | - COMFYUI_HOST = "0.0.0.0"; |
279 | | - COMFYUI_PORT = "8188"; |
280 | | - |
281 | 184 | # ROCm configuration |
282 | 185 | HSA_OVERRIDE_GFX_VERSION = "11.0.0"; |
283 | 186 | HIP_VISIBLE_DEVICES = "0"; |
| 187 | + CUDA_VISIBLE_DEVICES = ""; |
| 188 | + |
| 189 | + # Memory management |
| 190 | + PYTORCH_HIP_ALLOC_CONF = "garbage_collection_threshold:0.6,max_split_size_mb:256"; |
| 191 | + PYTORCH_CUDA_ALLOC_CONF = "max_split_size_mb:256,garbage_collection_threshold:0.6"; |
| 192 | + PYTORCH_TUNABLEOP_ENABLED = "1"; |
| 193 | + TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL = "1"; |
| 194 | + |
| 195 | + # MIOpen settings |
| 196 | + MIOPEN_DISABLE_CACHE = "1"; |
| 197 | + MIOPEN_USER_DB_PATH = "${comfyHome}/cache/miopen"; |
| 198 | + |
| 199 | + # Paths |
| 200 | + HOME = comfyHome; |
| 201 | + XDG_CACHE_HOME = "${comfyHome}/cache"; |
| 202 | + UV_CACHE_DIR = "${comfyHome}/cache/uv"; |
| 203 | + COMFYUI_MODEL_PATH = "${comfyHome}/models"; |
| 204 | + COMFYUI_INPUT_PATH = "${comfyHome}/input"; |
| 205 | + COMFYUI_OUTPUT_PATH = "${comfyHome}/output"; |
| 206 | + |
| 207 | + # Service settings |
| 208 | + PYTHONUNBUFFERED = "1"; |
| 209 | + GIT_PYTHON_GIT_EXECUTABLE = "${pkgs.git}/bin/git"; |
| 210 | + COMFYUI_HOST = "0.0.0.0"; |
| 211 | + COMFYUI_PORT = "8188"; |
284 | 212 | }; |
285 | 213 | }; |
286 | 214 | } |
0 commit comments