docs: encryption-key rotation safety + cloud/local README split
Rotation section now leads with a "back up the old key first" callout covering the most common foot-gun: rotating the key while .enc files still exist anywhere encrypted under the old key. Adds the explicit backup-then-test-recovery flow with platform-specific paths to look up the current key (env var / .env for local, Secrets panel for cloud). Cloud and local setup paths are now fully separate top-level sections with the gate-setup as the first action in each. Every .env reference is tagged "(local only)" to prevent the recurring confusion where cloud users tried to write secrets to disk on a hosted pod. Env-var entry tables now use explicit Field/Value column pairs (Name = COMFYUI_DROPSEND_ALLOW_SETUP, Value = 1) to match the layout of the actual RunPod Environment Variables UI. No code changes. Comfy Registry stays at v1.1.1; this commit lands on main only and is visible on the GitHub README. A v1.1.2 bump can publish the doc delta to the registry whenever convenient.
This commit is contained in:
@@ -46,14 +46,14 @@ Encryption is optional. Leave `enable_encryption` off and files upload as-is.
|
||||
## Two Nodes
|
||||
|
||||
### DropSend Setup Node
|
||||
Runs once. Exchanges your Dropbox app credentials for a refresh token, then either writes them to `.env` (local installs) or shows them in a one-shot browser panel (cloud installs) so you can copy them into your platform's secrets manager.
|
||||
Runs once. Takes your Dropbox app credentials (entered through a browser-only password modal), exchanges them for a refresh token, then either writes the token to `.env` *(for local installs only)* or shows it in a one-shot browser panel so you can copy it into your platform's secrets manager *(cloud installs)*.
|
||||
|
||||
### DropSend AutoUploader Node
|
||||
Runs every workflow. Watches your ComfyUI output folder, optionally encrypts each new file, and uploads it to Dropbox. Supports `.png`, `.jpg`, `.jpeg`, `.webp`, `.gif`, `.mp4`, `.avi`, `.mov`. Includes SHA256 verification, queue-based retries, and optional subfolder monitoring.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
## Installation (both cloud and local)
|
||||
|
||||
```bash
|
||||
cd ComfyUI/custom_nodes/
|
||||
@@ -61,11 +61,11 @@ git clone https://github.com/machinepainting/ComfyUI_DropSendNode.git
|
||||
pip install -r ComfyUI_DropSendNode/requirements.txt
|
||||
```
|
||||
|
||||
Restart ComfyUI after installation.
|
||||
Restart ComfyUI after installation. **Do not run the Setup Node yet** — the gate has to be set first (next step in your chosen path below).
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create a Dropbox App
|
||||
## Create a Dropbox App (both cloud and local)
|
||||
|
||||
1. Log in to [Dropbox](https://www.dropbox.com/)
|
||||
2. Open [Dropbox Developers](https://www.dropbox.com/developers/) and click **Create Apps**
|
||||
@@ -82,53 +82,65 @@ Restart ComfyUI after installation.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Run the Setup Node
|
||||
## Pick your path
|
||||
|
||||
The Setup Node is gated behind an environment variable. This prevents a remote workflow from hijacking or wiping your credentials. Pick the section that matches where you run ComfyUI.
|
||||
- **[Cloud Setup (RunPod and similar hosted ComfyUI)](#cloud-setup-runpod-and-similar)** — credentials never touch the pod's filesystem
|
||||
- **[Local Setup (ComfyUI on your own machine)](#local-setup-comfyui-on-your-own-machine)** — credentials written to a `.env` file at mode `0600`
|
||||
|
||||
### A) Cloud (RunPod and similar)
|
||||
---
|
||||
|
||||
**1. Set the gate.** Add this to your RunPod template's **Environment Variables**:
|
||||
## Cloud Setup (RunPod and similar)
|
||||
|
||||
```
|
||||
COMFYUI_DROPSEND_ALLOW_SETUP=1
|
||||
```
|
||||
> **For hosted ComfyUI installs.** Credentials are delivered to your browser only and never written to the pod's filesystem. If you're running ComfyUI on your own machine, use the [Local Setup](#local-setup-comfyui-on-your-own-machine) below instead.
|
||||
|
||||
Start (or restart) the pod. To verify, open a pod shell and run:
|
||||
### Step 1 (Cloud): Set the gate — do this BEFORE running the Setup Node
|
||||
|
||||
The Setup Node refuses to run without `COMFYUI_DROPSEND_ALLOW_SETUP=1` in the pod environment. This blocks remote workflows from hijacking or wiping your credentials.
|
||||
|
||||
In your RunPod template, open the **Environment Variables** section and add:
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Name** | `COMFYUI_DROPSEND_ALLOW_SETUP` |
|
||||
| **Value** | `1` |
|
||||
|
||||
Save the template, then **restart the pod or deploy a new one** from the updated template (RunPod picks up env-var changes only on pod start, not while a pod is already running). Once the pod is up, open a pod shell and verify:
|
||||
|
||||
```bash
|
||||
echo $COMFYUI_DROPSEND_ALLOW_SETUP # should print: 1
|
||||
```
|
||||
|
||||
**2. Add the Setup Node to your workflow.** Configure:
|
||||
If `echo` prints nothing, the variable did not propagate — fix this before continuing or the next step will fail with a "Setup is disabled" error.
|
||||
|
||||
### Step 2 (Cloud): Run the Setup Node (display_only mode)
|
||||
|
||||
Add the **DropSend Setup Node** to a workflow and configure:
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| `storage_method` | `display_only` (values shown in browser, never saved on the pod) |
|
||||
| `encryption_key_method` | `Display Only` (or `off` if you do not want encryption) |
|
||||
| `storage_method` | `display_only` *(values shown in browser, never written to the pod)* |
|
||||
| `encryption_key_method` | `Display Only` *(or `off` if you don't want encryption)* |
|
||||
| `reconnect` | leave off |
|
||||
|
||||
**3. Click "Set credentials..."** on the node. A modal opens with three password fields:
|
||||
Click **Set credentials…** on the node. A modal opens with three password fields:
|
||||
|
||||
| Field | What to paste |
|
||||
|---|---|
|
||||
| App Key | Your Dropbox App Key (from Step 1) |
|
||||
| App Secret | Your Dropbox App Secret (from Step 1) |
|
||||
| Auth Code | Leave blank for now |
|
||||
| App Key | Your Dropbox App Key |
|
||||
| App Secret | Your Dropbox App Secret |
|
||||
| Auth Code | **Leave blank for now** |
|
||||
|
||||
Click **Save**. The modal closes.
|
||||
|
||||
**4. Click Queue (Run).** The node prints an OAuth URL. The URL is delivered three ways, use whichever works:
|
||||
Click **Save** in the modal. Then click **Queue** in ComfyUI. The node prints an OAuth URL three ways, use whichever works:
|
||||
|
||||
- A browser popup opens automatically (preferred)
|
||||
- The ComfyUI terminal prints a `DROPSEND DROPBOX AUTHORIZATION REQUIRED` banner with the URL (Cmd or Ctrl click to open)
|
||||
- The pod's ComfyUI terminal prints a `DROPSEND DROPBOX AUTHORIZATION REQUIRED` banner with the URL (Cmd / Ctrl click to open)
|
||||
- Wire a `Show Text` node to the Setup Node's `STRING` output
|
||||
|
||||
**5. Authorize at Dropbox.** Open the URL, click Allow, and copy the authorization code Dropbox displays.
|
||||
**Authorize at Dropbox.** Open the URL → Allow → copy the authorization code Dropbox shows you.
|
||||
|
||||
**6. Paste the auth code.** A second modal auto-opens for this. Paste your App Key, App Secret, and the new Auth Code. Click **Save**.
|
||||
**A second modal auto-opens** in your ComfyUI tab. Paste your **App Key**, **App Secret**, and the new **Auth Code** all three. Click **Save**, then click **Queue** again.
|
||||
|
||||
**7. Click Queue again.** A **DropSend Credentials** panel appears in your browser with four values:
|
||||
A **DropSend Credentials** panel appears in your browser with four values:
|
||||
|
||||
| Value | Description |
|
||||
|---|---|
|
||||
@@ -137,39 +149,64 @@ Click **Save**. The modal closes.
|
||||
| `DROPBOX_REFRESH_TOKEN` | Long-lived token, just generated |
|
||||
| `COMFYUI_ENCRYPTION_KEY` | Only if you chose to generate one |
|
||||
|
||||
Each value has a **Copy** button. There is also a **Copy all as NAME=value** button.
|
||||
Each value has a **Copy** button. There's also **Copy all as NAME=value**. **The panel is browser-only — closing it discards the data, and nothing was written to the pod.** If you close it before copying, just rerun the Setup Node to regenerate.
|
||||
|
||||
The panel is browser-only. Closing it discards the data and nothing is saved on the pod. If you close it before copying, just rerun the Setup Node to regenerate the values.
|
||||
### Step 3 (Cloud): Save the credentials to RunPod Secrets
|
||||
|
||||
**8. Save the values to RunPod Secrets.** In RunPod, click **Secrets** in the sidebar and create:
|
||||
In RunPod, click **Secrets** in the sidebar and create:
|
||||
|
||||
| Secret Name (must match exactly) | Value |
|
||||
|---|---|
|
||||
| `DROPBOX_APP_KEY` | from the panel |
|
||||
| `DROPBOX_APP_SECRET` | from the panel |
|
||||
| `DROPBOX_REFRESH_TOKEN` | from the panel |
|
||||
| `COMFYUI_ENCRYPTION_KEY` | from the panel (only if using encryption) |
|
||||
| `COMFYUI_ENCRYPTION_KEY` | from the panel *(only if using encryption)* |
|
||||
|
||||
**9. Add the secrets to your pod template.** Click **My Templates**, edit your template, and under **Environment Variables** add:
|
||||
### Step 4 (Cloud): Add the secrets to your pod template
|
||||
|
||||
| Key | Value |
|
||||
In **My Templates**, edit your template, and under **Environment Variables** add four more entries (one per row):
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| `DROPBOX_APP_KEY` | `{{ RUNPOD_SECRET_DROPBOX_APP_KEY }}` |
|
||||
| `DROPBOX_APP_SECRET` | `{{ RUNPOD_SECRET_DROPBOX_APP_SECRET }}` |
|
||||
| `DROPBOX_REFRESH_TOKEN` | `{{ RUNPOD_SECRET_DROPBOX_REFRESH_TOKEN }}` |
|
||||
| `COMFYUI_ENCRYPTION_KEY` | `{{ RUNPOD_SECRET_COMFYUI_ENCRYPTION_KEY }}` (optional) |
|
||||
| **Name** | `DROPBOX_APP_KEY` |
|
||||
| **Value** | `{{ RUNPOD_SECRET_DROPBOX_APP_KEY }}` |
|
||||
|
||||
Save the template. The next time you deploy a pod from this template, ComfyUI will see the credentials automatically.
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Name** | `DROPBOX_APP_SECRET` |
|
||||
| **Value** | `{{ RUNPOD_SECRET_DROPBOX_APP_SECRET }}` |
|
||||
|
||||
> You can now remove `COMFYUI_DROPSEND_ALLOW_SETUP=1` from the template unless you plan to re-run the Setup Node from this pod.
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Name** | `DROPBOX_REFRESH_TOKEN` |
|
||||
| **Value** | `{{ RUNPOD_SECRET_DROPBOX_REFRESH_TOKEN }}` |
|
||||
|
||||
**10. Deploy a fresh pod from your template.** Skip to **Step 3**.
|
||||
*(Optional — only if using encryption)*
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Name** | `COMFYUI_ENCRYPTION_KEY` |
|
||||
| **Value** | `{{ RUNPOD_SECRET_COMFYUI_ENCRYPTION_KEY }}` |
|
||||
|
||||
> **You can now remove `COMFYUI_DROPSEND_ALLOW_SETUP=1` from the template** unless you plan to re-run the Setup Node from this pod. The AutoUploader doesn't need it.
|
||||
|
||||
Save the template. **Deploy a fresh pod from the updated template** so the new env vars take effect.
|
||||
|
||||
### Step 5 (Cloud): Use the AutoUploader
|
||||
|
||||
Skip down to [Use the AutoUploader](#use-the-autouploader-both-cloud-and-local) below — that section is shared between cloud and local.
|
||||
|
||||
---
|
||||
|
||||
### B) Local install
|
||||
## Local Setup (ComfyUI on your own machine)
|
||||
|
||||
**1. Set the gate in the same shell that will launch ComfyUI:**
|
||||
> **For ComfyUI running on your own machine.** Credentials are stored in a `.env` file *(local installs only)* at mode `0600` in the plugin directory. If you're running ComfyUI on a hosted pod, use [Cloud Setup](#cloud-setup-runpod-and-similar) instead — `.env` is never appropriate on a multi-tenant or shared host.
|
||||
|
||||
### Step 1 (Local): Set the gate — do this BEFORE running the Setup Node
|
||||
|
||||
The Setup Node refuses to run without `COMFYUI_DROPSEND_ALLOW_SETUP=1` in the shell environment. This blocks remote workflows from hijacking or wiping your credentials.
|
||||
|
||||
**In the same terminal you'll use to launch ComfyUI**, run:
|
||||
|
||||
```bash
|
||||
# macOS / Linux
|
||||
@@ -195,52 +232,54 @@ echo %COMFYUI_DROPSEND_ALLOW_SETUP%
|
||||
echo $env:COMFYUI_DROPSEND_ALLOW_SETUP
|
||||
```
|
||||
|
||||
Each command should print `1`. Now launch ComfyUI from that same shell.
|
||||
Each command should print `1`. **Now launch ComfyUI from that same terminal** — env vars don't carry across separate terminals.
|
||||
|
||||
**2. Add the Setup Node to your workflow.** Configure:
|
||||
### Step 2 (Local): Run the Setup Node (env_file mode)
|
||||
|
||||
> **`.env` is for local installs only.** This mode writes your Dropbox refresh token (and optionally your encryption key) to `.env` (mode `0600`) in the plugin directory. Don't use `env_file` on a hosted pod — the file persists on the pod's filesystem and is readable by any process running as the same user.
|
||||
|
||||
Add the **DropSend Setup Node** to a workflow and configure:
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| `storage_method` | `env_file` (values written to `.env`, mode `0600`, in the plugin directory) |
|
||||
| `encryption_key_method` | `save to .env` (or `off`) |
|
||||
| `storage_method` | `env_file` *(local installs only — values written to `.env` at mode `0600` in the plugin directory)* |
|
||||
| `encryption_key_method` | `save to .env` *(local installs only)* — or `off` if you don't want encryption |
|
||||
| `reconnect` | leave off |
|
||||
|
||||
**3. Click "Set credentials..."** on the node. In the modal:
|
||||
Click **Set credentials…** on the node. In the modal:
|
||||
|
||||
| Field | What to paste |
|
||||
|---|---|
|
||||
| App Key | Your Dropbox App Key |
|
||||
| App Secret | Your Dropbox App Secret |
|
||||
| Auth Code | Leave blank |
|
||||
| Auth Code | **Leave blank for now** |
|
||||
|
||||
Click **Save**.
|
||||
Click **Save**. Then click **Queue**. The node prints an OAuth URL — open it, authorize at Dropbox, copy the auth code.
|
||||
|
||||
**4. Click Queue.** The node prints an OAuth URL. Open it, authorize at Dropbox, and copy the auth code.
|
||||
**A second modal auto-opens.** Paste **App Key**, **App Secret**, and **Auth Code** all three. Click **Save**, then **Queue** again.
|
||||
|
||||
**5. Paste the auth code.** A second modal auto-opens. Paste App Key, App Secret, and Auth Code. Click **Save**.
|
||||
Credentials are written to `.env` *(local only)* in the plugin directory and loaded into the running ComfyUI process. **No ComfyUI restart needed** — the AutoUploader will read them on its next run.
|
||||
|
||||
**6. Click Queue again.** Credentials are written to `.env` in the plugin directory and loaded into the running ComfyUI process. No restart needed.
|
||||
|
||||
> Once setup is complete, you can drop `COMFYUI_DROPSEND_ALLOW_SETUP` from your environment. The AutoUploader does not need it.
|
||||
> **You can now `unset COMFYUI_DROPSEND_ALLOW_SETUP`** *(or close the terminal)* — the AutoUploader doesn't need it. You'll only need to set it again if you re-run the Setup Node to rotate credentials.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Use the AutoUploader
|
||||
## Use the AutoUploader (both cloud and local)
|
||||
|
||||
1. Add the **DropSend AutoUploader Node** to your workflow.
|
||||
2. Configure:
|
||||
|
||||
| Field | What it does |
|
||||
|---|---|
|
||||
| `watch_folder` | Folder to monitor for new files (defaults to ComfyUI output, see clamp note in Security section) |
|
||||
| `dropbox_dest_folder` | Destination folder in Dropbox (must start with `/Apps/...`) |
|
||||
| `folder_format` | Append today's date to the destination, or use the literal name |
|
||||
| `watch_folder` | Folder to monitor for new files (defaults to ComfyUI output; see clamp note in Security section) |
|
||||
| `dropbox_dest_folder` | Destination folder in Dropbox (must start with `/`, see Dropbox app's App Folder root) |
|
||||
| `folder_format` | `project_name` (use the literal folder name) or one of the date formats (appends today's date) |
|
||||
| `enable_encryption` | If true, encrypts each file with AES (Fernet) before uploading |
|
||||
| `Post_Delete_Enc` | After upload, delete the local `.enc` file |
|
||||
| `Post_Delete_Enc` | After successful upload, delete the local `.enc` file |
|
||||
| `Subfolder_Monitor` | Recursively watch subfolders |
|
||||
| `run_process` | Set to `True` to start uploading |
|
||||
|
||||
3. Run a workflow that generates an image. The AutoUploader picks it up, optionally encrypts it, uploads it to Dropbox, and prints status to the ComfyUI console.
|
||||
3. Run a workflow that generates an image. The AutoUploader picks it up, optionally encrypts it, uploads it to Dropbox, and prints status to the ComfyUI console (look for `📦👀 Watching:`, `📦🔐 Encrypted:`, `📦📤 Sent:`).
|
||||
|
||||
---
|
||||
|
||||
@@ -371,11 +410,26 @@ The Setup Node printed this because your prompt was submitted without a `client_
|
||||
|
||||
### Encryption key rotation
|
||||
|
||||
The Fernet key in `COMFYUI_ENCRYPTION_KEY` is symmetric: the same key encrypts and decrypts. Practical implications:
|
||||
The Fernet key in `COMFYUI_ENCRYPTION_KEY` is symmetric: the same key encrypts and decrypts. The Dropbox credentials and the encryption key are independent — rotating one does not require rotating the other.
|
||||
|
||||
- **Old `.enc` files cannot be decrypted with a new key.** If you rotate the key while previously-encrypted files still live in your Dropbox, those files become permanently unreadable unless you keep the old key on hand (e.g. in a labelled backup). Decide before rotating: re-download and re-encrypt against the new key, accept the loss, or stash the old key in a labelled secrets vault entry (e.g. `COMFYUI_ENCRYPTION_KEY_2025_archive`).
|
||||
- **A leaked key compromises everything encrypted under it.** If you suspect the key has been exposed (committed to git, pasted into a chat, etc.), generate a fresh key, re-encrypt files you need going forward, and delete or replace the old `.enc` files in Dropbox. The leaked key remains valid for any copy of the old files an attacker may already have.
|
||||
- **Generating a new key.** Re-run the Setup Node with `encryption_key_method = Display Only` (or `save to .env`). Each run generates a fresh `Fernet.generate_key()`. Copy the new value into your secrets store and restart the pod.
|
||||
> ⚠️ **Before you swap in a new encryption key — back up the old one first.** If you have `.enc` files anywhere (still in Dropbox, on a synced drive, archived on disk) that were encrypted with the old key, **only the old key can decrypt them**. A new key cannot. Once the old key is overwritten or unset and not saved anywhere, those files become unreadable forever.
|
||||
>
|
||||
> **Do this before rotating, in this order:**
|
||||
>
|
||||
> 1. **Find your current `COMFYUI_ENCRYPTION_KEY`.** *(Local installs only — for cloud, the same applies but the value is in your platform's secrets store, e.g. RunPod Secrets.)* Locations to check:
|
||||
> - **Local — env var:** `echo $COMFYUI_ENCRYPTION_KEY` *(macOS / Linux)* or `echo %COMFYUI_ENCRYPTION_KEY%` *(Windows cmd)*
|
||||
> - **Local — `.env`:** `grep COMFYUI_ENCRYPTION_KEY ComfyUI/custom_nodes/ComfyUI_DropSendNode/.env`
|
||||
> - **Cloud — RunPod Secrets:** open the Secrets panel and reveal `COMFYUI_ENCRYPTION_KEY`
|
||||
> 2. **Save it somewhere durable** — password manager entry labelled e.g. `COMFYUI_ENCRYPTION_KEY_<date>_archive`, secure note, encrypted vault. Don't paste it into chat / git / a screenshot you'll share.
|
||||
> 3. *(Then)* **Swap in the new key** — replace `COMFYUI_ENCRYPTION_KEY` in your env / `.env` *(local only)* / RunPod Secrets with the new value.
|
||||
> 4. **Test recovery before deleting anything.** Pick one `.enc` file, set the OLD key in a shell *(see "Recovering files encrypted with an old key" below)*, run the decrypt script — confirm it produces the original file. If decryption works, you have a working backup of the old key and rotation is safe.
|
||||
>
|
||||
> Once you've confirmed the old key is saved and the recovery path works, you can rotate freely. The new key handles all *future* uploads; the old key stays useful for anything previously encrypted.
|
||||
|
||||
Other practical implications:
|
||||
|
||||
- **A leaked key compromises everything encrypted under it.** If you suspect the key has been exposed (committed to git, pasted into a chat, screenshot leaked, etc.), generate a fresh key, re-encrypt files you need going forward, and delete or replace the old `.enc` files in Dropbox. The leaked key remains valid for any copy of the old files an attacker may already have.
|
||||
- **Generating a new key.** Re-run the Setup Node with `encryption_key_method = Display Only` (cloud) or `save to .env` *(local only)*. Each run generates a fresh `Fernet.generate_key()`. Copy the new value into your secrets store *(cloud)* or `.env` *(local)* and restart ComfyUI / the pod.
|
||||
|
||||
#### Recovering files encrypted with an old key
|
||||
|
||||
|
||||
Reference in New Issue
Block a user