ComfyUI on a VPS: Self-Hosted Stable Diffusion Image Generation with Node-Based Workflow
ComfyUI is the most powerful and flexible open-source Stable Diffusion interface — it uses a node-based visual workflow editor where each step of the image generation pipeline (model loading, conditioning, sampling, upscaling, face restoration) is a separate node that you connect visually. Unlike Automatic1111 (linear UI), ComfyUI’s workflow approach enables complex pipelines, reproducible generation workflows, and a JSON-based workflow format that works as an API. Self-hosting eliminates Midjourney ($10–$30/month) and Stable Diffusion API fees ($0.003–$0.02/image).
ComfyUI vs Automatic1111
- ComfyUI: Node-based workflow editor, more flexible for complex pipelines, better performance, workflow JSON exports, built-in API. Learning curve is steeper.
- Automatic1111: Traditional web UI, more user-friendly for beginners, huge extension ecosystem. Not as performant.
- Choose ComfyUI: Reproducible workflows, API integration, complex multi-step pipelines (img2img + upscale + face restore in one workflow).
Server Requirements
- GPU (recommended): NVIDIA GPU with 6+ GB VRAM for SDXL, 4 GB for SD1.5. CUDA 12.1+
- CPU (functional, slow): 16+ GB RAM, expect 1–5 minutes per image vs 3–10 seconds on GPU
- 50+ GB disk for models (SDXL ~6 GB, Flux ~24 GB)
- Python 3.10+
Step 1: Install ComfyUI
<code"># Create environment sudo apt install -y python3.11 python3.11-venv git python3.11 -m venv /opt/comfyui-env source /opt/comfyui-env/bin/activate # Clone ComfyUI git clone https://github.com/comfyanonymous/ComfyUI.git /opt/comfyui cd /opt/comfyui # Install dependencies # For CPU only: pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu pip install -r requirements.txt # For NVIDIA GPU: pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 pip install -r requirements.txt
Step 2: Download Models
<code"># Model storage locations:
# /opt/comfyui/models/checkpoints/ — main SD models
# /opt/comfyui/models/loras/ — LoRA fine-tunes
# /opt/comfyui/models/vae/ — VAE models
# /opt/comfyui/models/upscale_models/ — ESRGAN upscalers
# Download SDXL base model (6.5 GB)
pip install huggingface_hub
huggingface-cli download \
stabilityai/stable-diffusion-xl-base-1.0 \
sd_xl_base_1.0.safetensors \
--local-dir /opt/comfyui/models/checkpoints/
# Download Flux model (more powerful, 23 GB)
# huggingface-cli download black-forest-labs/FLUX.1-schnell \
# --local-dir /opt/comfyui/models/checkpoints/
# Download VAE (improves color accuracy)
wget -O /opt/comfyui/models/vae/sdxl_vae.safetensors \
https://huggingface.co/madebyollin/sdxl-vae-fp16-fix/resolve/main/sdxl_vae.safetensors
Step 3: Start ComfyUI
<code"># CPU mode
cd /opt/comfyui
source /opt/comfyui-env/bin/activate
python main.py \
--listen 127.0.0.1 \
--port 8188 \
--cpu # CPU inference mode
# --gpu-only # GPU mode (remove --cpu)
# --lowvram # For GPU with limited VRAM
Step 4: Systemd Service
<code">sudo nano /etc/systemd/system/comfyui.service
<code">[Unit] Description=ComfyUI Stable Diffusion After=network.target [Service] Type=simple User=ubuntu WorkingDirectory=/opt/comfyui ExecStart=/opt/comfyui-env/bin/python main.py --listen 127.0.0.1 --port 8188 --cpu Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target
<code">sudo systemctl daemon-reload sudo systemctl enable comfyui sudo systemctl start comfyui
Step 5: Nginx with Authentication
<code">sudo nano /etc/nginx/sites-available/comfyui
<code">server {
listen 443 ssl http2;
server_name diffusion.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/diffusion.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/diffusion.yourdomain.com/privkey.pem;
# Basic auth — protect your GPU resource
auth_basic "ComfyUI";
auth_basic_user_file /etc/nginx/.comfyui_htpasswd;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:8188;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_read_timeout 600s; # Long timeout for image generation
proxy_buffering off;
}
}
<code">sudo htpasswd -c /etc/nginx/.comfyui_htpasswd admin sudo certbot --nginx -d diffusion.yourdomain.com sudo systemctl reload nginx
Step 6: API Usage for Application Integration
<code">import json
import httpx
import uuid
import time
# Export a workflow from ComfyUI UI → Save → download JSON
# Then use it in API calls:
with open('my_workflow.json') as f:
workflow = json.load(f)
# Modify workflow parameters programmatically
workflow['6']['inputs']['text'] = "a majestic mountain at sunset, photorealistic"
workflow['7']['inputs']['text'] = "blurry, low quality, watermark"
workflow['3']['inputs']['seed'] = random.randint(0, 2**32)
# Queue the generation
client_id = str(uuid.uuid4())
response = httpx.post('http://localhost:8188/prompt', json={
'prompt': workflow,
'client_id': client_id,
})
prompt_id = response.json()['prompt_id']
# Poll for completion
while True:
history = httpx.get(f'http://localhost:8188/history/{prompt_id}').json()
if prompt_id in history:
outputs = history[prompt_id]['outputs']
# Get the image filename
for node_id, output in outputs.items():
if 'images' in output:
for img in output['images']:
filename = img['filename']
# Download the generated image
image_data = httpx.get(
f'http://localhost:8188/view?filename={filename}&type=output'
).content
with open(f'output_{filename}', 'wb') as f:
f.write(image_data)
print(f"Generated: {filename}")
break
time.sleep(2)
Step 7: Custom Nodes (Extend ComfyUI)
<code"># Install ComfyUI Manager for easy custom node installation cd /opt/comfyui/custom_nodes git clone https://github.com/ltdrdata/ComfyUI-Manager.git # Popular custom nodes: # ComfyUI-Impact-Pack: face detection, seam fixing, detailers # ComfyUI_IPAdapter_plus: style transfer from reference images # ComfyUI-VideoHelperSuite: video generation workflows # ComfyUI-AnimateDiff: animated image generation pip install -r ComfyUI-Manager/requirements.txt sudo systemctl restart comfyui
Getting Started
For GPU inference, a VPS with NVIDIA A4000 (16 GB VRAM) generates SDXL images in 3–10 seconds. For CPU-only inference on a high-RAM Ubuntu VPS at VPS.DO (16+ GB RAM), expect 1–5 minutes per SDXL image — adequate for batch generation workflows where speed isn’t critical. NVMe storage speeds up model loading significantly — SDXL takes 10 seconds to load from NVMe versus 60+ seconds from HDD.
Conclusion
ComfyUI on a self-hosted VPS provides unlimited AI image generation with reproducible node-based workflows, a JSON API for application integration, and no per-image fees. For developers building image generation into applications (product mockups, avatar generation, marketing assets), ComfyUI’s JSON workflow API is the cleanest interface for programmatic generation. GPU-equipped VPS instances make generation speeds comparable to cloud APIs at a fraction of the per-image cost at scale.