cocount21 commited on
Commit
12fb3fd
·
verified ·
1 Parent(s): 9c1ddf6

Upload provision.sh

Browse files
Files changed (1) hide show
  1. provision.sh +241 -0
provision.sh ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # ---------------------------------------------------------------------------
3
+ # ComfyUI provisioning for RunPod -- Flux.2 Klein FaceSwap + Z-Image LoRA
4
+ #
5
+ # RunPod template -> "Container Start Command":
6
+ # bash -c "curl -sL <RAW_URL_OF_THIS_FILE> -o /provision.sh && bash /provision.sh 2>&1 | tee /workspace/provision.log"
7
+ #
8
+ # Required template env var:
9
+ # HF_TOKEN read-only HuggingFace token (Klein 9b fp8 is a gated repo)
10
+ # Optional:
11
+ # START_JUPYTER=1 also run JupyterLab on :8888 (default 0)
12
+ # SKIP_MODELS=1 set up nodes only, no model downloads
13
+ # COMFY_PORT=8188 ComfyUI port
14
+ # ---------------------------------------------------------------------------
15
+ set -uo pipefail
16
+
17
+ ROOT="${WORKSPACE:-/workspace}"
18
+ COMFY="$ROOT/ComfyUI"
19
+ STAGE="$ROOT/.dl"
20
+ CONS="$ROOT/.torch-constraints.txt"
21
+ PORT="${COMFY_PORT:-8188}"
22
+ M="$COMFY/models"
23
+
24
+ log() { printf '\n\033[1;36m==> %s\033[0m\n' "$*"; }
25
+ ok() { printf ' \033[1;32m%s\033[0m\n' "$*"; }
26
+ warn() { printf ' \033[1;33m[warn] %s\033[0m\n' "$*"; }
27
+ die() { printf '\n\033[1;31m[fail] %s\033[0m\n' "$*"; exit 1; }
28
+
29
+ mkdir -p "$ROOT"
30
+ cd "$ROOT"
31
+ START_TS=$(date +%s)
32
+
33
+ # --------------------------------------------------------------- ssh --------
34
+ if [ -n "${PUBLIC_KEY:-}" ]; then
35
+ mkdir -p ~/.ssh && chmod 700 ~/.ssh
36
+ echo "$PUBLIC_KEY" >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
37
+ ssh-keygen -A >/dev/null 2>&1
38
+ /usr/sbin/sshd >/dev/null 2>&1 && ok "sshd up"
39
+ fi
40
+
41
+ # ------------------------------------------------------------ apt deps ------
42
+ if [ ! -f "$ROOT/.apt-done" ]; then
43
+ log "System packages"
44
+ export DEBIAN_FRONTEND=noninteractive
45
+ apt-get update -qq >/dev/null 2>&1
46
+ apt-get install -y -qq git aria2 libgl1 libglib2.0-0t64 >/dev/null 2>&1 \
47
+ || apt-get install -y -qq git aria2 libgl1 libglib2.0-0 >/dev/null 2>&1 \
48
+ || warn "apt partially failed (opencv-based nodes may complain)"
49
+ touch "$ROOT/.apt-done"
50
+ ok "done"
51
+ fi
52
+
53
+ # ------------------------------------------------- pin torch, get hf cli ----
54
+ log "Python tooling"
55
+ python - > "$CONS" <<'PYEOF'
56
+ import torch
57
+ print("torch==" + torch.__version__)
58
+ for m in ("torchvision", "torchaudio"):
59
+ try:
60
+ print(m + "==" + __import__(m).__version__)
61
+ except Exception:
62
+ pass
63
+ PYEOF
64
+ ok "torch pinned: $(head -1 "$CONS")"
65
+
66
+ pip install -q -U pip >/dev/null 2>&1
67
+ pip install -q -U "huggingface_hub[hf_transfer,cli]" >/dev/null 2>&1
68
+ export HF_HUB_ENABLE_HF_TRANSFER=1
69
+ HF_BIN="$(command -v hf || command -v huggingface-cli || true)"
70
+ [ -n "$HF_BIN" ] || die "huggingface cli not found"
71
+ ok "hf cli: $HF_BIN"
72
+
73
+ # -------------------------------------------------------------- ComfyUI ----
74
+ if [ ! -d "$COMFY/.git" ]; then
75
+ log "Cloning ComfyUI"
76
+ git clone --depth 1 https://github.com/comfyanonymous/ComfyUI "$COMFY" || die "clone failed"
77
+ fi
78
+ log "ComfyUI requirements"
79
+ pip install -q -r "$COMFY/requirements.txt" -c "$CONS" >/dev/null 2>&1 || warn "some reqs failed"
80
+ ok "done"
81
+
82
+ # --------------------------------------------------------- custom nodes ----
83
+ NODES=(
84
+ "https://github.com/ltdrdata/ComfyUI-Manager"
85
+ "https://github.com/ltdrdata/ComfyUI-Impact-Pack"
86
+ "https://github.com/ltdrdata/ComfyUI-Impact-Subpack"
87
+ "https://github.com/yolain/ComfyUI-Easy-Use"
88
+ "https://github.com/rgthree/rgthree-comfy"
89
+ "https://github.com/zhangp365/ComfyUI-utils-nodes"
90
+ )
91
+ log "Custom nodes"
92
+ mkdir -p "$COMFY/custom_nodes"
93
+ for url in "${NODES[@]}"; do
94
+ name="$(basename "$url")"
95
+ dir="$COMFY/custom_nodes/$name"
96
+ if [ ! -d "$dir/.git" ]; then
97
+ if git clone --depth 1 "$url" "$dir" >/dev/null 2>&1; then
98
+ ok "cloned $name"
99
+ else
100
+ warn "clone failed: $name"
101
+ continue
102
+ fi
103
+ else
104
+ ok "present $name"
105
+ fi
106
+ if [ -f "$dir/requirements.txt" ]; then
107
+ pip install -q -r "$dir/requirements.txt" -c "$CONS" >/dev/null 2>&1 || warn "pip failed: $name"
108
+ fi
109
+ if [ -f "$dir/install.py" ]; then
110
+ ( cd "$dir" && python install.py >/dev/null 2>&1 ) || warn "install.py failed: $name"
111
+ fi
112
+ done
113
+
114
+ TORCH_NOW="$(python -c 'import torch; print(torch.__version__)' 2>/dev/null || echo BROKEN)"
115
+ if [ "torch==$TORCH_NOW" = "$(head -1 "$CONS")" ]; then
116
+ ok "torch intact ($TORCH_NOW)"
117
+ else
118
+ warn "TORCH CHANGED -> $TORCH_NOW (expected $(head -1 "$CONS"))"
119
+ fi
120
+
121
+ # --------------------------------------------------------------- models ----
122
+ mkdir -p "$M/diffusion_models" "$M/text_encoders" "$M/vae" "$M/loras" "$M/sams" "$M/ultralytics/bbox"
123
+
124
+ fetch() { # repo path-in-repo dest expected-bytes
125
+ local repo="$1" path="$2" dest="$3" want="$4" have
126
+ mkdir -p "$(dirname "$dest")"
127
+ if [ -f "$dest" ]; then
128
+ have=$(stat -c %s "$dest")
129
+ if [ "$have" = "$want" ]; then
130
+ ok "cached $(basename "$dest")"
131
+ return 0
132
+ fi
133
+ warn "size mismatch ($have != $want) -> refetch $(basename "$dest")"
134
+ rm -f "$dest"
135
+ fi
136
+ printf ' downloading %s ...\n' "$(basename "$dest")"
137
+ rm -rf "$STAGE"
138
+ if ! "$HF_BIN" download "$repo" "$path" --local-dir "$STAGE" >/dev/null 2>&1; then
139
+ warn "DOWNLOAD FAILED $repo :: $path"
140
+ rm -rf "$STAGE"
141
+ return 1
142
+ fi
143
+ mv -f "$STAGE/$path" "$dest"
144
+ rm -rf "$STAGE"
145
+ have=$(stat -c %s "$dest")
146
+ if [ "$have" = "$want" ]; then
147
+ ok "ok $(basename "$dest") ($have B)"
148
+ else
149
+ warn "BAD SIZE $(basename "$dest"): $have != $want"
150
+ return 1
151
+ fi
152
+ }
153
+
154
+ fetch_url() { # url dest expected-bytes
155
+ local url="$1" dest="$2" want="$3" have
156
+ mkdir -p "$(dirname "$dest")"
157
+ if [ -f "$dest" ]; then
158
+ have=$(stat -c %s "$dest")
159
+ if [ "$have" = "$want" ]; then
160
+ ok "cached $(basename "$dest")"
161
+ return 0
162
+ fi
163
+ rm -f "$dest"
164
+ fi
165
+ printf ' downloading %s ...\n' "$(basename "$dest")"
166
+ aria2c -x8 -s8 -q --allow-overwrite=true \
167
+ -d "$(dirname "$dest")" -o "$(basename "$dest")" "$url" >/dev/null 2>&1 \
168
+ || curl -sL "$url" -o "$dest" \
169
+ || { warn "DOWNLOAD FAILED $url"; return 1; }
170
+ have=$(stat -c %s "$dest")
171
+ if [ "$have" = "$want" ]; then
172
+ ok "ok $(basename "$dest") ($have B)"
173
+ else
174
+ warn "BAD SIZE $(basename "$dest"): $have != $want"
175
+ fi
176
+ }
177
+
178
+ if [ "${SKIP_MODELS:-0}" = "1" ]; then
179
+ log "Models: skipped (SKIP_MODELS=1)"
180
+ else
181
+ log "Models (~37.6 GB total)"
182
+
183
+ # -- Flux.2 Klein 9b stage (GATED: needs HF_TOKEN + accepted licence) -----
184
+ if [ -z "${HF_TOKEN:-}" ]; then
185
+ warn "HF_TOKEN is empty - the gated Klein 9b fp8 file will fail."
186
+ warn "Set HF_TOKEN in the template AND accept the licence once at"
187
+ warn "https://huggingface.co/black-forest-labs/FLUX.2-klein-9b-fp8"
188
+ fi
189
+ fetch black-forest-labs/FLUX.2-klein-9b-fp8 \
190
+ flux-2-klein-9b-fp8.safetensors \
191
+ "$M/diffusion_models/Flux-2-Klein-9b-fp8.safetensors" 9433061528
192
+ fetch Comfy-Org/vae-text-encorder-for-flux-klein-9b \
193
+ split_files/text_encoders/qwen_3_8b_fp8mixed.safetensors \
194
+ "$M/text_encoders/qwen_3_8b_fp8mixed.safetensors" 8664848742
195
+ fetch Comfy-Org/vae-text-encorder-for-flux-klein-9b \
196
+ split_files/vae/flux2-vae.safetensors \
197
+ "$M/vae/flux2-vae.safetensors" 336211292
198
+ fetch bond12321/bfs-head-klein9b \
199
+ bfs_head_v1_flux-klein_9b_step3500_rank128.safetensors \
200
+ "$M/loras/bfs_head_v1_flux-klein_9b_step3500_rank128.safetensors" 662729912
201
+
202
+ # -- Z-Image Turbo stage (FaceDetailer) ----------------------------------
203
+ fetch Comfy-Org/z_image_turbo \
204
+ split_files/diffusion_models/z_image_turbo_bf16.safetensors \
205
+ "$M/diffusion_models/z_image_turbo_bf16.safetensors" 12309866400
206
+ fetch Comfy-Org/z_image_turbo \
207
+ split_files/text_encoders/qwen_3_4b.safetensors \
208
+ "$M/text_encoders/qwen_3_4b.safetensors" 8044982048
209
+ fetch Comfy-Org/z_image_turbo \
210
+ split_files/vae/ae.safetensors \
211
+ "$M/vae/ae.safetensors" 335304388
212
+
213
+ # -- your character LoRA -------------------------------------------------
214
+ fetch cocount21/Robert01 \
215
+ Robert01_epoch50.safetensors \
216
+ "$M/loras/Robert01_epoch50.safetensors" 174083128
217
+
218
+ # -- detectors for FaceDetailer ------------------------------------------
219
+ fetch Bingsu/adetailer face_yolov8m.pt \
220
+ "$M/ultralytics/bbox/face_yolov8m.pt" 52026019
221
+ fetch_url https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth \
222
+ "$M/sams/sam_vit_b_01ec64.pth" 375042383
223
+ fi
224
+
225
+ # -------------------------------------------------------------- jupyter ----
226
+ if [ "${START_JUPYTER:-0}" = "1" ] && command -v jupyter >/dev/null 2>&1; then
227
+ JT="${JUPYTER_PASSWORD:-$(python -c 'import secrets; print(secrets.token_hex(16))')}"
228
+ nohup jupyter lab --allow-root --no-browser --ip=0.0.0.0 --port=8888 \
229
+ --ServerApp.token="$JT" --ServerApp.allow_origin='*' \
230
+ --notebook-dir="$ROOT" >"$ROOT/jupyter.log" 2>&1 &
231
+ log "JupyterLab :8888 token = $JT"
232
+ fi
233
+
234
+ # --------------------------------------------------------------- launch ----
235
+ printf '\n\033[1;32m==================================================\033[0m\n'
236
+ printf '\033[1;32m provisioning finished in %s s\033[0m\n' "$(( $(date +%s) - START_TS ))"
237
+ printf '\033[1;32m ComfyUI -> port %s\033[0m\n' "$PORT"
238
+ printf '\033[1;32m==================================================\033[0m\n\n'
239
+
240
+ cd "$COMFY"
241
+ exec python main.py --listen 0.0.0.0 --port "$PORT"