DIY Deepfake Tutorial: Create Face Swaps at Home with RunPod and ComfyUI for Just $0.24/Hour
Hey there, if you're into experimenting with AI from the comfort of your setup without breaking the bank, this guide is for you. We're diving into a straightforward way to make deepfakes using open-source tools like ComfyUI and the ReActor node. Everything runs on a cloud GPU pod, so no need for fancy hardware—just your browser and a bit of patience. We'll keep costs low at $0.24 per hour on the RTX 2000 Ada GPU, and I'll show you how to do it stealthily from home. This is all about ethical tinkering, like for art or personal projects—remember, always get consent and follow laws on face usage.
We'll set up a persistent environment on RunPod, install ComfyUI with ReActor for face swapping, uncensor it for flexibility, and run a simple workflow to generate and swap faces based on text prompts. No prior coding needed, but you'll copy-paste some commands. Let's ease into it calmly.

Step 1: Sign Up for RunPod and Fund Your Account
First things first, head to the RunPod website and create a free account. It's quick—just enter your email, set a password, and verify. Once logged in, you'll land on the dashboard where you can manage pods and storage.
To get started, add some credits. The minimum is $10, which gives you about 35-40 hours on our cheap GPU setup (based on current pricing). Click "Add Credits" in the dashboard, choose your payment method, and fund it. Pro tip: This covers pod runtime and optional persistent storage for saving models across sessions—super handy to avoid re-downloading everything.
From RunPod's docs: "Create an account. The minimum credit is US$10, which would run a pod for 35 hours, and store the results for up to a month." (Source: Medium guide on Flux ComfyUI for non-devs).
Step 2: Deploy Your Minimal Pod
Now, let's spin up a pod. In the dashboard, go to the "Pods" section and click "Deploy." Search for the template: runpod/pytorch:2.8.0-py3.11-cuda12.8.1-cudnn-devel-ubuntu22.04. This one's optimized for PyTorch with CUDA 12.8, perfect for ComfyUI without extras bloating your costs.
Select the GPU: RTX 2000 Ada—it's $0.24/hour, entry-level but handles SDXL and ReActor fine for single images. Set storage to at least 50GB (free for the pod's life, or add a 100GB Network Volume for $7/month to persist files). Choose a datacenter close to you for low latency, like US-East if you're stateside.
Enable auto-termination after 10-30 minutes of inactivity to save credits—toggle that in the pod settings. Hit "Deploy," and wait 2-5 minutes for it to go "Running." Your pod ID will show up in the list.
Key highlight: RTX 2000 Ada at $0.24/hour is the sweet spot for budget deepfakes. As noted in Reddit's StableDiffusion community: "The RTX 2000 Ada is only $0.24/hour, and you can set up auto-termination for inactivity."
If you want persistence, create a Network Volume first under "Storage" (100GB for $7/month), then mount it to /workspace when deploying.
Step 3: Connect to Your Pod via JupyterLab
With the pod running, click on it in the dashboard, then hit "Connect." Under HTTP Services, click Connect to HTTP Service [Port 8888]. This opens JupyterLab in a new tab at a URL like https://[podId]-8888.proxy.runpod.net/lab. It might ask for a token—grab it from the pod logs if needed.
JupyterLab gives you a file browser and terminal. You'll see the /workspace folder— that's where the magic happens. If it's your first time, it loads in seconds.
From RunPod docs: "Go back to the Runpod console and click Connect on your Pod again. Under HTTP Services, click Connect to HTTP Service [Port 8888] to open JupyterLab." (Source: RunPod tutorials on running your first pod).
Step 4: Open a Terminal and Navigate to /workspace
In JupyterLab's file browser, right-click in the /workspace folder (or anywhere) and select New > Terminal. This opens a bash shell. You're now in /workspace by default—confirm with pwd. If not, type cd /workspace.
This is where we'll install everything. Stay calm; the next step is a big one-liner that handles cloning, installing, and downloading models.
From various tutorials: "Once the pod is up, open a Terminal and install the required dependencies." (Source: DEV Community on deploying ComfyUI with RunPod).
Step 5: Run the One-Liner Installation Script
This is the most important step—copy-paste this entire command into the terminal and hit Enter. It clones ComfyUI, sets up the environment, installs dependencies, adds the ReActor node, and downloads key models like SDXL base, VAE, and face restoration tools. It takes 5-15 minutes depending on downloads (total ~10GB).
Here's the command:
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
Watch the output: It updates packages, creates a virtual env, installs PyTorch for CUDA 12.8, ComfyUI requirements, clones ReActor, installs Insightface for face detection, and pulls models. If it errors on apt (permissions), prefix with sudo. For pip issues, retry or add --trusted-host pypi.org.
Sourced from ComfyUI GitHub, ReActor repo, and aggregated tutorials like Gurkan Ucar's complete setup guide: "Just copy and paste this entire code block into your RunPod terminal."
After it finishes, activate the env in future terminals with cd /workspace/ComfyUI && source venv/bin/activate.
Step 6: Uncensor the ReActor Node for Full Flexibility
By default, ReActor has an NSFW filter to block certain content. To bypass it (for ethical, non-harmful use), edit the safety file.
In JupyterLab, navigate to /workspace/ComfyUI/custom_nodes/comfyui-reactor-node/scripts/reactor_sfw.py. Right-click the file > Open With > Editor.
Find the function def nsfw_image(...) near the top. Immediately after the def line, add return False and save. This forces it to always pass without detection.
Example edit:
def nsfw_image(image):
return False # Add this line
# Original code below...
From Reddit's ComfyUI community: "To do it manually you can modify the reactor_sfw.py... by forcing it to always return false." (Source: Guide on disabling ReActor's NSFW filter).
Restart your terminal or pod if needed, but this persists.
Step 7: Launch and Connect to ComfyUI
Back in the terminal (with env activated: source /workspace/ComfyUI/venv/bin/activate), start ComfyUI:
cd /workspace/ComfyUI && python main.py --listen 0.0.0.0 --port 3000
It'll output something like "Starting server... To see the GUI go to: http://0.0.0.0:3000". Now, in the RunPod dashboard, click Connect on your pod > Connect to HTTP Service [Port 3000]. Open https://[podId]-3000.proxy.runpod.net/ in a new tab. You'll see the ComfyUI interface—a clean node graph editor.
If it's already running or port conflicts, kill it first: fuser -k 3000/tcp then restart.
From Furkan Gozukara's tutorial: "fuser -k 3000/tcp cd /workspace/ComfyUI/venv source bin/activate cd /workspace/ComfyUI python main.py --listen 0.0.0.0 --port 3000."
In the UI, if nodes are missing, refresh via the menu (three lines > Restart) or restart the server.
Step 8: Load the Workflow JSON
In ComfyUI, click Load (or drag-drop). Copy-paste this complete JSON workflow—it's a minimal setup: text-to-image with SDXL, then ReActor face swap. Save it as a .json file locally if you want to reuse.
{
"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 an image from a prompt (positive/negative in the CLIP nodes), then swaps in a source face via ReActor. Outputs save to /workspace/ComfyUI/output.
From ReActor GitHub: "Add the ReActorFaceSwap Node to the workflow and connect it as shown." (Source: Gourieff/ComfyUI-ReActor).
Step 9: Choose Your Input Image and Prompt
Upload your source face image to JupyterLab's /workspace/ComfyUI/input folder (drag-drop or use the upload button). Name it something like source_face_image.png—it should be a clear, front-facing photo.
In the workflow:
- Double-click the LoadImage node (ID 7) and select your uploaded file.
- Edit the CLIPTextEncode nodes (IDs 2 and 3): Positive prompt for the scene/body (e.g., "a person standing in a park, casual clothes"), negative for avoids (e.g., "deformed, ugly").
From Hugging Face on SDXL: "This model is a diffusion-based text-to-image generative model that can generate and modify images based on text prompts."
Step 10: Run the Workflow
Hit Queue Prompt in the top right. Watch the progress bar— it samples the image (~20 steps), decodes, swaps the face, and saves. Takes 15-45 seconds on your pod. Download the output from /output in JupyterLab.
If it works, you've got a deepfake! Experiment with prompts for different scenes.
From Toolify AI: "Run the workflow to generate the deepfake output." (Source: Mastering ComfyUI Reactor for deepfakes).
Troubleshooting Common Issues
- Pod Won't Start ComfyUI: Check if port 3000 is free—run
fuser -k 3000/tcp. Ensure env is activated. - Model Download Fails: Wget can timeout; retry the one-liner or use
huggingface-cli downloadif installed (pip install huggingface-hub). - ReActor Errors (e.g., Insightface Import Fail): Re-run
pip install insightface==0.7.3in the node dir. Verify CUDA withnvidia-smi. - NSFW Block Persists: Double-check the edit in reactor_sfw.py—restart ComfyUI after saving.
- Out of VRAM: Lower resolution in EmptyLatentImage to 512x512. SDXL needs ~7GB.
- Slow Downloads: Use a closer datacenter or add
--no-check-certificateto wget if SSL issues. - Persistent Storage Lost Models: Mount a Network Volume next time; copy files manually via Jupyter.
From GitHub issues: Common fixes include reinstalling deps or checking paths. (Source: ComfyUI-ReActor issues).
Frequently Asked Questions
How much does this really cost?
At $0.24/hour, a 30-min session is ~$0.12. With $10 credit, expect 40+ hours. Add $7/month for 100GB storage.
Is this stealthy/private?
RunPod doesn't store your outputs unless you choose persistent volume. Use incognito or VPN for extra privacy. No logs of your images.
Can I do video deepfakes?
Yes, extend with AnimateDiff nodes (git clone in custom_nodes), but it ups VRAM/cost. Start with images.
Ethical concerns?
Deepfakes can mislead—use only for consented, fun stuff. ReActor's original intent is creative, per its GitHub: "use it on your own responsibility."
What if I terminate the pod?
Without Network Volume, everything resets. Save outputs to your local drive via Jupyter download.
For more on ComfyUI setups, check RunPod's official guides at runpod.io/articles/guides/comfy-ui-flux.
Wrapping Up
There you have it—a calm, step-by-step path to DIY deepfakes on a budget. From account setup to running swaps, it's all doable in under an hour. Tweak prompts and images to refine results, and always prioritize ethics. If you're hooked, explore more workflows on the ComfyUI GitHub. Happy creating—keep it responsible.
Back to aip0rn for more AI guides.