| #!/bin/bash |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| set -uo pipefail |
|
|
| |
| |
| |
|
|
| WORKSPACE="${WORKSPACE:-/workspace}" |
| COMFYUI_DIR="${COMFYUI_DIR:-${WORKSPACE}/ComfyUI}" |
| LORA_DIR="${COMFYUI_DIR}/models/loras" |
| VAE_DIR="${COMFYUI_DIR}/models/vae" |
| CKPT_DIR="${COMFYUI_DIR}/models/checkpoints" |
| CLIP_DIR="${COMFYUI_DIR}/models/clip" |
| TEXT_ENC_DIR="${COMFYUI_DIR}/models/text_encoders" |
| DIFFUSION_DIR="${COMFYUI_DIR}/models/diffusion_models" |
| UPSCALE_DIR="${COMFYUI_DIR}/models/upscale_models" |
| ULTRALYTICS_DIR="${COMFYUI_DIR}/models/ultralytics/bbox" |
| NODES_DIR="${COMFYUI_DIR}/custom_nodes" |
|
|
| |
| if [ -f /venv/main/bin/activate ]; then |
| source /venv/main/bin/activate |
| fi |
|
|
| |
| |
| |
|
|
| |
| |
| HF_PRIVATE_LORAS=( |
| "Z-Isla_3K_0002_000003500.safetensors|https://huggingface.co/cozyga/test/resolve/main/Z-Isla_3K_0002_000003500.safetensors" |
| "z-kyla-v1.safetensors|https://huggingface.co/cozyga/test/resolve/main/z-kyla-v1.safetensors" |
| "m1a_zit_3.safetensors|https://huggingface.co/cozyga/test/resolve/main/m1a_zit_3.safetensors" |
| "c3lia_v1_000003600.safetensors|https://huggingface.co/cozyga/test/resolve/main/c3lia_v1_000003600.safetensors" |
| "c3lia_v1_000003900.safetensors|https://huggingface.co/cozyga/test/resolve/main/c3lia_v1_000003900.safetensors" |
| "qwen_c3lia_000003600.safetensors|https://huggingface.co/cozyga/test/resolve/main/qwen_c3lia_000003600.safetensors" |
| "s0fia_v2_000004800.safetensors|https://huggingface.co/cozyga/test/resolve/main/s0fia_v2_000004800.safetensors" |
| "s0fia_v2_000003700.safetensors|https://huggingface.co/cozyga/test/resolve/main/s0fia_v2_000003700.safetensors" |
| "s0fia_v2_000004300.safetensors|https://huggingface.co/cozyga/test/resolve/main/s0fia_v2_000004300.safetensors" |
| ) |
|
|
| |
| HF_PUBLIC_LORAS=( |
| "l0ki_zit_v1_000003000.safetensors|https://huggingface.co/XLB666/qwenzitloras/resolve/main/l0ki_zit_v1_000003000.safetensors" |
| "l0ki_qwen_v1_000002800.safetensors|https://huggingface.co/XLB666/qwenzitloras/resolve/main/l0ki_qwen_v1_000002800.safetensors" |
| "dmd2_sdxl_4step_lora_fp16.safetensors|https://huggingface.co/tianweiy/DMD2/resolve/main/dmd2_sdxl_4step_lora_fp16.safetensors" |
| ) |
|
|
| |
| |
| |
| CIVITAI_LORAS=( |
| "zittitslider.safetensors|https://civitai.com/api/download/models/2478366" |
| "QwenEditVersatilePoses.safetensors|https://civitai.com/api/download/models/2457989?type=Model&format=SafeTensor" |
| "sdxlcloseuppussy.safetensors|https://civitai.com/api/download/models/2376235?type=Model&format=SafeTensor" |
| "amateurphotography.safetensors|https://civitai.com/api/download/models/2363467" |
| "nextscene.safetensors|https://civitai.com/api/download/models/2337214?type=Model&format=SafeTensor" |
| ) |
|
|
| |
| CIVITAI_VAE=( |
| "zImage_vae.safetensors|https://civitai.com/api/download/models/2442479" |
| ) |
|
|
| |
| CIVITAI_CHECKPOINTS=( |
| "checkpoint.safetensors|https://civitai.com/api/download/models/798204?type=Model&format=SafeTensor&size=full&fp=fp16" |
| "LustifyENDGAME.safetensors|https://civitai.com/api/download/models/1094291?type=Model&format=SafeTensor&size=pruned&fp=fp16" |
| "analogMadnessXL.safetensors|https://civitai.com/api/download/models/2207703?type=Model&format=SafeTensor&size=full&fp=fp16" |
| ) |
|
|
| |
|
|
| HF_PUBLIC_TEXT_ENCODERS=( |
| "t5xxl_fp8_e4m3fn_scaled.safetensors|https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/t5xxl_fp8_e4m3fn_scaled.safetensors" |
| "qwen_2.5_vl_7b_fp8_scaled.safetensors|https://huggingface.co/Comfy-Org/Qwen-Image_ComfyUI/resolve/main/split_files/text_encoders/qwen_2.5_vl_7b_fp8_scaled.safetensors" |
| ) |
|
|
| HF_PUBLIC_CLIP=( |
| "qwen_3_4b.safetensors|https://huggingface.co/Comfy-Org/z_image_turbo/resolve/main/split_files/text_encoders/qwen_3_4b.safetensors" |
| ) |
|
|
| HF_PUBLIC_DIFFUSION_MODELS=( |
| "z_image_turbo_bf16.safetensors|https://huggingface.co/Comfy-Org/z_image_turbo/resolve/main/split_files/diffusion_models/z_image_turbo_bf16.safetensors" |
| ) |
|
|
| HF_PUBLIC_VAE=( |
| "qwen_image_vae.safetensors|https://huggingface.co/Comfy-Org/Qwen-Image_ComfyUI/resolve/main/split_files/vae/qwen_image_vae.safetensors" |
| "flux_vae.safetensors|https://huggingface.co/StableDiffusionVN/Flux/resolve/main/Vae/flux_vae.safetensors" |
| ) |
|
|
| HF_PUBLIC_CHECKPOINTS=( |
| "Qwen-Rapid-AIO-SFW-v23.safetensors|https://huggingface.co/Phr00t/Qwen-Image-Edit-Rapid-AIO/resolve/main/v23/Qwen-Rapid-AIO-SFW-v23.safetensors" |
| "Qwen-Rapid-AIO-NSFW-v23.safetensors|https://huggingface.co/Phr00t/Qwen-Image-Edit-Rapid-AIO/resolve/main/v23/Qwen-Rapid-AIO-NSFW-v23.safetensors" |
| ) |
|
|
| HF_PUBLIC_ULTRALYTICS=( |
| "FacesV1.pt|https://huggingface.co/ashllay/YOLO_Models/resolve/e07b01219ff1807e1885015f439d788b038f49bd/bbox/FacesV1.pt" |
| ) |
|
|
| |
|
|
| HF_PRIVATE_CHECKPOINTS=( |
| "lustifySDXLNSFW_endgame.safetensors|https://huggingface.co/cozyga/test/resolve/main/lustifySDXLNSFW_endgame.safetensors" |
| ) |
|
|
| HF_PRIVATE_UPSCALE=( |
| "1x-ITF-SkinDiffDetail-Lite-v1.pth|https://huggingface.co/cozyga/test/resolve/main/1x-ITF-SkinDiffDetail-Lite-v1.pth" |
| ) |
|
|
| HF_PRIVATE_ULTRALYTICS=( |
| "nipple.pt|https://huggingface.co/cozyga/test/resolve/main/nipple.pt" |
| "pussyV2.pt|https://huggingface.co/cozyga/test/resolve/main/pussyV2.pt" |
| ) |
|
|
| |
| NODES=( |
| "https://github.com/ltdrdata/ComfyUI-Manager" |
| "https://github.com/ltdrdata/ComfyUI-Impact-Pack" |
| "https://github.com/ltdrdata/ComfyUI-Impact-Subpack" |
| "https://github.com/cubiq/ComfyUI_essentials" |
| "https://github.com/yolain/ComfyUI-Easy-Use" |
| "https://github.com/rgthree/rgthree-comfy" |
| "https://github.com/chflame163/ComfyUI_LayerStyle" |
| "https://github.com/numz/ComfyUI-SeedVR2_VideoUpscaler" |
| "https://github.com/EllangoK/ComfyUI-post-processing-nodes" |
| "https://github.com/wallish77/wlsh_nodes" |
| "https://github.com/chrisgoringe/cg-image-filter" |
| "https://github.com/Azornes/Comfyui-Resolution-Master" |
| "https://github.com/ltdrdata/was-node-suite-comfyui" |
| "https://github.com/DanrisiUA/ComfyUI-ZImage-LoRA-Merger" |
| |
| ) |
|
|
| |
| PIP_PACKAGES=( |
| |
| ) |
|
|
| |
| |
| |
|
|
| print_header() { |
| echo "" |
| echo "==============================================" |
| echo " ComfyUI Provisioning — Vast.ai" |
| echo "==============================================" |
| echo " Workspace: ${WORKSPACE}" |
| echo " ComfyUI: ${COMFYUI_DIR}" |
| echo " HF_TOKEN: ${HF_TOKEN:+set}${HF_TOKEN:-MISSING}" |
| echo " CIVITAI: ${CIVITAI_TOKEN:+set}${CIVITAI_TOKEN:-MISSING}" |
| echo "==============================================" |
| echo "" |
| } |
|
|
| |
| install_aria2() { |
| if command -v aria2c &>/dev/null; then |
| return 0 |
| fi |
| echo "Installing aria2c for fast parallel downloads..." |
| if [ "$(id -u)" -eq 0 ]; then |
| apt-get update -qq && apt-get install -y -qq aria2 |
| elif command -v sudo &>/dev/null; then |
| sudo apt-get update -qq && sudo apt-get install -y -qq aria2 |
| else |
| echo "ERROR: aria2 not found and cannot install (not root, no sudo)." |
| echo "Falling back to wget." |
| return 1 |
| fi |
| } |
|
|
| |
| validate_hf_token() { |
| if [ -z "${HF_TOKEN:-}" ]; then |
| echo "WARNING: HF_TOKEN is not set. Private HuggingFace downloads will fail." |
| return 1 |
| fi |
| local status |
| status=$(curl -s -o /dev/null -w "%{http_code}" \ |
| -H "Authorization: Bearer ${HF_TOKEN}" \ |
| "https://huggingface.co/api/whoami-v2") |
| if [ "$status" -eq 200 ]; then |
| echo "HF_TOKEN: validated" |
| return 0 |
| else |
| echo "WARNING: HF_TOKEN validation failed (HTTP ${status}). Private downloads may fail." |
| return 1 |
| fi |
| } |
|
|
| |
| validate_civitai_token() { |
| if [ -z "${CIVITAI_TOKEN:-}" ]; then |
| echo "WARNING: CIVITAI_TOKEN is not set. CivitAI downloads will fail." |
| return 1 |
| fi |
| local status |
| status=$(curl -s -o /dev/null -w "%{http_code}" \ |
| -H "Authorization: Bearer ${CIVITAI_TOKEN}" \ |
| "https://civitai.com/api/v1/models?hidden=1&limit=1") |
| if [ "$status" -eq 200 ]; then |
| echo "CIVITAI_TOKEN: validated" |
| return 0 |
| else |
| echo "WARNING: CIVITAI_TOKEN validation failed (HTTP ${status}). CivitAI downloads may fail." |
| return 1 |
| fi |
| } |
|
|
| |
| |
| |
| |
| |
| download_if_missing() { |
| local dir="$1" |
| local filename="$2" |
| local url="$3" |
| local auth_header="${4:-}" |
|
|
| mkdir -p "$dir" |
|
|
| if [ -f "${dir}/${filename}" ]; then |
| echo " [skip] ${filename}" |
| return 0 |
| fi |
|
|
| echo " [downloading] ${filename}..." |
|
|
| |
| |
| if [[ "$url" =~ civitai\.com ]]; then |
| if [ -n "$auth_header" ]; then |
| curl -L - |
| -o "${dir}/${filename}" "$url" |
| else |
| curl -L - |
| fi |
| elif command -v aria2c &>/dev/null; then |
| if [ -n "$auth_header" ]; then |
| aria2c -x 16 -s 16 -k 1M -c \ |
| --header="Authorization: Bearer ${auth_header}" \ |
| -d "$dir" -o "$filename" "$url" 2>&1 | tail -1 |
| else |
| aria2c -x 16 -s 16 -k 1M -c \ |
| -d "$dir" -o "$filename" "$url" 2>&1 | tail -1 |
| fi |
| else |
| |
| if [ -n "$auth_header" ]; then |
| wget -q --show-progress \ |
| --header="Authorization: Bearer ${auth_header}" \ |
| -O "${dir}/${filename}" "$url" |
| else |
| wget -q --show-progress -O "${dir}/${filename}" "$url" |
| fi |
| fi |
|
|
| |
| if [ ! -s "${dir}/${filename}" ]; then |
| echo " [FAILED] ${filename} — downloaded file is empty, removing" |
| rm -f "${dir}/${filename}" |
| return 1 |
| fi |
| } |
|
|
| |
| |
| download_batch() { |
| local dir="$1" |
| local auth_token="$2" |
| shift 2 |
|
|
| local failed=0 |
| for entry in "$@"; do |
| local filename="${entry%%|*}" |
| local url="${entry#*|}" |
| download_if_missing "$dir" "$filename" "$url" "$auth_token" || ((failed++)) || true |
| done |
|
|
| if [ "$failed" -gt 0 ]; then |
| echo " WARNING: ${failed} download(s) failed in ${dir}" |
| fi |
| } |
|
|
| |
| install_nodes() { |
| if [ ${#NODES[@]} -eq 0 ]; then |
| return 0 |
| fi |
|
|
| echo "=== Installing Custom Nodes ===" |
| mkdir -p "$NODES_DIR" |
|
|
| for repo in "${NODES[@]}"; do |
| local dirname="${repo##*/}" |
| local path="${NODES_DIR}/${dirname}" |
| local requirements="${path}/requirements.txt" |
|
|
| if [ -d "$path" ]; then |
| echo " [update] ${dirname}" |
| (cd "$path" && git pull -q) || echo " [WARN] git pull failed for ${dirname}, skipping" |
| else |
| echo " [clone] ${dirname}" |
| git clone --recursive -q "$repo" "$path" || { |
| echo " [WARN] git clone failed for ${dirname}, skipping" |
| continue |
| } |
| fi |
|
|
| if [ -f "$requirements" ]; then |
| pip install --no-cache-dir -q -r "$requirements" || echo " [WARN] pip install failed for ${dirname}" |
| fi |
| done |
| echo "" |
| } |
|
|
| |
| install_pip_packages() { |
| if [ ${#PIP_PACKAGES[@]} -eq 0 ]; then |
| return 0 |
| fi |
| echo "=== Installing pip packages ===" |
| pip install --no-cache-dir -q "${PIP_PACKAGES[@]}" |
| echo "" |
| } |
|
|
| |
| |
| |
|
|
| print_header |
|
|
| |
| install_aria2 || true |
|
|
| |
| validate_hf_token || true |
| validate_civitai_token || true |
| echo "" |
|
|
| |
| mkdir -p "$LORA_DIR" "$VAE_DIR" "$CKPT_DIR" "$CLIP_DIR" "$TEXT_ENC_DIR" \ |
| "$DIFFUSION_DIR" "$UPSCALE_DIR" "$ULTRALYTICS_DIR" |
|
|
| |
| install_nodes |
|
|
| |
| install_pip_packages |
|
|
| |
| echo "=== HuggingFace Private LoRAs (cozyga/test) ===" |
| download_batch "$LORA_DIR" "${HF_TOKEN:-}" "${HF_PRIVATE_LORAS[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Public LoRAs ===" |
| download_batch "$LORA_DIR" "${HF_TOKEN:-}" "${HF_PUBLIC_LORAS[@]}" |
| echo "" |
|
|
| |
| echo "=== CivitAI LoRAs ===" |
| download_batch "$LORA_DIR" "${CIVITAI_TOKEN:-}" "${CIVITAI_LORAS[@]}" |
| echo "" |
|
|
| |
| echo "=== CivitAI VAE ===" |
| download_batch "$VAE_DIR" "${CIVITAI_TOKEN:-}" "${CIVITAI_VAE[@]}" |
| echo "" |
|
|
| |
| echo "=== CivitAI Checkpoints ===" |
| download_batch "$CKPT_DIR" "${CIVITAI_TOKEN:-}" "${CIVITAI_CHECKPOINTS[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Text Encoders ===" |
| download_batch "$TEXT_ENC_DIR" "${HF_TOKEN:-}" "${HF_PUBLIC_TEXT_ENCODERS[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace CLIP ===" |
| download_batch "$CLIP_DIR" "${HF_TOKEN:-}" "${HF_PUBLIC_CLIP[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Diffusion Models ===" |
| download_batch "$DIFFUSION_DIR" "${HF_TOKEN:-}" "${HF_PUBLIC_DIFFUSION_MODELS[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace VAE ===" |
| download_batch "$VAE_DIR" "${HF_TOKEN:-}" "${HF_PUBLIC_VAE[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Checkpoints (Qwen) ===" |
| download_batch "$CKPT_DIR" "${HF_TOKEN:-}" "${HF_PUBLIC_CHECKPOINTS[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Ultralytics (YOLO) ===" |
| download_batch "$ULTRALYTICS_DIR" "${HF_TOKEN:-}" "${HF_PUBLIC_ULTRALYTICS[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Private Checkpoints (cozyga/test) ===" |
| download_batch "$CKPT_DIR" "${HF_TOKEN:-}" "${HF_PRIVATE_CHECKPOINTS[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Private Upscale Models (cozyga/test) ===" |
| download_batch "$UPSCALE_DIR" "${HF_TOKEN:-}" "${HF_PRIVATE_UPSCALE[@]}" |
| echo "" |
|
|
| |
| echo "=== HuggingFace Private Ultralytics (cozyga/test) ===" |
| download_batch "$ULTRALYTICS_DIR" "${HF_TOKEN:-}" "${HF_PRIVATE_ULTRALYTICS[@]}" |
| echo "" |
|
|
| |
| |
| |
|
|
| echo "==============================================" |
| echo " Provisioning complete" |
| echo "==============================================" |
| echo "" |
| for label_dir in \ |
| "LoRAs|${LORA_DIR}" \ |
| "Checkpoints|${CKPT_DIR}" \ |
| "VAE|${VAE_DIR}" \ |
| "CLIP|${CLIP_DIR}" \ |
| "Text Encoders|${TEXT_ENC_DIR}" \ |
| "Diffusion Models|${DIFFUSION_DIR}" \ |
| "Upscale Models|${UPSCALE_DIR}" \ |
| "Ultralytics|${ULTRALYTICS_DIR}"; do |
| label="${label_dir%%|*}" |
| dir="${label_dir#*|}" |
| count=$(find "$dir" -maxdepth 1 -type f 2>/dev/null | wc -l | tr -d ' ') |
| echo " ${label}: ${count} files" |
| done |
| echo "" |
| echo "Application will start now." |
|
|