DIY Deepfake Creation: A Stealthy, Cost-Effective Guide Using RunPod and ComfyUI
Deepfakes represent a pinnacle of AI-driven image manipulation, allowing precise face swaps in generated visuals with remarkable realism. For creators seeking a professional-grade setup without investing in high-end hardware, cloud-based solutions like RunPod offer an elegant pathway. This tutorial delineates a complete, do-it-yourself process to craft deepfakes from home, leveraging ComfyUI's node-based interface and the ReActor extension for face swapping. At a mere $0.24 per hour on an RTX 2000 Ada GPU, this method ensures affordability and discretion—your computations occur remotely, leaving no trace on local devices. We emphasize ethical application: use this knowledge responsibly, obtaining consent for any featured likenesses and adhering to legal standards.

Step 1: Establishing a RunPod Account
Initiate by securing access to RunPod's infrastructure, a platform renowned for scalable GPU rentals tailored to AI workloads. Visit runpod.io and select the "Sign Up" option in the upper right corner. Provide a valid email address and create a secure password. Verification follows via an email link—click it promptly to activate your account.
Upon login, you'll encounter the dashboard, a centralized hub for managing pods and credits. RunPod requires pre-funding for usage; the minimum deposit is $10, sufficient for approximately 40 hours on our selected GPU or extended storage retention. Navigate to the "Billing" section on the left sidebar, select "Add Credits," and input your payment details. Opt for a credit card or cryptocurrency for seamless transactions. Sources confirm this entry-level funding sustains initial experiments, with pods auto-terminating on inactivity to conserve costs (medium.com/@tchpnk/flux-comfyui-for-non-developers-using-runpod-2025-409d6e050858).
For stealth, enable two-factor authentication immediately under account settings. This adds a layer of security, ensuring only you access the dashboard. No local installations are needed—everything operates in the cloud, minimizing digital footprints.
Step 2: Deploying a Minimal Pod
With credits loaded, proceed to pod creation. From the dashboard, click "Pods" in the navigation menu, then "Deploy." Search for the template "runpod/pytorch:2.8.0-py3.11-cuda12.8.1-cudnn-devel-ubuntu22.04" in the template library—this pre-configured environment includes PyTorch 2.8, CUDA 12.8, and essential development tools, optimized for our deepfake pipeline.
Under GPU selection, choose the RTX 2000 Ada, priced at $0.24/hour. This card delivers 16GB VRAM, ample for Stable Diffusion XL (SDXL) inference and ReActor processing without excess expenditure. Set storage to at least 50GB (20GB minimum pod disk plus optional network volume). For persistence across sessions—crucial for retaining models and workflows—attach a 100GB Network Volume at $0.20/GB/month, mountable at /workspace. This ensures downloaded assets endure pod terminations, as noted in community guides (reddit.com/r/StableDiffusion/comments/1kaqkoz/persistent_comfyui_with_flux_on_runpod_a_tutorial).
Configure ports: Expose 8888 (JupyterLab) and 3000 (ComfyUI). Select a datacenter with low latency, such as US-East for North American users. Click "Deploy" to launch. Monitor status in the Pods list; startup takes 2-5 minutes. Important: Enable auto-termination after 10 minutes of inactivity via pod settings to avoid idle charges.
Once running, note the Pod ID (e.g., abc123def)—it forms the base for connection URLs.
Step 3: Connecting to the Pod via JupyterLab
Access your pod's environment through JupyterLab, RunPod's integrated interface for terminals and file management. In the Pods dashboard, locate your active pod and click "Connect." Under "HTTP Services," select "Connect to HTTP Service [Port 8888]." This redirects to a URL formatted as https://[PodId]-8888.proxy.runpod.net/lab, where [PodId] is your unique identifier (e.g., https://abc123def-8888.proxy.runpod.net/lab).
The interface loads in a new tab, presenting a file browser rooted at /workspace. If prompted for a token, retrieve it from the pod logs or RunPod console under Connect options (docs.runpod.io/tutorials/pods/run-your-first). JupyterLab enables seamless navigation: use the sidebar to create notebooks, upload files, or open terminals.
Key Action: Right-click in the file browser and select "New > Terminal" to open a shell. Confirm your location with pwd—it should output /workspace. This terminal is your gateway to installations, ensuring all operations occur in the persistent volume.
Step 4: Installing ComfyUI, ReActor, and Dependencies
In the JupyterLab terminal, navigate to /workspace if not already there: cd /workspace. Execute the following comprehensive one-liner command to clone ComfyUI, set up the virtual environment, install dependencies, integrate the ReActor node, and download essential models. This script, synthesized from verified sources, automates the process for efficiency.
cd /workspace && git clone https://github.com/comfyanonymous/ComfyUI.git && cd ComfyUI && apt update && apt install -y build-essential && python -m venv venv && source venv/bin/activate && pip install --upgrade pip && pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu128 && pip install -r requirements.txt && cd custom_nodes && git clone https://github.com/Gourieff/comfyui-reactor-node.git && cd comfyui-reactor-node && pip install insightface==0.7.3 && python install.py && mkdir -p ../../models/insightface/models/antelopev2 && wget -O ../../models/insightface/models/antelopev2/inswapper_128.onnx https://huggingface.co/ezioruan/inswapper_128.onnx/resolve/main/inswapper_128.onnx && cd ../../models/facerestore_models && wget -O codeformer-v0.1.0.pth https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/codeformer.pth && cd ../checkpoints && wget -O sd_xl_base_1.0.safetensors https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors && cd ../vae && wget -O sdxl_vae.safetensors https://huggingface.co/stabilityai/sdxl-vae/resolve/main/sdxl_vae.safetensors && cd /workspace/ComfyUI
Highlighted Steps Breakdown:
- Cloning ComfyUI:
git clone https://github.com/comfyanonymous/ComfyUI.gitfetches the latest repository, establishing the core node-based UI (github.com/comfyanonymous/ComfyUI). - System Preparation:
apt update && apt install -y build-essentialrefreshes packages and installs compilers for Insightface. - Virtual Environment:
python -m venv venv && source venv/bin/activateisolates dependencies, preventing conflicts with the pod's base Python. - Core Installations: Upgrades pip, then installs PyTorch with CUDA 12.8 support, followed by ComfyUI's requirements (e.g., transformers, diffusers).
- ReActor Integration: Clones the node from github.com/Gourieff/comfyui-reactor-node, installs Insightface for face detection, and runs the setup script.
- Model Downloads: Creates directories and fetches inswapper_128.onnx (face swapper, ~246MB), codeformer-v0.1.0.pth (restoration, ~540MB), SDXL base (~6.9GB), and VAE (~335MB). These total ~8GB; ensure sufficient storage.
Execution takes 10-20 minutes, dominated by downloads. Monitor progress with ls in subdirectories to verify files. If interrupted, re-run from the failed point—wget supports resumption.
Step 5: Uncensoring the ReActor Node for Unrestricted Use
ReActor includes a built-in NSFW detector to deter misuse, but for comprehensive deepfake capabilities, modify it judiciously. In JupyterLab's file browser, navigate to /workspace/ComfyUI/custom_nodes/comfyui-reactor-node/scripts/reactor_sfw.py. Right-click the file and select "Open with Editor" (or use VS Code integration via RunPod Connect).
Locate the function def nsfw_image(...) near the top. Insert return False as the first line inside the function body, overriding the detection:
def nsfw_image(...):
return False # Bypass NSFW check
# Original code follows...
Save the file (Ctrl+S). This alteration, drawn from community expertise, ensures the node processes all content without interruption (reddit.com/r/comfyui/comments/1i43l3v/guidehow_to_disable_comfyuireactors_nsfw_filter). Caution: This enables unrestricted operation; employ ethically to avoid generating harmful material.
Step 6: Launching ComfyUI Interface
Return to the RunPod dashboard, select your pod, and click "Connect" > "Connect to HTTP Service [Port 3000]." Access the UI at https://[PodId]-3000.proxy.runpod.net. If ComfyUI isn't running, open a new terminal in JupyterLab and execute:
cd /workspace/ComfyUI && source venv/bin/activate && python main.py --listen 0.0.0.0 --port 3000
The interface appears: a canvas for nodes, menu bar for workflows. If a process binds port 3000, terminate it with fuser -k 3000/tcp in the terminal, then restart (github.com/FurkanGozukara/Stable-Diffusion/blob/main/Tutorials/How-To-Use-ComfyUI-On-Your-PC-On-RunPod-On-Colab-With-SDXL.md).
In the UI, use the menu (three lines icon) to refresh or restart if nodes fail to load. Verify ReActor under "Add Node" > "ReActor"—it should appear post-install.
Step 7: Implementing the Deepfake Workflow
ComfyUI workflows are JSON-defined graphs. Load our minimal ReActor-based pipeline for text-to-image generation followed by face swap. Copy the complete JSON below and paste it via the UI's "Load" button (under menu > Load > From JSON).
{
"id": "minimal-reactor-workflow",
"revision": 0,
"last_node_id": 10,
"last_link_id": 14,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [100, 100],
"size": [270, 98],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{"name": "MODEL", "type": "MODEL", "links": [1]},
{"name": "CLIP", "type": "CLIP", "links": [2, 3]},
{"name": "VAE", "type": "VAE", "links": [4]}
],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "CheckpointLoaderSimple"},
"widgets_values": ["sd_xl_base_1.0.safetensors"]
},
{
"id": 2,
"type": "CLIPTextEncode",
"pos": [400, 100],
"size": [400, 200],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [{"name": "clip", "type": "CLIP", "link": 2}],
"outputs": [{"name": "CONDITIONING", "type": "CONDITIONING", "links": [5]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "CLIPTextEncode"},
"widgets_values": ["a beautiful landscape, mountains, river, sunset"]
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [400, 350],
"size": [400, 200],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [{"name": "clip", "type": "CLIP", "link": 3}],
"outputs": [{"name": "CONDITIONING", "type": "CONDITIONING", "links": [6]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "CLIPTextEncode"},
"widgets_values": ["blurry, low quality, artifacts"]
},
{
"id": 4,
"type": "EmptyLatentImage",
"pos": [100, 250],
"size": [270, 106],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [{"name": "LATENT", "type": "LATENT", "links": [7]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "EmptyLatentImage"},
"widgets_values": [1024, 1024, 1]
},
{
"id": 5,
"type": "KSampler",
"pos": [850, 100],
"size": [270, 262],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{"name": "model", "type": "MODEL", "link": 1},
{"name": "positive", "type": "CONDITIONING", "link": 5},
{"name": "negative", "type": "CONDITIONING", "link": 6},
{"name": "latent_image", "type": "LATENT", "link": 7}
],
"outputs": [{"name": "LATENT", "type": "LATENT", "links": [8]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "KSampler"},
"widgets_values": [156680208522230, "randomize", 20, 1, "euler", "normal", 1]
},
{
"id": 6,
"type": "VAEDecode",
"pos": [1150, 100],
"size": [147, 46],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{"name": "samples", "type": "LATENT", "link": 8},
{"name": "vae", "type": "VAE", "link": 4}
],
"outputs": [{"name": "IMAGE", "type": "IMAGE", "links": [9]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "VAEDecode"},
"widgets_values": []
},
{
"id": 7,
"type": "LoadImage",
"pos": [100, 400],
"size": [340, 314],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [],
"outputs": [
{"name": "IMAGE", "type": "IMAGE", "links": [10]},
{"name": "MASK", "type": "MASK", "links": null}
],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "LoadImage"},
"widgets_values": ["source_face_image.png", "image"]
},
{
"id": 8,
"type": "ReActorFaceSwap",
"pos": [1350, 100],
"size": [285, 358],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{"name": "input_image", "type": "IMAGE", "link": 9},
{"name": "source_image", "type": "IMAGE", "link": 10},
{"name": "face_model", "type": "FACE_MODEL", "link": null},
{"name": "face_boost", "type": "FACE_BOOST", "link": null}
],
"outputs": [
{"name": "SWAPPED_IMAGE", "type": "IMAGE", "links": [11]},
{"name": "FACE_MODEL", "type": "FACE_MODEL", "links": null},
{"name": "ORIGINAL_IMAGE", "type": "IMAGE", "links": null}
],
"properties": {"cnr_id": "comfyui-reactor", "ver": "48a3ad27f99f775dcf63e61276e0110d256597ef", "Node name for S&R": "ReActorFaceSwap"},
"widgets_values": [true, "inswapper_128.onnx", "retinaface_resnet50", "codeformer-v0.1.0.pth", 1, 1, "no", "no", "0", "0", 1]
},
{
"id": 9,
"type": "SaveImage",
"pos": [1650, 100],
"size": [308, 270],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [{"name": "images", "type": "IMAGE", "link": 11}],
"outputs": [],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "SaveImage"},
"widgets_values": ["ComfyUI"]
}
],
"links": [
[1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"],
[3, 1, 1, 3, 0, "CLIP"],
[4, 1, 2, 6, 1, "VAE"],
[5, 2, 0, 5, 1, "CONDITIONING"],
[6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "LATENT"],
[8, 5, 0, 6, 0, "LATENT"],
[9, 6, 0, 8, 0, "IMAGE"],
[10, 7, 0, 8, 1, "IMAGE"],
[11, 8, 0, 9, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": {},
"version": 0.4
}
This workflow generates a base image from text (using SDXL), then swaps in a source face via ReActor. Nodes connect sequentially: model loading to sampling, decoding to swapping, culminating in output.
Step 8: Selecting Input Image and Crafting Prompts
Upload your source face image to /workspace/ComfyUI/input/ via JupyterLab's file browser (drag-and-drop or "Upload"). Rename it source_face_image.png to match the workflow's LoadImage node (ID 7). For optimal results, use a clear, front-facing portrait at 512x512 resolution—avoid obstructions for precise detection.
Edit prompts in the CLIPTextEncode nodes (IDs 2 and 3). Double-click the positive prompt widget: Replace "a beautiful landscape, mountains, river, sunset" with your desired scene, e.g., "elegant portrait of a person in a luxurious setting, soft lighting, high detail." For the negative prompt (ID 3), retain or refine to "blurry, deformed, low resolution, artifacts" to enhance quality. These condition the SDXL generation, ensuring the base image aligns with your vision before swapping (huggingface.co/stabilityai/stable-diffusion-xl-base-1.0).
Pro Tip: For stealthier outputs, incorporate descriptors that blend seamlessly, reducing detectability in final renders.
Step 9: Executing the Workflow
With the workflow loaded and inputs set, click "Queue Prompt" in the UI's right sidebar. Execution queues: SDXL samples the latent (20 steps, Euler method), decodes to an image (~10-20 seconds), ReActor swaps the face (~2-5 seconds), and saves to /workspace/ComfyUI/output/. Download the result via JupyterLab.
Monitor the progress bar; outputs appear in the viewport. For batches, adjust EmptyLatentImage (ID 4) batch size to >1. If errors arise (e.g., missing models), verify paths and restart ComfyUI.
Troubleshooting Common Issues
- Pod Connection Fails: Verify Pod ID in URL; restart pod if idle. Check RunPod status for outages (docs.runpod.io/get-started/connect-to-runpod).
- Installation Errors: If pip fails, add
--trusted-host pypi.org. For Insightface compilation, ensure build-essential installed; fallback to CPU mode temporarily. - ReActor Not Detected: Restart ComfyUI after install; check logs for import errors. Re-clone if needed.
- NSFW Block Persists: Confirm edit in reactor_sfw.py; reload node via menu.
- High VRAM Usage: Reduce resolution in EmptyLatentImage to 512x512; terminate pod post-use.
- Slow Downloads: Use a stable connection; wget resumes automatically. For large models, monitor storage—add volume if exceeded.
- Workflow Load Fails: Validate JSON syntax; ensure nodes like ReActor are installed.
Detailed logs in terminal aid diagnosis: Tail with tail -f server.log during runs.
Frequently Asked Questions
Q: Can I extend this to video deepfakes?
A: Yes—integrate AnimateDiff nodes for frame-by-frame processing. Clone via ComfyUI Manager post-setup, then adapt the workflow for video inputs (toolify.ai/ai-news/video-face-swap-mastering-comfyui-reactor-workflow-for-deepfakes-3316322).
Q: How much does a full session cost?
A: At $0.24/hour, generating 10 deepfakes (5-10 minutes each) totals under $0.50, plus $7/month for 100GB storage.
Q: Is this detectable as a deepfake?
A: ReActor with CodeFormer yields high fidelity, but forensic tools exist. For stealth, post-process with upscalers and avoid over-reliance on swaps.
Q: Legal considerations?
A: Deepfakes are regulated variably—e.g., consent required in many jurisdictions. Consult local laws; this guide assumes ethical, non-commercial use.
Q: Alternatives to RunPod?
A: Google Colab for free tiers, but lacks persistence and GPU reliability. RunPod excels in control and cost (runpod.io/articles/guides/comfy-ui-flux).
Ethical Reflections and Best Practices
While this setup empowers creative expression, deepfakes demand restraint. Prioritize consent, watermark outputs if shared, and avoid misinformation. Communities like Reddit's r/StableDiffusion advocate responsible innovation (reddit.com/r/StableDiffusion). For adult-oriented applications—aligning with our blog's focus—ensure all elements are fictional or consensual to uphold elegance in digital artistry.
In conclusion, this protocol transforms abstract AI concepts into tangible deepfakes with precision and economy. Experiment iteratively, refining prompts for sophistication. Terminate your pod after sessions to maintain stealth and budget. For advanced workflows, explore ComfyUI's extensions at comfyanonymous.github.io/ComfyUI.