> ## Documentation Index
> Fetch the complete documentation index at: https://comfyui-mcp.artokun.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloud deployment (RunPod)

> Deploy, connect, monitor, and stop a cloud GPU pod for ComfyUI without leaving the Agent Panel — one-tap deploy, an honest local⇄pod host switch, live cost/GPU status, and idle auto-stop. Or drive an existing pod with one command.

Don't have a local GPU — or want a bigger one on demand? Deploy ComfyUI to a
**cloud GPU pod** and drive it in natural language from the agent running on
**your** machine, on your own Claude or ChatGPT subscription.

<Note>
  The pod only serves **ComfyUI + Manager + the Agent Panel UI**. The agent's brain
  (the [panel orchestrator](./panel)) runs **locally on your machine** on your own
  subscription — so a cloud pod never burns GPU-hours on the LLM, and no API key or
  agent login ever touches the box. See [Topology](#topology-where-the-agent-runs).
</Note>

## One-click template (fastest path)

The prebuilt image boots **ready to be driven by the Agent Panel** — ComfyUI +
[Agent Panel](https://github.com/artokun/comfyui-mcp-panel) +
ComfyUI-Manager v2 are baked in, no setup:

[![Deploy on RunPod](https://img.shields.io/badge/Deploy_on-RunPod-673AB7?style=for-the-badge)](https://console.runpod.io/deploy?template=bnqtkvcer3\&ref=dkx71w9b)

1. Click **Deploy on RunPod** and pick a GPU (an RTX 5090 / any Blackwell or Ada
   card works — the image ships cu128 torch).
2. Keep the template defaults: HTTP port **3000** exposed and a network volume
   mounted at **`/workspace`**.
3. Wait for the pod to come up. An auto-refreshing "ComfyUI is starting…" page
   serves until it's ready (\~30–60s ComfyUI init).

Then jump to [Connect from your machine](#connect-from-your-machine).

## Deploy & control it from the Agent Panel (v0.44+)

Since **comfyui-mcp 0.44**, you don't have to touch the RunPod console or run a
CLI command at all — the [Agent Panel](./panel) has a **RunPod control panel** that
deploys, connects, monitors, and stops a pod for you, and the same control sheet
ships in the [mobile app](./mobile).

1. **Set your key once.** In the panel's **API-Keys** card, paste your
   `RUNPOD_API_KEY`. It's stored server-side in `~/.comfyui-mcp/.env` — never in
   the browser.
2. **Open the RunPod control panel** from the host pill in the panel toolbar (it
   reads **🟢 Local · your rig** to start).
3. **Deploy or connect.** Hit **Deploy** for a one-tap pod (it routes through the
   template's deploy link and falls back across GPU types / COMMUNITY→SECURE when
   capacity is tight), or pick an existing pod **by name** from the dropdown and
   **Connect**.
4. **Watch it live.** The status card shows GPU / VRAM / uptime / **$·hr** and an **idle auto-stop** countdown, and the host pill flips to **🔵 RunPod · <pod> ·
   GPU · $/hr** — so where a render runs is never ambiguous. The agent installs
   your custom nodes + LoRAs and downloads your models onto the pod, so you get
   **exact canvas parity** with your local rig.
5. **Switch back and stop.** **Use Local** retargets rendering to your own rig
   instantly; **Stop** shuts the pod down. Idle auto-stop
   (`RUNPOD_IDLE_STOP_MINUTES`, default 15; only counts while you're actually
   rendering on the pod) is the cost backstop if you forget.

**Dead-man switch (v0.46+).** Idle auto-stop lives in the comfyui-mcp process —
if that process dies (crash, closed laptop), the backstop used to die with it
and the pod billed forever. Pods **created through the connector** now carry a
pod-side watchdog: while comfyui-mcp minds the pod it heartbeats every few
seconds; if the beats stop, the pod **stops itself** (never terminates — your
`/workspace` survives) after a grace period (45 min after boot with no
heartbeat, then 20 min between beats; `RUNPOD_DEADMAN_BOOT_GRACE_S` /
`RUNPOD_DEADMAN_BEAT_GRACE_S`). "Minding" survives **Use Local** and
**Unwatch** — those only change what the UI shows; the watchdog fires only
when comfyui-mcp itself is gone (or the pod exits). The watchdog stops the pod
with the **pod-scoped API key RunPod auto-injects into every pod** — your
account-wide key never leaves your machine, and there is nothing credential-
wise to opt out of. Leave it unarmed with `deadman:false` on
`runpod` / `action: "create"` (or `RUNPOD_DEADMAN=0`), or `DEADMAN_DISABLE=1` as a pod
env. Console-deployed pods never carry the heartbeat token, and custom-
template deploys (`RUNPOD_TEMPLATE_ID`) default it **off** — pass
`deadman:true` only if that image ships our watchdog.

<Note>
  New to renting GPUs for ComfyUI? The blog walks the whole flow end to end:
  [Run ComfyUI on a rented cloud GPU](./blog/runpod-comfyui).
</Note>

The rest of this page is the **manual / CLI path** — still fully supported, and
what the control panel drives under the hood.

## Connect from your machine

Once the pod is up, grab its public proxy URL (RunPod → your pod → the **:3000**
HTTP endpoint, e.g. `https://<pod-id>-3000.proxy.runpod.net`) and run **one
command** on your laptop:

```bash theme={null}
npx -y comfyui-mcp@latest connect https://<pod-id>-3000.proxy.runpod.net
```

For a **remote HTTPS pod**, `connect` automatically opens a **secure encrypted
`wss://` tunnel** (via Cloudflare) to the agent bridge on your machine and hands
the pod's panel that URL for you — so the pod's HTTPS page reaches the agent with
**no browser prompt, nothing to copy, in any browser**. For a **local** ComfyUI it
uses the plain `ws://127.0.0.1:9180` loopback bridge. Either way the agent — and
your Claude/ChatGPT login — runs only on **your** machine; nothing is installed on
the pod.

To finish, in the pod's ComfyUI open the **Agent Panel** sidebar and:

1. Turn on **Settings → General → "Use external/local orchestrator (advanced)"**.
2. Click **Connect**.

Now drive the graph in natural language.

<Note>
  **Why a tunnel?** A pod page is served over `https://`, and browsers block a secure
  page from opening an insecure `ws://` socket to your machine (mixed content /
  Private Network Access). The tunnel gives the bridge a valid-TLS `wss://` URL —
  gated by a per-session random token — so it just works everywhere with no prompt.
</Note>

<Note>
  If the pod sits behind auth, set `COMFYUI_AUTH_TOKEN` (plus optional
  `COMFYUI_AUTH_HEADER` / `COMFYUI_AUTH_SCHEME`) on the local `connect` command. For a
  pod fronted by **Cloudflare Access**, create an Access **service token** and set
  `CF_ACCESS_CLIENT_ID` + `CF_ACCESS_CLIENT_SECRET` — both ride every ComfyUI request
  (HTTP + the queue-watcher WebSocket), so the connector passes the gate while the
  human sign-in page stays up for browsers.
</Note>

### Keep everything on your machine (no Cloudflare)

Prefer not to route the bridge through Cloudflare? Reach the pod through your own
**SSH port-forward** so the page is a loopback origin (plain `ws://` works, no
tunnel):

```bash theme={null}
ssh <pod-ssh> -L 3000:localhost:3000   # grab the SSH command from RunPod → Connect
npx -y comfyui-mcp@latest connect http://localhost:3000
```

Then open **[http://localhost:3000](http://localhost:3000)**. Or connect at the pod's direct https URL but
force the plain loopback bridge with **`--insecure-bridge`** (you then arrange your
own path for the pod page to reach `ws://127.0.0.1:9180`).

Want a **stable, self-hosted alternative** to the default Cloudflare quick tunnel
— your own domain, no ephemeral hostname, full ownership of that hop — instead of
either of the above? See [Self-hosted relay](./self-hosted-relay).

## Topology: where the agent runs

```
  YOUR LAPTOP                                   CLOUD GPU POD (RunPod)
  ┌───────────────────────────┐                ┌───────────────────────────────────┐
  │ npx comfyui-mcp connect …  │  HTTP/WS  ───▶ │ nginx :3000 ─▶ ComfyUI :3001        │
  │  └─ panel orchestrator     │                │   ├─ Manager v2 (--enable-manager) │
  │     (Claude/ChatGPT Agent  │ ◀───  events   │   └─ Agent Panel (sidebar)         │
  │      SDK on YOUR sub)      │                │                                     │
  └───────────────────────────┘                └───────────────────────────────────┘
```

The pod deliberately ships **no Node.js agent, no Agent SDK, and no LLM client** —
they'd burn GPU-hours for nothing. The reasoning loop lives on your machine; the
pod is a pure ComfyUI backend. This is the same [remote-driving model](./panel) the
local Agent Panel uses, just with ComfyUI on a cloud GPU instead of localhost.

## What persists (and what doesn't)

The image is optimized for **fast stop/start**. The heavy software — ComfyUI, its
venv, Manager v2 — is baked into the immutable image and run from `/opt/ComfyUI`,
while `custom_nodes` lives on the `/workspace` volume (symlinked) so your installs
persist. A warm restart does no full install/sync/seed and just relaunches ComfyUI.

| What                                          | Where it lives                               | Survives a restart?      |
| --------------------------------------------- | -------------------------------------------- | ------------------------ |
| Models (incl. Manager downloads)              | volume `/workspace/models`                   | **Yes**                  |
| Workflows + ComfyUI settings + Manager config | volume `/workspace/user`                     | **Yes**                  |
| Inputs / outputs                              | volume `/workspace/input`, `/output`         | **Yes**                  |
| **Custom nodes** (agent/Manager installs)     | volume `/workspace/custom_nodes` (symlinked) | **Yes**                  |
| ComfyUI install + venv + Manager              | image `/opt/ComfyUI`                         | Re-pulled with the image |

<Note>
  **Custom nodes installed at runtime survive a restart.** `custom_nodes` is
  symlinked to `/workspace/custom_nodes`; on each boot the image's baked nodes (Agent
  Panel + builtins) are seeded/refreshed into it (so an image upgrade ships a current
  panel while your own nodes are kept), and each node's Python deps are reinstalled
  into the venv from a **persistent pip cache** on the volume — fast after the first
  time. Models persist too. To bake a node so it needs zero boot-time work, add it to
  the `Dockerfile` and rebuild the image (below).
</Note>

## Build & deploy your own image

The one-click template is the prebuilt image. A **lean, prebuilt image** — same
ComfyUI + Agent Panel + Manager, but without the optional donor extras
(`runpod-uploader`/`croc`/`app-manager`) or the baked SDXL spotcheck checkpoint,
built continuously in CI — is also public at
[`ghcr.io/artokun/comfyui-mcp-runpod:cu128-lean`](https://github.com/artokun/comfyui-mcp/pkgs/container/comfyui-mcp-runpod)
if you just want to point a RunPod template at something without building
anything yourself.

To customize it — pin versions, bake in extra custom nodes, change the model
layout — build and push your own from
[`docker/runpod/`](https://github.com/artokun/comfyui-mcp/tree/main/docker/runpod):

```bash theme={null}
cd docker/runpod
docker build -t <your-registry>/comfyui-mcp-runpod:cu128 .
docker push     <your-registry>/comfyui-mcp-runpod:cu128
```

No GPU is needed at build time. Then create a RunPod **Pod template** pointed at
your image with **HTTP port 3000** exposed and a **network volume at `/workspace`**.

The [`docker/runpod/README.md`](https://github.com/artokun/comfyui-mcp/blob/main/docker/runpod/README.md)
is the full build reference — the multi-stage Dockerfile, the exact ComfyUI launch
flags, the `extra_model_paths.yaml` volume mapping, the Manager remote-install
gate, environment variables, and the size/pin tradeoffs.

## Other cloud targets

The `connect` flow is not RunPod-specific — it works against **any** reachable
ComfyUI that serves the Agent Panel (another cloud host, a VPS, a box on your LAN).
Point `connect` at its URL and flip the external-orchestrator toggle:

```bash theme={null}
npx -y comfyui-mcp@latest connect https://your-comfyui.example.com
```

For exposing **comfyui-mcp itself** as a hosted, authenticated MCP server (rather
than deploying ComfyUI), see [Remote / hosted connector](./remote-connector).
