comfyui-mcp 0.41.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/orchestrator/gemini-backend.js +109 -29
- package/dist/orchestrator/gemini-backend.js.map +1 -1
- package/dist/orchestrator/index.js +106 -5
- package/dist/orchestrator/index.js.map +1 -1
- package/dist/orchestrator/panel-agent.js +12 -1
- package/dist/orchestrator/panel-agent.js.map +1 -1
- package/dist/services/ai-toolkit.js +220 -0
- package/dist/services/ai-toolkit.js.map +1 -0
- package/dist/services/training-config.js +138 -0
- package/dist/services/training-config.js.map +1 -0
- package/dist/services/training-jobs.js +654 -0
- package/dist/services/training-jobs.js.map +1 -0
- package/dist/services/workflow-validator.js +4 -0
- package/dist/services/workflow-validator.js.map +1 -1
- package/dist/tools/diagnostics.js +120 -1
- package/dist/tools/diagnostics.js.map +1 -1
- package/dist/tools/index.js +63 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/train.js +187 -0
- package/dist/tools/train.js.map +1 -0
- package/docker/runpod/.gitattributes +8 -0
- package/docker/runpod/Dockerfile +486 -0
- package/docker/runpod/README.md +658 -0
- package/docker/runpod/config.ini +28 -0
- package/docker/runpod/deploy-dockerhub.sh +46 -0
- package/docker/runpod/extra_model_paths.yaml +61 -0
- package/docker/runpod/nginx.conf +124 -0
- package/docker/runpod/post_start.sh +619 -0
- package/docker/runpod/starting.html +47 -0
- package/docker/runpod/test_image.sh +180 -0
- package/docker/runpod/verify_image_remote.py +126 -0
- package/docker/trainer/Dockerfile +69 -0
- package/package.json +2 -1
- package/plugin/skills/train-character-lora/SKILL.md +83 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
# comfyui-mcp RunPod image — FAST RESTART (image-immutable software)
|
|
2
|
+
|
|
3
|
+
A RunPod image that boots **ready to be driven by the
|
|
4
|
+
[comfyui-mcp](https://github.com/artokun/comfyui-mcp) Agent Panel**. Deploy on
|
|
5
|
+
RunPod, run **one local command** on your laptop, and the agent drives the pod's
|
|
6
|
+
live ComfyUI graph from your Claude/ChatGPT subscription.
|
|
7
|
+
|
|
8
|
+
It is optimized for **fast stop/start**. All the software — ComfyUI + its venv +
|
|
9
|
+
`comfyui_manager` v2 + the Agent Panel custom node — is **baked into the
|
|
10
|
+
(immutable) image** at `/opt/ComfyUI` and **run directly from there**. The
|
|
11
|
+
`/workspace` network volume holds **only your data** (`user/`, `models/`,
|
|
12
|
+
`input/`, `output/`). A warm restart does **no install, no sync, no seed** — it
|
|
13
|
+
just `mkdir -p` the data dirs and launches ComfyUI (~**30-60s** ComfyUI init).
|
|
14
|
+
|
|
15
|
+
> **Testing:** every build ends in an in-Dockerfile integrity gate, and
|
|
16
|
+
> [`test_image.sh`](#test-before-you-push-post-build-gate) runs a full boot
|
|
17
|
+
> suite (fresh volume → redeploy → corruption self-heal) before any push;
|
|
18
|
+
> `deploy-dockerhub.sh` makes that gate mandatory for the official image.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## TL;DR
|
|
23
|
+
|
|
24
|
+
1. **Build & push** the image (a machine with Docker; no GPU needed).
|
|
25
|
+
See [Build & push](#build--push).
|
|
26
|
+
2. **Deploy** on RunPod: GPU pod (e.g. RTX 5090), **expose HTTP 3000**, attach a
|
|
27
|
+
**network volume at `/workspace`**. See [Deploy on RunPod](#deploy-on-runpod).
|
|
28
|
+
3. On your laptop:
|
|
29
|
+
```bash
|
|
30
|
+
npx -y comfyui-mcp@latest connect https://<pod-id>-3000.proxy.runpod.net
|
|
31
|
+
```
|
|
32
|
+
4. Open the pod's ComfyUI, open the **Agent Panel** sidebar, enable the
|
|
33
|
+
external-orchestrator toggle, hit **Connect**, and drive the graph in natural
|
|
34
|
+
language.
|
|
35
|
+
|
|
36
|
+
The agent's brain (the **panel orchestrator**) runs **locally on your machine**
|
|
37
|
+
on your own subscription — see [Topology](#topology-where-the-agent-runs).
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## The fast-restart model (what changed and why)
|
|
42
|
+
|
|
43
|
+
The previous design **seeded/synced** ComfyUI + its venv onto `/workspace` on the
|
|
44
|
+
first boot and re-synced on upgrades. That made the volume the source of truth for
|
|
45
|
+
software, which is slow to sync, fragile to upgrade (the `rsync -u` venv caveat),
|
|
46
|
+
and couples software to the data volume.
|
|
47
|
+
|
|
48
|
+
This design **inverts** that:
|
|
49
|
+
|
|
50
|
+
| Concern | Where it lives | Persists a restart? |
|
|
51
|
+
|---------|----------------|---------------------|
|
|
52
|
+
| ComfyUI install + venv | **image** `/opt/ComfyUI` (immutable) | n/a (re-pulled with the image) |
|
|
53
|
+
| `custom_nodes` (Agent Panel + your installs) | **volume** `/workspace/custom_nodes` (symlinked; image nodes seeded each boot) | **Yes** |
|
|
54
|
+
| ComfyUI-Manager | **image** venv (pip package) | n/a (in the image) |
|
|
55
|
+
| Custom-node pip cache | **volume** `/workspace/.cache/pip` | **Yes** |
|
|
56
|
+
| Other caches (HF / torch / npm) | **container** ephemeral disk | **No** — ephemeral |
|
|
57
|
+
| `user/` (workflows + settings + Manager config) | **volume** `/workspace/user` | **Yes** |
|
|
58
|
+
| `models/` (incl. Manager downloads) | **volume** `/workspace/models` | **Yes** |
|
|
59
|
+
| `input/` | **volume** `/workspace/input` | **Yes** |
|
|
60
|
+
| `output/` | **volume** `/workspace/output` | **Yes** |
|
|
61
|
+
|
|
62
|
+
**Result:** the base ComfyUI + venv boot fast from the immutable image; only your
|
|
63
|
+
data **and your custom nodes** live on the volume. A restart is `mkdir -p` the
|
|
64
|
+
user-data dirs, symlink + seed `custom_nodes`, reinstall node deps from the
|
|
65
|
+
persistent cache, and launch from the baked venv. No full install/sync/seed.
|
|
66
|
+
|
|
67
|
+
### Custom nodes persist on the volume
|
|
68
|
+
|
|
69
|
+
`custom_nodes` is **symlinked to `/workspace/custom_nodes`**, so **custom nodes the
|
|
70
|
+
agent or Manager install at runtime survive a restart** — while the base ComfyUI +
|
|
71
|
+
venv still boot fast from the immutable image.
|
|
72
|
+
|
|
73
|
+
* **How it works (each boot).** The entrypoint symlinks
|
|
74
|
+
`/opt/ComfyUI/custom_nodes` → `/workspace/custom_nodes`, seeds/refreshes the
|
|
75
|
+
image's baked nodes (Agent Panel + ComfyUI builtins) into it — so an image
|
|
76
|
+
upgrade always ships a current panel while **your** installed nodes are preserved
|
|
77
|
+
— then reinstalls each node's `requirements.txt` into the venv from a
|
|
78
|
+
**persistent pip cache** on the volume (fast after the first time).
|
|
79
|
+
* **Models DO persist** — Manager's install-model writes to `/workspace/models`
|
|
80
|
+
(see [Model paths](#model-paths-extra_model_pathsyaml)).
|
|
81
|
+
* **First install of a node** downloads its Python deps into the persistent cache;
|
|
82
|
+
every restart after re-materializes them from cache (the venv lives in the image,
|
|
83
|
+
so its packages are refreshed on boot). Compiled/CUDA-linked deps may rebuild
|
|
84
|
+
rather than unpack. To bake a node so it needs **zero** boot-time work, still add
|
|
85
|
+
it to the `Dockerfile` and rebuild.
|
|
86
|
+
|
|
87
|
+
### If the panel (or a node) shows up EMPTY — 0-byte files
|
|
88
|
+
|
|
89
|
+
A **full network volume** is the classic cause: on ENOSPC, `cp`/`git` still
|
|
90
|
+
*create* every file but write 0 bytes into them, so the node's whole file tree
|
|
91
|
+
exists as empty husks — ComfyUI lists the node, but nothing loads. Because the
|
|
92
|
+
volume persists, this used to survive every redeploy.
|
|
93
|
+
|
|
94
|
+
The entrypoint now defends itself:
|
|
95
|
+
|
|
96
|
+
* logs the volume's **free space** at boot and prints a loud warning under 500 MB;
|
|
97
|
+
* **skips the ~7 GB spotcheck-model copy** when the volume can't hold it;
|
|
98
|
+
* **verifies the Agent Panel** on the volume every boot and **self-heals** a
|
|
99
|
+
broken copy (re-clone from GitHub, or restore from the image seed offline);
|
|
100
|
+
* names any other custom node whose `__init__.py` is 0 bytes in the boot log
|
|
101
|
+
(`WARN: custom nodes with 0-byte __init__.py …`) — reinstall those via Manager.
|
|
102
|
+
|
|
103
|
+
If you see the ENOSPC warning: free or grow the volume, restart the pod, and the
|
|
104
|
+
panel repairs itself on the next boot.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Architecture (multi-stage)
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
ARG BASE_IMAGE = runpod/pytorch:1.0.7-cu1281-torch280-ubuntu2404 (lean, recent)
|
|
112
|
+
ARG RUNPOD_SRC_IMAGE = aitrepreneur/comfyui:2.3.5 (donor only)
|
|
113
|
+
|
|
114
|
+
┌─ STAGE A: runpod-donor ── ARG-gated (INCLUDE_RUNPOD_EXTRAS) ─────────┐
|
|
115
|
+
│ FROM aitrepreneur/comfyui:2.3.5 │
|
|
116
|
+
│ (built only so runpod-extras-1 can COPY service artifacts out of it;│
|
|
117
|
+
│ INCLUDE_RUNPOD_EXTRAS=0 -> runpod-extras-0 (empty), and BuildKit │
|
|
118
|
+
│ never builds/pulls this stage at all) │
|
|
119
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
120
|
+
┌─ spotcheck-0 / spotcheck-1 (alpine) ─ ARG-gated SDXL model carrier ──┐
|
|
121
|
+
│ spotcheck-1 = ADD sd_xl_base_1.0.safetensors ; spotcheck-0 = empty │
|
|
122
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
123
|
+
┌─ FINAL: FROM ${BASE_IMAGE} ─────────────────────────────────────────┐
|
|
124
|
+
│ apt: git cron nodejs … ; install code-server │
|
|
125
|
+
│ git clone ComfyUI (master) -> /opt/ComfyUI (BAKED, run from here) │
|
|
126
|
+
│ python -m venv /opt/ComfyUI/venv │
|
|
127
|
+
│ pip cu128 torch/vision/audio (NO xformers) │
|
|
128
|
+
│ pip -r requirements.txt ; pip comfyui_manager==4.2.2 │
|
|
129
|
+
│ rm classic custom_nodes/ComfyUI-Manager │
|
|
130
|
+
│ git clone comfyui-mcp-panel -> /opt/ComfyUI/custom_nodes/… │
|
|
131
|
+
│ COPY extra_model_paths.yaml -> /opt/ComfyUI/extra_model_paths.yaml │
|
|
132
|
+
│ COPY config.ini -> /opt/ComfyUI/config.ini.seed (Manager gate) │
|
|
133
|
+
│ COPY --from=spotcheck-src -> /opt/ComfyUI-seed-models │
|
|
134
|
+
│ COPY --from=runpod-extras /extras/ / (uploader, croc, app-manager)│
|
|
135
|
+
│ COPY nginx.conf (:3000->:3001), starting.html, post_start.sh │
|
|
136
|
+
│ (no ENTRYPOINT/CMD override — keep the base's /start.sh chain) │
|
|
137
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Boot sequence (what runs, in order)
|
|
141
|
+
|
|
142
|
+
The base image's `CMD` is **`/start.sh`** (from `runpod/containers`). On boot it:
|
|
143
|
+
|
|
144
|
+
1. `service nginx start` — reads our `/etc/nginx/nginx.conf` (**:3000 → :3001**,
|
|
145
|
+
websocket-aware, with the "starting" fallback page).
|
|
146
|
+
2. runs `/pre_start.sh` if present (we ship none).
|
|
147
|
+
3. `setup_ssh` — injects RunPod's `$PUBLIC_KEY` and starts sshd.
|
|
148
|
+
4. `start_jupyter` — starts JupyterLab on **:8888** if `$JUPYTER_PASSWORD` is set.
|
|
149
|
+
5. runs **our `/post_start.sh`** — `mkdir` the volume data dirs, assert the
|
|
150
|
+
Manager gate, start the ancillary services, and **launch ComfyUI from the
|
|
151
|
+
baked venv**.
|
|
152
|
+
6. `sleep infinity` — keeps the pod alive.
|
|
153
|
+
|
|
154
|
+
So SSH + Jupyter + nginx come from the base; **our hook adds everything else**.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## ComfyUI launch command (the exact flags)
|
|
159
|
+
|
|
160
|
+
`/post_start.sh` launches (from `cd /opt/ComfyUI`, with the baked venv python):
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
/opt/ComfyUI/venv/bin/python main.py \
|
|
164
|
+
--listen 0.0.0.0 --port 3001 \
|
|
165
|
+
--enable-manager \
|
|
166
|
+
--use-pytorch-cross-attention \
|
|
167
|
+
--user-directory /workspace/user \
|
|
168
|
+
--input-directory /workspace/input \
|
|
169
|
+
--output-directory /workspace/output \
|
|
170
|
+
--extra-model-paths-config /opt/ComfyUI/extra_model_paths.yaml
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
* **`--user-directory /workspace/user`** — workflows, ComfyUI settings, AND the
|
|
174
|
+
Manager config (see [Manager gate](#manager-remote-install-gate)) live on the
|
|
175
|
+
volume.
|
|
176
|
+
* **`--input-directory` / `--output-directory`** — inputs and generated images on
|
|
177
|
+
the volume.
|
|
178
|
+
* **`--extra-model-paths-config`** — points every model category at
|
|
179
|
+
`/workspace/models` (see below). MODELS persist on the volume.
|
|
180
|
+
* **We deliberately do NOT use `--base-directory`.** It would relocate
|
|
181
|
+
`custom_nodes` (and temp) onto the volume too — but we want `custom_nodes` to
|
|
182
|
+
stay **in the image**. The per-dir flags + `extra_model_paths.yaml` give us
|
|
183
|
+
exactly the split we want (data on the volume, software in the image).
|
|
184
|
+
|
|
185
|
+
> **Flag verification.** These flag names were verified against ComfyUI `master`
|
|
186
|
+
> (`comfy/cli_args.py`): `--user-directory`, `--input-directory`,
|
|
187
|
+
> `--output-directory`, `--base-directory`, and `--extra-model-paths-config` all
|
|
188
|
+
> exist with these exact spellings, and `--base-directory`'s own help text states
|
|
189
|
+
> it sets the base for "models, custom_nodes, input, output, temp, and user
|
|
190
|
+
> directories" — confirming why we avoid it. **Assumption to confirm at build:**
|
|
191
|
+
> the *pinned* `COMFYUI_REF` you bake actually ships these flags (they are present
|
|
192
|
+
> on recent `master`; an old pin may not have them). Run
|
|
193
|
+
> `"/opt/ComfyUI/venv/bin/python" /opt/ComfyUI/main.py --help` in the built image
|
|
194
|
+
> to confirm before publishing.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Model paths (`extra_model_paths.yaml`)
|
|
199
|
+
|
|
200
|
+
`extra_model_paths.yaml` is baked at `/opt/ComfyUI/extra_model_paths.yaml` and
|
|
201
|
+
loaded via `--extra-model-paths-config`. It maps **every** model category to a
|
|
202
|
+
subfolder under `/workspace/models`, with `is_default: true` so the volume is the
|
|
203
|
+
**primary** (download) location — i.e. Manager's install-model writes there and
|
|
204
|
+
the files persist.
|
|
205
|
+
|
|
206
|
+
```yaml
|
|
207
|
+
comfyui_mcp_volume:
|
|
208
|
+
base_path: /workspace
|
|
209
|
+
is_default: true # insert these paths at the FRONT → default target
|
|
210
|
+
|
|
211
|
+
checkpoints: models/checkpoints/
|
|
212
|
+
configs: models/configs/
|
|
213
|
+
loras: models/loras/
|
|
214
|
+
vae: models/vae/
|
|
215
|
+
text_encoders: | # ComfyUI key "text_encoders" (a.k.a. CLIP)
|
|
216
|
+
models/text_encoders/
|
|
217
|
+
models/clip/
|
|
218
|
+
diffusion_models: | # a.k.a. UNet
|
|
219
|
+
models/diffusion_models/
|
|
220
|
+
models/unet/
|
|
221
|
+
clip_vision: models/clip_vision/
|
|
222
|
+
style_models: models/style_models/
|
|
223
|
+
embeddings: models/embeddings/
|
|
224
|
+
diffusers: models/diffusers/
|
|
225
|
+
vae_approx: models/vae_approx/
|
|
226
|
+
controlnet: |
|
|
227
|
+
models/controlnet/
|
|
228
|
+
models/t2i_adapter/
|
|
229
|
+
gligen: models/gligen/
|
|
230
|
+
upscale_models: models/upscale_models/
|
|
231
|
+
latent_upscale_models: models/latent_upscale_models/
|
|
232
|
+
hypernetworks: models/hypernetworks/
|
|
233
|
+
photomaker: models/photomaker/
|
|
234
|
+
classifiers: models/classifiers/
|
|
235
|
+
model_patches: models/model_patches/
|
|
236
|
+
audio_encoders: models/audio_encoders/
|
|
237
|
+
background_removal: models/background_removal/
|
|
238
|
+
frame_interpolation: models/frame_interpolation/
|
|
239
|
+
geometry_estimation: models/geometry_estimation/
|
|
240
|
+
optical_flow: models/optical_flow/
|
|
241
|
+
detection: models/detection/
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Notes:
|
|
245
|
+
|
|
246
|
+
* **`is_default: true`** is the load-bearing line. ComfyUI's
|
|
247
|
+
`add_model_folder_path(..., is_default=True)` **inserts** the path at the front
|
|
248
|
+
of each category's list, so `/workspace/models/<cat>` becomes the default
|
|
249
|
+
download target. Without it, the image's `/opt/ComfyUI/models/<cat>` (ephemeral)
|
|
250
|
+
would stay first and Manager downloads would **not** persist.
|
|
251
|
+
* **No `custom_nodes:` key** — on purpose. Mapping `custom_nodes` to the volume
|
|
252
|
+
would break the fast-restart contract.
|
|
253
|
+
* `base_path: /workspace` with `models/...` relative subpaths mirrors ComfyUI's
|
|
254
|
+
own `extra_model_paths.yaml.example` convention.
|
|
255
|
+
* The category **keys** match ComfyUI's `folder_names_and_paths` keys (verified
|
|
256
|
+
against `master`'s `folder_paths.py`). The category list mirrors the example's
|
|
257
|
+
full set; harmless if a future ComfyUI renames one.
|
|
258
|
+
* `/post_start.sh` pre-creates the matching subfolders under `/workspace/models`
|
|
259
|
+
so they exist on a cold volume.
|
|
260
|
+
|
|
261
|
+
### Warm model volume (skip the cold HF pull)
|
|
262
|
+
|
|
263
|
+
A **fresh** network volume has an empty `models/` tree — the first time the
|
|
264
|
+
agent (or you) needs a checkpoint, it's a cold download from HuggingFace, which
|
|
265
|
+
can be tens of GB and the slowest part of getting a new pod usable.
|
|
266
|
+
|
|
267
|
+
The fix is the same idea as the image itself: **build once, reuse many times.**
|
|
268
|
+
|
|
269
|
+
1. **Build a seed volume once.** Spin up a pod with this image + a network
|
|
270
|
+
volume, download the checkpoints/LoRAs/VAEs you use most (the exact same
|
|
271
|
+
files the [installer packs](../../packs) already fetch — `packs/*/install-runpod.sh`
|
|
272
|
+
lists the HF URLs per pack) into that volume's `models/<category>/` tree
|
|
273
|
+
matching the layout in `extra_model_paths.yaml` above, then stop the pod.
|
|
274
|
+
That volume is now your **warm seed** — keep it around, don't delete it.
|
|
275
|
+
2. **Reuse it for new pods**, by whichever mechanism your RunPod plan supports:
|
|
276
|
+
- **Volume snapshot/clone** (if available on your account) — instantly fork
|
|
277
|
+
a new volume from the seed's current contents instead of attaching the
|
|
278
|
+
same volume serially.
|
|
279
|
+
- **Attach the seed volume directly** to a new pod deployment (stop any pod
|
|
280
|
+
currently using it first) — simplest, but one pod at a time.
|
|
281
|
+
- **A shared object store + boot-time sync** — the most portable option, and
|
|
282
|
+
the only one that supports many pods pulling concurrently: keep the seed
|
|
283
|
+
models in an S3-compatible bucket (RunPod's own network storage, or any
|
|
284
|
+
S3-compatible provider) and add an `rclone sync` (or `aws s3 sync`) step to
|
|
285
|
+
`post_start.sh` before the model-subfolder `mkdir -p` block, pulling only
|
|
286
|
+
what's missing on that pod's volume. This also composes cleanly with
|
|
287
|
+
`PANEL_AUTO_UPDATE` above — both are "pull what's missing/changed at boot,
|
|
288
|
+
skip what's already there" patterns.
|
|
289
|
+
|
|
290
|
+
None of this requires a new mechanism in the image itself — `extra_model_paths.yaml`
|
|
291
|
+
already treats `/workspace/models` as the single source of truth regardless of
|
|
292
|
+
*how* files got there, so a warm volume (or a boot-time sync into one) is
|
|
293
|
+
transparent to ComfyUI and the agent.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Manager (remote-install gate)
|
|
298
|
+
|
|
299
|
+
* **Manager v2 (pip), gated by `--enable-manager`.** `comfyui_manager==4.2.2`
|
|
300
|
+
exposes `/v2/manager/queue/task` (the API comfyui-mcp talks to). The classic
|
|
301
|
+
`custom_nodes/ComfyUI-Manager` checkout **conflicts** with it and is removed.
|
|
302
|
+
* **Where the config lives.** With `--user-directory /workspace/user`,
|
|
303
|
+
`comfyui_manager` reads its `config.ini` from **under the user dir** — verified
|
|
304
|
+
against the Manager source (`manager_migration.get_manager_path(user_dir)`):
|
|
305
|
+
* new ComfyUI (System User API): `…/user/__manager/config.ini`
|
|
306
|
+
* older ComfyUI: `…/user/default/ComfyUI-Manager/config.ini`
|
|
307
|
+
|
|
308
|
+
Because that's on the **volume**, the gate persists. `/post_start.sh` writes/re-
|
|
309
|
+
asserts **both** locations on every boot (idempotent), so it's correct on either
|
|
310
|
+
Manager build.
|
|
311
|
+
* **Gate values** (`config.ini`):
|
|
312
|
+
|
|
313
|
+
| Key | Value | Why |
|
|
314
|
+
|-----|-------|-----|
|
|
315
|
+
| `network_mode` | `personal_cloud` | required — the `/v2` install gate only allows remote installs in this mode |
|
|
316
|
+
| `security_level` | `normal-` | safe default; set `weak` (env `COMFY_SECURITY_LEVEL=weak`) for no guardrails, trusted pods only |
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## ComfyUI / torch specifics
|
|
321
|
+
|
|
322
|
+
* **cu128 torch, no xformers.** The venv gets a clean `torch torchvision
|
|
323
|
+
torchaudio` from `https://download.pytorch.org/whl/cu128` (sm_120 kernels for
|
|
324
|
+
Blackwell / RTX 5090). xformers is **omitted** — its prebuilt wheels lag the
|
|
325
|
+
cu128 ABI — so ComfyUI launches with `--use-pytorch-cross-attention` (PyTorch
|
|
326
|
+
SDPA).
|
|
327
|
+
* **Caches are ephemeral (in the container), by design.** We do **not** redirect
|
|
328
|
+
HF/pip/torch/npm caches to `/workspace`. Model downloads via Manager go to
|
|
329
|
+
`/workspace/models` and persist — that's the only persistence we need. (First
|
|
330
|
+
use after a restart may re-download small ancillary files into the ephemeral
|
|
331
|
+
cache; the big model weights stay on the volume.)
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Services (replicating the aitrepreneur set)
|
|
336
|
+
|
|
337
|
+
| Service | Port | Source | Notes |
|
|
338
|
+
|---------|------|--------|-------|
|
|
339
|
+
| **nginx** | **3000** (→ ComfyUI 3001) | our `nginx.conf` | websocket-aware; "starting" fallback page |
|
|
340
|
+
| **ComfyUI** | 3001 (internal) | baked image venv | launched from `/opt/ComfyUI`; see [launch flags](#comfyui-launch-command-the-exact-flags) |
|
|
341
|
+
| **sshd** | 22 | base | RunPod `$PUBLIC_KEY` injection |
|
|
342
|
+
| **JupyterLab** | 8888 | base | set `JUPYTER_PASSWORD` |
|
|
343
|
+
| **code-server** | 8081 (→ 8080) | installed at build | best-effort |
|
|
344
|
+
| **app-manager** | 8001 (→ 8000) | COPY from donor | Node app; best-effort (needs `node`) |
|
|
345
|
+
| **runpod-uploader** | — | COPY from donor | file uploader; best-effort |
|
|
346
|
+
| **croc** | — | COPY from donor | on-demand P2P transfer |
|
|
347
|
+
| **cron** | — | apt | best-effort |
|
|
348
|
+
|
|
349
|
+
All ancillary services are launched **best-effort** — if a binary is absent (e.g.
|
|
350
|
+
you dropped the donor COPYs) the entrypoint logs `skip` and carries on, so the
|
|
351
|
+
image still boots ComfyUI fine.
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Topology: where the agent runs
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
YOUR LAPTOP RUNPOD POD (this image)
|
|
359
|
+
┌───────────────────────────┐ ┌───────────────────────────────────┐
|
|
360
|
+
│ npx comfyui-mcp connect … │ HTTP/WS ───▶ │ nginx :3000 ─▶ ComfyUI :3001 │
|
|
361
|
+
│ └─ panel orchestrator │ │ ├─ Manager v2 (--enable-manager) │
|
|
362
|
+
│ (Claude/Codex Agent SDK│ ◀─── events │ └─ Agent Panel (sidebar) │
|
|
363
|
+
│ on YOUR subscription) │ │ + sshd / jupyter / code-server │
|
|
364
|
+
└───────────────────────────┘ └───────────────────────────────────┘
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
The **panel orchestrator** (the autonomous agent loop, on your Claude **or**
|
|
368
|
+
ChatGPT subscription — no API key) runs **on your machine**, not the pod. The pod
|
|
369
|
+
only serves ComfyUI + Manager + the panel UI. That's why **Node.js for the agent,
|
|
370
|
+
the Agent SDK and any LLM client are intentionally absent** — they'd burn pod
|
|
371
|
+
GPU-hours for nothing.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Deploy on RunPod
|
|
376
|
+
|
|
377
|
+
Create a **Pod template** (or fill these on a one-off GPU pod):
|
|
378
|
+
|
|
379
|
+
| Template field | Value |
|
|
380
|
+
|----------------|-------|
|
|
381
|
+
| **Container image** | `<your-registry>/comfyui-mcp-runpod:<tag>` (after build & push) |
|
|
382
|
+
| **Container disk** | ≥ 30 GB (the baked ComfyUI + venv + cu128 torch + any runtime-installed nodes/caches, which are ephemeral) |
|
|
383
|
+
| **Volume disk** | e.g. 100 GB+ (your **models + workflows + I/O** live here; size for your models) |
|
|
384
|
+
| **Volume mount path** | **`/workspace`** |
|
|
385
|
+
| **Expose HTTP ports** | **`3000`** (nginx → ComfyUI). Optionally `8081` (code-server), `8001` (app-manager), `8888` (Jupyter). |
|
|
386
|
+
| **Expose TCP ports** | `22` (SSH) |
|
|
387
|
+
| **GPU** | RTX 5090 / any Blackwell or Ada card (cu128 covers both) |
|
|
388
|
+
| **Host driver** | >= 570 (CUDA 12.8) for the default image; >= 580 (CUDA 13) for the `:cu130` perf variant. The entrypoint preflights this (`MIN_DRIVER`) and holds the pod open with a clear message instead of crash-looping. |
|
|
389
|
+
|
|
390
|
+
**Environment variables** (Pod → Environment):
|
|
391
|
+
|
|
392
|
+
| Env | Default | Purpose |
|
|
393
|
+
|-----|---------|---------|
|
|
394
|
+
| `JUPYTER_PASSWORD` | *(unset)* | set to enable JupyterLab on :8888 (base behavior) |
|
|
395
|
+
| `PUBLIC_KEY` | *(RunPod injects)* | SSH public key (base behavior) |
|
|
396
|
+
| `COMFY_SECURITY_LEVEL` | `weak` | Manager security level — `weak` lets the agent install nodes from git URLs (single-user pod); set `normal-` to restore Manager's guardrails |
|
|
397
|
+
| `COMFY_NETWORK_MODE` | `personal_cloud` | must stay `personal_cloud` for remote installs |
|
|
398
|
+
| `COMFY_AUTOUPDATE_MANAGER` | `1` | fast-forward `comfyui_manager` (pip) at boot: `1` = latest stable release, `nightly` = ComfyUI-Manager git main, `0` = keep the baked pin. The venv is ephemeral, so this is the only Manager fix that survives a restart short of a new image. Best-effort (180s cap), never blocks boot. |
|
|
399
|
+
| `COMFY_EXTRA_ARGS` | *(empty)* | extra ComfyUI flags appended verbatim by the entrypoint |
|
|
400
|
+
| `COMFY_HOME` | `/opt/ComfyUI` | baked ComfyUI path (rarely overridden) |
|
|
401
|
+
| `WORKSPACE` | `/workspace` | network-volume mount (rarely overridden) |
|
|
402
|
+
| `PANEL_AUTO_UPDATE` | `1` | fast-forward the Agent Panel to its latest release on every boot (git fetch + reset --hard, before ComfyUI launches) — reaches pods without a new image build. Automatically a no-op on a `PANEL_REF`-pinned build (detached HEAD). Set `0` to disable. |
|
|
403
|
+
| `HF_TOKEN` (or `HUGGINGFACE_TOKEN`) | *(unset)* | HuggingFace token for gated model downloads (exported to ComfyUI + Manager) |
|
|
404
|
+
| `ARIA2_DISABLE` | `0` | set `1` to skip the aria2 download sidecar (Manager then uses its slow built-in downloader) |
|
|
405
|
+
| `ARIA2_RPC_PORT` | `6800` | loopback port for the aria2 RPC daemon |
|
|
406
|
+
| `ARIA2_RPC_SECRET` | *(random per boot)* | RPC secret for the aria2 daemon (auto-generated; set only if you need a fixed one) |
|
|
407
|
+
| `HF_HUB_ENABLE_HF_TRANSFER` | `1` (set at boot) | Rust parallel downloader for `huggingface_hub` fetches. **Set `0` as the FIRST troubleshooting step if an HF download fails** — hf_transfer trades resume robustness/proxy support for speed |
|
|
408
|
+
| `HF_XET_HIGH_PERFORMANCE` | `1` (set at boot) | high-performance mode for Xet-backed HF repos (newer hub versions) |
|
|
409
|
+
|
|
410
|
+
### Fast model downloads (aria2 sidecar)
|
|
411
|
+
|
|
412
|
+
ComfyUI-Manager's built-in model downloader is single-stream with tiny chunks
|
|
413
|
+
and collapses to **<1–4 MB/s** against the MooseFS network volume — a 13 GB
|
|
414
|
+
model then takes hours, and because Manager's install queue is serial,
|
|
415
|
+
everything behind it looks wedged ("downloads don't work"). Measured on a live
|
|
416
|
+
pod (2026-07-07): Manager at 792 kB/s while `curl` on the same pod pulled the
|
|
417
|
+
same HuggingFace file at 15–80 MB/s and wrote the volume at 60–300 MB/s.
|
|
418
|
+
|
|
419
|
+
The image therefore bakes **aria2** and runs a loopback, secret-gated RPC
|
|
420
|
+
daemon at boot (post_start §4.4), hardened per review:
|
|
421
|
+
|
|
422
|
+
- **Supervised**: aria2c runs under a respawn loop — a crashed daemon would
|
|
423
|
+
otherwise leave Manager hard-failing with *no* fallback (Manager commits to
|
|
424
|
+
the aria2 path at import time).
|
|
425
|
+
- **Readiness-probed**: `COMFYUI_MANAGER_ARIA2_SERVER`/`SECRET` are exported
|
|
426
|
+
only after a real `aria2.getVersion` RPC answers (daemonizing successfully
|
|
427
|
+
says nothing about the listener). On probe failure the sidecar is torn down
|
|
428
|
+
and Manager keeps its built-in downloader.
|
|
429
|
+
- **`/models` → `/workspace/models` symlink**: Manager's aria2 path joins
|
|
430
|
+
*relative* model dirs onto `/models` — without the link an edge case would
|
|
431
|
+
write models onto the ephemeral container fs and lose them on restart.
|
|
432
|
+
- The RPC secret lives in a `0600` conf file (not the process cmdline) and is
|
|
433
|
+
length-checked; the live server+secret are written to
|
|
434
|
+
`/var/lib/comfyui-mcp/aria2-rpc.env` (root-only) so `test_image.sh` and a
|
|
435
|
+
debugging human can make a real RPC call.
|
|
436
|
+
|
|
437
|
+
Note Manager's aria2 path (like its built-in one) does not attach `HF_TOKEN`
|
|
438
|
+
to download requests — gated-model fetches need a token-authenticated URL
|
|
439
|
+
either way.
|
|
440
|
+
|
|
441
|
+
aria2 only covers Manager's install-model route. The **other** fetch path —
|
|
442
|
+
custom nodes (Impact, WAS, …) and ComfyUI internals downloading via
|
|
443
|
+
`huggingface_hub` — is accelerated separately: the image bakes `hf_transfer`
|
|
444
|
+
(HF's Rust parallel downloader) + `hf_xet`, and boot defaults
|
|
445
|
+
`HF_HUB_ENABLE_HF_TRANSFER=1` + `HF_XET_HIGH_PERFORMANCE=1` **only after
|
|
446
|
+
verifying `hf_transfer` imports** (with the flag set and the package missing,
|
|
447
|
+
`huggingface_hub` raises at download time — the integrity gate asserts the
|
|
448
|
+
import for the same reason). Both are plain pod env opt-outs (`=0`); flip
|
|
449
|
+
`HF_HUB_ENABLE_HF_TRANSFER=0` first when debugging a failing HF download.
|
|
450
|
+
|
|
451
|
+
> **First boot vs warm restart:** both are fast. First boot additionally creates
|
|
452
|
+
> the volume data dirs and copies the spotcheck model (if baked); warm restart
|
|
453
|
+
> skips even those. Watch the pod log / the "starting" page; ComfyUI init is
|
|
454
|
+
> ~30-60s either way.
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## Build & push
|
|
459
|
+
|
|
460
|
+
No GPU is needed at **build** time. On a machine with Docker + BuildKit:
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
cd docker/runpod
|
|
464
|
+
|
|
465
|
+
# Default: baked software + spotcheck model.
|
|
466
|
+
docker build -t <your-registry>/comfyui-mcp-runpod:cu128 .
|
|
467
|
+
docker push <your-registry>/comfyui-mcp-runpod:cu128
|
|
468
|
+
|
|
469
|
+
# Omit the baked spotcheck model (the 6.9 GB layer is never downloaded):
|
|
470
|
+
docker build --build-arg BAKE_SPOTCHECK_MODEL=0 \
|
|
471
|
+
-t <your-registry>/comfyui-mcp-runpod:cu128-noseed .
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### Test before you push (post-build gate)
|
|
475
|
+
|
|
476
|
+
The build itself ends in an **integrity gate** (Dockerfile §9.5) that fails on
|
|
477
|
+
missing/0-byte panel files, a broken venv, or a `post_start.sh` syntax error.
|
|
478
|
+
Before any registry push, run the deeper suite:
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
# static checks + a real 2-boot volume test + the ENOSPC self-heal test:
|
|
482
|
+
./test_image.sh <image-ref>
|
|
483
|
+
|
|
484
|
+
# static checks only (~seconds):
|
|
485
|
+
./test_image.sh <image-ref> --static
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
For the official Docker Hub image, release **npm-publish style** — one command
|
|
489
|
+
that versions, builds, gates, publishes, verifies, and pins the template:
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
npm run runpod:release # minor bump: 1.6 -> 1.7
|
|
493
|
+
npm run runpod:release:major # major bump: 1.6 -> 2.0
|
|
494
|
+
npm run runpod:release -- 2.3 # explicit tag
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
The script (`scripts/runpod-release.mjs`): resolves the next version from
|
|
498
|
+
Docker Hub → builds the fat image (extras donor = the previous release, so no
|
|
499
|
+
63 GB pull; panel layer cache-busted to the panel repo's main SHA) → runs the
|
|
500
|
+
full `test_image.sh` suite via `deploy-dockerhub.sh` (**a failure aborts before
|
|
501
|
+
anything is pushed**) → pushes `:<version>` + `:latest` → `verify_image_remote.py`
|
|
502
|
+
checks what the registry actually serves → pins the RunPod template to the new
|
|
503
|
+
version tag via the GraphQL API (`RUNPOD_API_KEY`; `SKIP_TEMPLATE=1` to skip).
|
|
504
|
+
|
|
505
|
+
The two lower-level pieces also work standalone:
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
docker build -t artokun/comfyui-mcp-runpod:build .
|
|
509
|
+
./deploy-dockerhub.sh 1.7 # gate + push :1.7 + :latest + remote verify
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
CI does the same for `ghcr.io/...:cu128-lean` (`verify_image_remote.py`
|
|
513
|
+
inspects the pushed manifest + seed layer without pulling the 20 GB image).
|
|
514
|
+
|
|
515
|
+
> **Pin the RunPod template to the VERSION tag** (`:1.6`), not `:latest`.
|
|
516
|
+
> RunPod hosts cache images per-tag — a template on `:latest` can silently
|
|
517
|
+
> serve a stale build from a host's cache; a fresh version tag can't. The
|
|
518
|
+
> release script does this for you. (Don't use `runpodctl template update`
|
|
519
|
+
> for it — it trips a "public templates cannot have Registry Credentials"
|
|
520
|
+
> API error on public templates; the script's GraphQL path doesn't.)
|
|
521
|
+
|
|
522
|
+
Override pins as needed:
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
docker build \
|
|
526
|
+
--build-arg BASE_IMAGE=runpod/pytorch:1.0.7-cu1281-torch280-ubuntu2404 \
|
|
527
|
+
--build-arg COMFYUI_REF=master \
|
|
528
|
+
--build-arg COMFYUI_MANAGER_VERSION=4.2.2 \
|
|
529
|
+
--build-arg PANEL_REF=<tag-or-branch> \
|
|
530
|
+
-t <your-registry>/comfyui-mcp-runpod:cu128 .
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### The 63 GB donor pull (and how to drop it)
|
|
534
|
+
|
|
535
|
+
`STAGE A` (`runpod-donor`) pulls `aitrepreneur/comfyui:2.3.5` (~63 GB) **at build
|
|
536
|
+
time** purely to copy out `runpod-uploader`, `croc` and `/app-manager`. It does
|
|
537
|
+
**not** ship in the final image, but it is a heavy one-time pull on your build
|
|
538
|
+
host — and won't fit on a disk-constrained CI runner. If you don't need those
|
|
539
|
+
extras:
|
|
540
|
+
|
|
541
|
+
```bash
|
|
542
|
+
docker build --build-arg INCLUDE_RUNPOD_EXTRAS=0 \
|
|
543
|
+
-t <your-registry>/comfyui-mcp-runpod:cu128-lean .
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
BuildKit only builds a stage the final target's dependency graph actually
|
|
547
|
+
reaches, so `INCLUDE_RUNPOD_EXTRAS=0` skips the donor pull **entirely** — not
|
|
548
|
+
just its `COPY` (see `runpod-extras-0`/`runpod-extras-1` in the Dockerfile,
|
|
549
|
+
which mirror the `BAKE_SPOTCHECK_MODEL` selector pattern below). The entrypoint
|
|
550
|
+
already treats `runpod-uploader`/`croc`/`app-manager` as best-effort and skips
|
|
551
|
+
them cleanly when absent; `croc` can instead be installed from its official
|
|
552
|
+
release if you want it back without the donor pull.
|
|
553
|
+
|
|
554
|
+
### Image size note (the duplicate-torch tradeoff)
|
|
555
|
+
|
|
556
|
+
Because the software is now baked, the image is **larger** than the volume-seed
|
|
557
|
+
design — that's the deliberate fast-restart tradeoff (first-pull/image-size no
|
|
558
|
+
longer matters per the spec). The lean base `runpod/pytorch:…-cu1281-torch280-…`
|
|
559
|
+
**already ships a cu128 torch**, yet we install cu128 torch again into the
|
|
560
|
+
isolated venv (~7 GB duplicated) for a guaranteed-correct, isolated environment.
|
|
561
|
+
To shave that:
|
|
562
|
+
|
|
563
|
+
* Build the venv with `python -m venv --system-site-packages /opt/ComfyUI/venv`
|
|
564
|
+
and **skip the `pip install torch …` step**, so ComfyUI reuses the base's
|
|
565
|
+
cu128 torch. **Verify first** that the base torch is genuinely `+cu128`
|
|
566
|
+
(`python -c "import torch;print(torch.__version__, torch.version.cuda)"`) —
|
|
567
|
+
some older `cu1281` tags shipped a cu-default torch.
|
|
568
|
+
|
|
569
|
+
> **First build on a new base tag?** Watch for: (a) the base's
|
|
570
|
+
> `/start.sh` actually invokes `/post_start.sh` (it does in `runpod/containers`,
|
|
571
|
+
> but confirm for your exact tag); (b) `main.py --help` lists `--user-directory`,
|
|
572
|
+
> `--input-directory`, `--output-directory`, `--extra-model-paths-config`,
|
|
573
|
+
> `--enable-manager`, `--use-pytorch-cross-attention` for your pinned
|
|
574
|
+
> `COMFYUI_REF`; (c) `comfyui_manager 4.2.2` reads the gate from the volume user
|
|
575
|
+
> dir (`user/__manager/config.ini` or `user/default/ComfyUI-Manager/config.ini`);
|
|
576
|
+
> (d) Manager install-model writes to `/workspace/models/<cat>` (i.e. `is_default`
|
|
577
|
+
> took effect); (e) the donor paths `/usr/local/bin/runpod-uploader`,
|
|
578
|
+
> `/usr/local/bin/croc`, `/app-manager` exist. Then deploy and verify a real
|
|
579
|
+
> stop/start is fast.
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
## The one-command local connect
|
|
584
|
+
|
|
585
|
+
Once the pod is up and you have its proxy URL, on your laptop:
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
npx -y comfyui-mcp@latest connect https://<pod-id>-3000.proxy.runpod.net
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
This starts the comfyui-mcp panel orchestrator pointed at the pod. Because the pod
|
|
592
|
+
page is served over `https://`, `connect` automatically opens a secure, token-gated
|
|
593
|
+
**`wss://` tunnel** (via Cloudflare) to the agent bridge on your machine and hands
|
|
594
|
+
the pod's panel that URL — so the HTTPS page reaches your local agent with **no
|
|
595
|
+
browser prompt, in any browser** (a secure page can't open a plain `ws://` socket
|
|
596
|
+
to your box). Then open the pod's ComfyUI, open the **Agent Panel**, enable the
|
|
597
|
+
**external-orchestrator** toggle, and click **Connect**. (Add **`--insecure-bridge`**
|
|
598
|
+
to force the plain `ws://127.0.0.1:9180` loopback instead — e.g. when you reach the
|
|
599
|
+
pod via an SSH port-forward.)
|
|
600
|
+
|
|
601
|
+
If you're on a build that predates the `connect` subcommand, the equivalents are:
|
|
602
|
+
|
|
603
|
+
```bash
|
|
604
|
+
# remote ComfyUI as an MCP server (for Claude Code / Desktop):
|
|
605
|
+
npx -y comfyui-mcp --comfyui-url https://<pod-id>-3000.proxy.runpod.net
|
|
606
|
+
# panel orchestrator (drives the sidebar agent):
|
|
607
|
+
COMFYUI_URL=https://<pod-id>-3000.proxy.runpod.net npx -y comfyui-mcp --panel-orchestrator
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
If the pod sits behind auth, set `COMFYUI_AUTH_TOKEN` (+ `COMFYUI_AUTH_HEADER` /
|
|
611
|
+
`COMFYUI_AUTH_SCHEME`) on the local command.
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## Owner confirmations needed
|
|
616
|
+
|
|
617
|
+
Draft pins/assumptions — confirm before building/publishing:
|
|
618
|
+
|
|
619
|
+
1. **Base tag** — `runpod/pytorch:1.0.7-cu1281-torch280-ubuntu2404` (verified on
|
|
620
|
+
Docker Hub 2026-06-19). Confirm it's still the one you want at build.
|
|
621
|
+
2. **Base `/start.sh` hook** — confirm your exact base tag's `/start.sh` runs
|
|
622
|
+
`/post_start.sh` and `service nginx start` reads `/etc/nginx/nginx.conf`
|
|
623
|
+
(true in `runpod/containers` `main`).
|
|
624
|
+
3. **Launch flags on the pinned ComfyUI** — `--user-directory`,
|
|
625
|
+
`--input-directory`, `--output-directory`, `--extra-model-paths-config`,
|
|
626
|
+
`--enable-manager`, `--use-pytorch-cross-attention`. Verified present on
|
|
627
|
+
`master`; confirm for whatever `COMFYUI_REF` you bake (`main.py --help`).
|
|
628
|
+
4. **`is_default` write behavior** — confirm Manager install-model actually lands
|
|
629
|
+
in `/workspace/models/<cat>` (it should, since `is_default` front-inserts the
|
|
630
|
+
volume paths).
|
|
631
|
+
5. **`comfyui_manager` 4.2.2 config path** — reads
|
|
632
|
+
`user/__manager/config.ini` (new) or `user/default/ComfyUI-Manager/config.ini`
|
|
633
|
+
(older) under `--user-directory`. We write both; confirm one is honored.
|
|
634
|
+
6. **Donor artifact paths** — `/usr/local/bin/runpod-uploader`,
|
|
635
|
+
`/usr/local/bin/croc`, `/app-manager` in `aitrepreneur/comfyui:2.3.5`.
|
|
636
|
+
7. **nginx port convention** — kept **3000 → 3001** (matches your `connect`
|
|
637
|
+
flow). We override the base's native ComfyUI proxy block with our
|
|
638
|
+
self-contained `nginx.conf`.
|
|
639
|
+
8. **Duplicate torch** — keep the isolated cu128 torch (default, ~+7 GB) or reuse
|
|
640
|
+
the base's via `--system-site-packages` (see size note).
|
|
641
|
+
9. **Panel ref** — cloned from the default branch (nightly HEAD). Pin `PANEL_REF`
|
|
642
|
+
for reproducible images?
|
|
643
|
+
10. **custom_nodes tradeoff** — confirm you accept that runtime-installed nodes
|
|
644
|
+
don't survive a restart (models do). Permanent nodes go in the Dockerfile.
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## Files
|
|
649
|
+
|
|
650
|
+
| File | Purpose |
|
|
651
|
+
|------|---------|
|
|
652
|
+
| `Dockerfile` | Multi-stage: lean `runpod/pytorch` final stage; `aitrepreneur` donor stage for service artifacts; ARG-gated SDXL spotcheck stage. **Bakes** ComfyUI + cu128 venv + Manager v2 + Agent Panel into `/opt/ComfyUI` (run from there; never synced to the volume). |
|
|
653
|
+
| `post_start.sh` | Boot hook (installed as `/post_start.sh`): `mkdir` the `/workspace` data dirs, first-boot spotcheck-model copy, Manager-gate write, ancillary services, and ComfyUI launch from the baked venv with the per-dir flags. |
|
|
654
|
+
| `extra_model_paths.yaml` | Maps every model category to `/workspace/models/<cat>` with `is_default: true` (volume is the primary/download location). No `custom_nodes:` key (nodes stay in the image). |
|
|
655
|
+
| `nginx.conf` | Self-contained reverse proxy (`:3000 → :3001`, websocket-aware, "starting" fallback) + code-server / app-manager fronts. Installed over the base's. |
|
|
656
|
+
| `starting.html` | The auto-refreshing "ComfyUI is starting…" page nginx serves until upstreams are up. |
|
|
657
|
+
| `config.ini` | Manager v2 gate template (`network_mode = personal_cloud`, `security_level = normal-`), copied to the volume user dir at boot. |
|
|
658
|
+
| `README.md` | This document. |
|