From 97547c783c94762625ded92d5b612ef864dc7d3f Mon Sep 17 00:00:00 2001 From: William Gill Date: Sun, 19 Apr 2026 10:45:23 -0500 Subject: [PATCH] Make ai-stack the only deployment shape Drops the duplicate standalone compose / .env.example / SETUP.md at the repo root. Bring-up content folded into deployments/ai-stack/README.md so there's exactly one set of deployment instructions, sitting next to the files it describes. Root README is now just the repo overview and a pointer at the deployment. Co-Authored-By: Claude Opus 4.7 (1M context) --- .env.example | 9 -- README.md | 61 ++++------- SETUP.md | 146 -------------------------- deployments/ai-stack/README.md | 180 +++++++++++++++++++++++++++------ docker-compose.yml | 110 -------------------- 5 files changed, 173 insertions(+), 333 deletions(-) delete mode 100644 .env.example delete mode 100644 SETUP.md delete mode 100644 docker-compose.yml diff --git a/.env.example b/.env.example deleted file mode 100644 index 71d65a2..0000000 --- a/.env.example +++ /dev/null @@ -1,9 +0,0 @@ -# Copy to .env and edit. docker compose picks .env up automatically. - -# Public hostname/scheme your reverse proxy terminates. Used by Open WebUI for -# auth redirects and email-link generation. -OPEN_WEBUI_URL=http://localhost:3000 - -# Cookie-signing key. Generate once with: openssl rand -hex 32 -# Must stay stable across restarts — rotating it logs every user out. -OPEN_WEBUI_SECRET_KEY=change-me-please diff --git a/README.md b/README.md index cf38530..9b769a5 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,33 @@ # comfyui-nvidia -ComfyUI image-generation backend, NVIDIA-accelerated, fronted by Open WebUI for -multi-user chat and image generation/editing. +ComfyUI image-generation backend, NVIDIA-accelerated, fronted by Open WebUI +for multi-user chat and image generation/editing. Built from the official ComfyUI [manual install for -NVIDIA](https://docs.comfy.org/installation/manual_install#nvidia) — no third- -party base image. Two services on one bridge network: +NVIDIA](https://docs.comfy.org/installation/manual_install#nvidia) — no +third-party base image. CI publishes the image to +`git.anomalous.dev/alphacentri/comfyui-nvidia` on every `v*` tag (see +[.gitea/workflows/release.yml](.gitea/workflows/release.yml)). -| Service | Port (host) | Role | -| ----------- | ----------- | ----------------------------------------------- | -| `comfyui` | `8188` | ComfyUI server + native web UI | -| `open-webui`| `3000` | Multi-user chat with txt2img / img2img panel | +## Repository layout -Open WebUI submits ComfyUI workflows directly via the documented integration — -no MCP shim, no API translation layer. Workflow templates live in -[`workflows/`](workflows/) and get pasted into Open WebUI's admin panel during -setup. +| Path | What | +| -------------------------- | ----------------------------------------------------- | +| `Dockerfile` | ComfyUI on NVIDIA, manual-install pattern | +| `workflows/` | txt2img + img2img workflow JSONs and node mappings | +| `deployments/ai-stack/` | The deployment — compose, Caddyfile, env, model preseed | +| `.gitea/workflows/` | Release pipeline (build & push image on tag) | -## Quick start +## Deploy -```sh -cp .env.example .env -# edit .env — set OPEN_WEBUI_SECRET_KEY at minimum -docker compose up -d -``` - -`compose up` pulls the prebuilt ComfyUI image from -`git.anomalous.dev/alphacentri/comfyui-nvidia` (CI publishes it on every -`v*` tag — see [.gitea/workflows/release.yml](.gitea/workflows/release.yml)). -Use `docker compose build` to rebuild locally when iterating on the Dockerfile. - -Then drop a checkpoint into the `comfyui-models` volume and finish the Open -WebUI ComfyUI configuration. Full walkthrough in [SETUP.md](SETUP.md). - -## Deployment examples - -- **Repo root** (`docker-compose.yml`) — minimal `comfyui` + `open-webui` - bridge for kicking the tyres on a single-purpose box. -- **[`deployments/ai-stack/`](deployments/ai-stack/)** — production-shaped - multi-service stack: Caddy (TLS + reverse proxy), Ollama (with one-shot - model preseeding), ComfyUI, Open WebUI, optional Anubis anti-bot. Mirrors - the live `srvno.de` deployment. +The full stack — Caddy + Ollama + ComfyUI + Open WebUI (+ optional +Anubis) — lives under [`deployments/ai-stack/`](deployments/ai-stack/). +Bring-up steps, host prerequisites, Open WebUI workflow wiring, and +gotchas are in [`deployments/ai-stack/README.md`](deployments/ai-stack/README.md). ## Replaces -This repo supersedes the previous figment + segment + Forge stack. ComfyUI's -node graph covers everything those services provided (txt2img, img2img, -inpaint, mask generation via SAM/GroundingDINO custom nodes), and Open WebUI -talks to it natively. +This repo supersedes the previous figment + segment + Forge stack. +ComfyUI's node graph covers everything those services provided +(txt2img, img2img, inpaint, mask generation via SAM/GroundingDINO custom +nodes), and Open WebUI talks to it natively. diff --git a/SETUP.md b/SETUP.md deleted file mode 100644 index 682d727..0000000 --- a/SETUP.md +++ /dev/null @@ -1,146 +0,0 @@ -# Setup - -End-to-end walkthrough: clean host -> running stack -> first generated image -in Open WebUI. - -## 1. Host prerequisites - -- Linux (or WSL2) with an NVIDIA GPU and a recent driver. - - cu126 wheels (default Dockerfile): driver >= 545 - - cu130 wheels (swap in Dockerfile): driver >= 580 -- Docker Engine + Compose v2. -- [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) - installed and the Docker runtime configured (`nvidia-ctk runtime configure - --runtime=docker && systemctl restart docker`). - -Confirm GPU passthrough works before bringing the stack up: - -```sh -docker run --rm --gpus all nvidia/cuda:12.6.3-base-ubuntu24.04 nvidia-smi -``` - -## 2. Configure environment - -```sh -cp .env.example .env -``` - -Edit `.env`: - -- `OPEN_WEBUI_URL` — public URL Open WebUI is reached at (used for auth - redirects). For local-only, leave the default. -- `OPEN_WEBUI_SECRET_KEY` — generate with `openssl rand -hex 32`. Keep stable; - rotating it logs every user out. - -## 3. Start the stack - -```sh -docker compose up -d -``` - -This pulls the prebuilt `comfyui-nvidia` image from the Gitea registry (CI -publishes it on every `v*` tag) plus the upstream Open WebUI image, then -brings both up. `docker compose logs -f comfyui` should end with a line like -`To see the GUI go to: http://0.0.0.0:8188`. - -To build the image locally instead (e.g. while iterating on the Dockerfile): - -```sh -docker compose build comfyui -docker compose up -d -``` - -First local build pulls the CUDA base, PyTorch wheels, and ComfyUI source — -expect several minutes. - -Health-check both services: - -```sh -curl -sf http://localhost:8188/system_stats | head -c 200 -curl -sf http://localhost:3000/health -``` - -## 4. Add at least one checkpoint - -ComfyUI ships no models. The shipped workflow templates reference -`v1-5-pruned-emaonly.safetensors` as a placeholder; drop any SD/SDXL/Flux -checkpoint into the `comfyui-models` volume under `checkpoints/`: - -```sh -docker run --rm -v comfyui-nvidia_comfyui-models:/models -w /models/checkpoints \ - curlimages/curl:latest -L -O \ - https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors -``` - -Or open the ComfyUI web UI at , click the **Manager** -button (added by ComfyUI-Manager), and use **Model Manager** to install one -through the UI. - -## 5. First-user signup in Open WebUI - -Open . The first account created becomes the admin. -Subsequent signups land in `pending` and need admin approval (set by -`DEFAULT_USER_ROLE: pending` in compose). - -## 6. Wire Open WebUI to ComfyUI - -Open WebUI ships the ComfyUI integration but won't know which workflow to -submit until you paste one in. Do this once per workflow (txt2img and -img2img). - -In Open WebUI: **Admin Panel -> Settings -> Images**. - -1. **Image Generation Engine** -> `ComfyUI` (already preselected via env var). -2. **ComfyUI Base URL** -> `http://comfyui:8188` (already preselected). -3. **ComfyUI Workflow** -> paste the entire contents of - [`workflows/txt2img.json`](workflows/txt2img.json). -4. **ComfyUI Workflow Nodes** -> paste the contents of - [`workflows/txt2img.nodes.json`](workflows/txt2img.nodes.json). -5. **Default Model** -> the filename of the checkpoint you dropped in step 4 - (e.g. `v1-5-pruned-emaonly.safetensors`). -6. Save. - -For image editing (img2img), scroll to the **Image Editing** section in the -same panel and repeat with [`workflows/img2img.json`](workflows/img2img.json) -and [`workflows/img2img.nodes.json`](workflows/img2img.nodes.json). - -## 7. Test it - -In any chat, click the image-generation button and prompt for an image. Open -WebUI submits the workflow to ComfyUI; the result drops back into the chat -when KSampler finishes. To test img2img, attach an image and use the edit -action. - -## How the workflow node mappings work - -Open WebUI doesn't introspect the workflow graph. The `*.nodes.json` files -tell it which node IDs and input fields to overwrite when the user provides -a prompt, image, seed, etc. Each entry: - -```json -{ "type": "", "node_ids": [""], "key": "" } -``` - -Recognised `type` strings (per Open WebUI source): `model`, `prompt`, -`negative_prompt`, `width`, `height`, `n` (batch size), `steps`, `seed`, and -`image` (img2img / edit only). - -If you swap in a fancier workflow (SDXL, Flux, ControlNet, custom samplers, -NL masking via SAM nodes, etc.), update the matching `*.nodes.json` so the -node IDs and input keys still line up. - -## Common gotchas - -- **"Model not found" in Open WebUI's image panel.** ComfyUI lists models from - `/opt/comfyui/models/checkpoints/`. Confirm the file is there and matches - the **Default Model** field exactly (filename including extension). -- **Out-of-memory on first generate.** Lower `IMAGE_SIZE` in compose - (e.g. `768x768`) or pass `--lowvram` / `--medvram` in the Dockerfile CMD. -- **Custom nodes need extra pip packages.** Install via ComfyUI-Manager (it - pip-installs into the container's venv). Persisted because - `/opt/comfyui/custom_nodes` is a named volume — but the venv at `/opt/venv` - is not, so packages added by the manager survive container restarts only if - the manager re-installs them on boot. For permanent custom-node deps, add a - `RUN pip install ...` to the Dockerfile and rebuild. -- **GPU not visible inside container.** Re-run the `nvidia-smi` test in step - 1. If it fails, the toolkit is misconfigured. diff --git a/deployments/ai-stack/README.md b/deployments/ai-stack/README.md index f354285..7228309 100644 --- a/deployments/ai-stack/README.md +++ b/deployments/ai-stack/README.md @@ -1,12 +1,12 @@ -# ai-stack — combined deployment example +# ai-stack — deployment The full multi-service stack: Caddy (TLS + reverse proxy) in front of Open WebUI (chat + image generation panel), Ollama (LLMs), and ComfyUI (image generation), with an optional Anubis PoW anti-bot sidecar. One GPU host, one bridge network, one TLS entry point. -This is what runs in production for the `srvno.de` deployment, sanitized -for sharing. +This is the only supported deployment shape — sanitized snapshot of the +production `srvno.de` deployment. ## Files @@ -17,43 +17,165 @@ for sharing. | `init-models.sh` | Models to preseed into Ollama on first boot | | `.env.example` | Secrets and image-tag pins. Copy to `.env` | -## Bring it up +## 1. Host prerequisites + +- Linux (or WSL2) with an NVIDIA GPU and a recent driver. + - cu126 wheels (default Dockerfile): driver >= 545 + - cu130 wheels (swap in Dockerfile): driver >= 580 +- Docker Engine + Compose v2. +- [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) + installed and the Docker runtime configured (`nvidia-ctk runtime configure + --runtime=docker && systemctl restart docker`). +- DNS for the chat / ComfyUI hostnames already pointing at this host + (Caddy needs working DNS to provision Let's Encrypt certs on first boot). + +Confirm GPU passthrough works before bringing the stack up: + +```sh +docker run --rm --gpus all nvidia/cuda:12.6.3-base-ubuntu24.04 nvidia-smi +``` + +## 2. Configure ```sh cp .env.example .env -# edit .env — generate the two keys with `openssl rand -hex 32` +# generate the two keys with: openssl rand -hex 32 +``` -# edit Caddyfile — replace example.com hostnames with yours, replace the -# basic_auth bcrypt placeholder, point DNS at this host +Then edit: -# edit init-models.sh — keep the models you want, drop the rest +- **`.env`** — fill in `WEBUI_SECRET_KEY` and (if using Anubis) `ANUBIS_OWUI_KEY`. + Optionally pin `COMFYUI_IMAGE_TAG` to a specific `v*` release instead of + `latest`. +- **`Caddyfile`** — replace the `chat.example.com` and `comfyui.example.com` + hostnames with yours; replace `REPLACE_WITH_BCRYPT_HASH` with a real + bcrypt hash: + ```sh + docker run --rm caddy:latest caddy hash-password --plaintext 'your-password' + ``` +- **`init-models.sh`** — keep the LLMs you want preseeded, drop the rest. + Check sizes at first; the host needs disk + for everything listed. +- **`docker-compose.yml`** — update `WEBUI_URL` and `COOKIE_DOMAIN` to + match the hostnames you set in the Caddyfile. + +## 3. Bring it up + +```sh docker compose up -d docker compose logs -f ``` -First boot: Caddy provisions Let's Encrypt certs (DNS must already point -here), the model-init container pulls the LLMs listed in `init-models.sh` -(can take a while — `mistral-nemo:12b` is ~7 GB), and ComfyUI initialises -its volumes empty. Drop a checkpoint into the `comfyui-models` volume -under `checkpoints/` before the first image generation — see the repo -root [SETUP.md](../../SETUP.md) §4. +First boot: Caddy provisions Let's Encrypt certs, the `model-init` +container pulls the LLMs in `init-models.sh` (slow — `mistral-nemo:12b` +alone is ~7 GB), and ComfyUI initialises empty volumes. -After Open WebUI is up, finish the ComfyUI integration via the admin -panel — paste the four workflow JSONs from [`../../workflows/`](../../workflows/). -See [SETUP.md §6](../../SETUP.md). +Health-check: -## What's different from the upstream `comfyui-nvidia` standalone compose +```sh +docker compose exec comfyui curl -sf http://127.0.0.1:8188/system_stats | head -c 200 +docker compose exec open-webui curl -sf http://127.0.0.1:8080/health +``` -The standalone compose at the repo root is just `comfyui` + `open-webui` -on a fresh bridge — meant for kicking the tyres or running ComfyUI on a -single-purpose box. This deployment adds: +## 4. Drop in at least one ComfyUI checkpoint -- **Caddy** with auto-TLS, so Open WebUI and ComfyUI are reachable on - real hostnames over HTTPS instead of `localhost:3000`. -- **Ollama** for chat models, with a one-shot `model-init` puller that - preseeds whatever `init-models.sh` lists. -- **Anubis** anti-bot stub for protected hostnames (commented in by - default; uncomment + provide a key to activate). -- No host ports published for ComfyUI or Open WebUI — Caddy is the only - service bound to 80/443. +ComfyUI ships no models. The shipped workflow templates reference +`v1-5-pruned-emaonly.safetensors` as a placeholder; drop any +SD/SDXL/Flux checkpoint into the `comfyui-models` volume under +`checkpoints/`: + +```sh +docker run --rm -v ai-stack_comfyui-models:/models -w /models/checkpoints \ + curlimages/curl:latest -L -O \ + https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors +``` + +Or open the ComfyUI native UI at `https://comfyui.example.com` (after +basic-auth login), use the **Manager** button (added by ComfyUI-Manager), +and install one through **Model Manager**. + +## 5. First-user signup in Open WebUI + +Open `https://chat.example.com`. The first account created becomes the +admin. Subsequent signups land in `pending` and need admin approval (set +by `DEFAULT_USER_ROLE: pending` in compose). + +## 6. Wire Open WebUI to ComfyUI + +Open WebUI ships the ComfyUI integration but won't know which workflow to +submit until you paste one in. Do this once for txt2img, once for img2img. + +In Open WebUI: **Admin Panel -> Settings -> Images**. + +1. **Image Generation Engine** -> `ComfyUI` (preselected via env var). +2. **ComfyUI Base URL** -> `http://comfyui:8188` (preselected). +3. **ComfyUI Workflow** -> paste the entire contents of + [`../../workflows/txt2img.json`](../../workflows/txt2img.json). +4. **ComfyUI Workflow Nodes** -> paste the contents of + [`../../workflows/txt2img.nodes.json`](../../workflows/txt2img.nodes.json). +5. **Default Model** -> the filename of the checkpoint you dropped in + step 4 (e.g. `v1-5-pruned-emaonly.safetensors`). +6. Save. + +For image editing (img2img), scroll to the **Image Editing** section in +the same panel and repeat with +[`../../workflows/img2img.json`](../../workflows/img2img.json) and +[`../../workflows/img2img.nodes.json`](../../workflows/img2img.nodes.json). + +## 7. Test it + +In any chat, click the image-generation button and prompt for an image. +Open WebUI submits the workflow to ComfyUI; the result drops back into +the chat when KSampler finishes. To test img2img, attach an image and +use the edit action. + +## Enabling Anubis (later) + +The `anubis-owui` service is defined in compose but no Caddy site block +points at it yet. To activate: + +1. Generate a key: `openssl rand -hex 32` and set `ANUBIS_OWUI_KEY` in `.env`. +2. In `Caddyfile`, change `reverse_proxy open-webui:8080` to + `reverse_proxy anubis-owui:8923` for the chat hostname. +3. `docker compose up -d`. + +## How the workflow node mappings work + +Open WebUI doesn't introspect the workflow graph. The `*.nodes.json` +files tell it which node IDs and input fields to overwrite when the user +provides a prompt, image, seed, etc. Each entry: + +```json +{ "type": "", "node_ids": [""], "key": "" } +``` + +Recognised `type` strings (per Open WebUI source): `model`, `prompt`, +`negative_prompt`, `width`, `height`, `n` (batch size), `steps`, `seed`, +and `image` (img2img / edit only). + +If you swap in a fancier workflow (SDXL, Flux, ControlNet, custom +samplers, NL masking via SAM nodes, etc.), update the matching +`*.nodes.json` so the node IDs and input keys still line up. + +## Common gotchas + +- **"Model not found" in Open WebUI's image panel.** ComfyUI lists + models from `/opt/comfyui/models/checkpoints/`. Confirm the file is + there and that **Default Model** matches the filename exactly + (including extension). +- **Out-of-memory on first generate.** Lower `IMAGE_SIZE` in compose + (e.g. `768x768`) or pass `--lowvram` / `--medvram` in the Dockerfile + CMD and rebuild. +- **Custom nodes need extra pip packages.** Install via ComfyUI-Manager + (it pip-installs into the container's venv). The `custom_nodes` + volume persists, but `/opt/venv` does not — so packages installed by + the manager survive container restarts only because the manager + re-installs them on boot. For permanent custom-node deps, add a + `RUN pip install …` to the Dockerfile and rebuild. +- **GPU not visible inside container.** Re-run the `nvidia-smi` test in + step 1. If it fails, the toolkit is misconfigured. +- **Caddy can't get a cert.** First-boot ACME requires DNS A/AAAA + records pointing at this host's public IP and ports 80+443 reachable + from the internet. Check `docker compose logs caddy` for the specific + challenge failure. diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 1f0e108..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,110 +0,0 @@ -# comfyui-nvidia — ComfyUI image-generation backend fronted by Open WebUI. -# -# Open WebUI provides the multi-user chat UI and a built-in image-generation -# panel that submits ComfyUI workflows directly. Two workflow templates ship in -# workflows/ — txt2img.json and img2img.json. Paste them (and the matching -# node-mapping JSON) into the Open WebUI admin panel under -# Settings -> Images. See SETUP.md. -# -# Single GPU, single host. Both services share the comfyui-net bridge so Open -# WebUI addresses ComfyUI by service name (http://comfyui:8188). - -name: comfyui-nvidia - -networks: - comfyui-net: - driver: bridge - -volumes: - comfyui-models: # /opt/comfyui/models (checkpoints, vae, loras, ...) - comfyui-custom-nodes: # /opt/comfyui/custom_nodes - comfyui-input: # /opt/comfyui/input (uploaded source images) - comfyui-output: # /opt/comfyui/output (generated images) - comfyui-user: # /opt/comfyui/user (saved workflows, settings) - open-webui-data: # Open WebUI accounts, chats, settings - -services: - comfyui: - # CI (.gitea/workflows/release.yml) builds and pushes this image on tag. - # `build:` is kept so `docker compose build` still works locally — useful - # when iterating on the Dockerfile without going through CI. - image: git.anomalous.dev/alphacentri/comfyui-nvidia:${COMFYUI_IMAGE_TAG:-latest} - pull_policy: always - build: - context: . - dockerfile: Dockerfile - container_name: comfyui - restart: unless-stopped - networks: [comfyui-net] - ports: - # Optional on the host — Open WebUI reaches comfyui:8188 over the bridge. - # Keep it published if you also want to use ComfyUI's native web UI at - # http://localhost:8188. - - "8188:8188" - volumes: - - comfyui-models:/opt/comfyui/models - - comfyui-custom-nodes:/opt/comfyui/custom_nodes - - comfyui-input:/opt/comfyui/input - - comfyui-output:/opt/comfyui/output - - comfyui-user:/opt/comfyui/user - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: all - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-sf", "http://127.0.0.1:8188/system_stats"] - interval: 30s - timeout: 5s - retries: 5 - start_period: 120s - - open-webui: - image: ghcr.io/open-webui/open-webui:main - container_name: open-webui - restart: unless-stopped - networks: [comfyui-net] - ports: - - "3000:8080" - extra_hosts: - # So Open WebUI can reach an Ollama instance running on the VM host. - # Drop this if you don't run Ollama on the host. - - "host.docker.internal:host-gateway" - depends_on: - comfyui: - condition: service_started - environment: - WEBUI_AUTH: "true" - ENABLE_SIGNUP: "true" - DEFAULT_USER_ROLE: "pending" - - # Public URL used for auth redirects and email-link generation. Set this - # to whatever your reverse proxy terminates. - WEBUI_URL: "${OPEN_WEBUI_URL:-http://localhost:3000}" - - # Cookie-signing key. Stable across restarts (rotating it logs every - # user out). Generate once: openssl rand -hex 32 - WEBUI_SECRET_KEY: "${OPEN_WEBUI_SECRET_KEY:-change-me-please}" - - # Optional: Ollama on the VM host for chat. Comment out if unused. - OLLAMA_BASE_URL: "http://host.docker.internal:11434" - - # Image generation via ComfyUI. The workflow JSON and node-mapping JSON - # are configured through the admin UI — see SETUP.md for the paste-in - # values. Only the engine selection and base URL are wired here so the - # admin panel comes up pre-pointed at the right backend. - ENABLE_IMAGE_GENERATION: "true" - IMAGE_GENERATION_ENGINE: "comfyui" - COMFYUI_BASE_URL: "http://comfyui:8188" - IMAGE_SIZE: "1024x1024" - IMAGE_STEPS: "20" - volumes: - - open-webui-data:/app/backend/data - healthcheck: - test: ["CMD", "curl", "-sf", "http://127.0.0.1:8080/health"] - interval: 30s - timeout: 5s - retries: 3 - start_period: 60s