The qwen_image21 detection check and GGUF node arch list patch are applied by a startup wrapper (comfyui-start.sh) that runs before ComfyUI starts. The patch script and wrapper are baked into the image so they survive container recreations. The quadlet's Exec now points at the wrapper instead of main.py directly.
71 lines
3.0 KiB
INI
71 lines
3.0 KiB
INI
# Quadlet unit: ComfyUI (rootless, boot-persistent).
|
|
#
|
|
# Install path on dankclaw: ~/.config/containers/systemd/comfyui.container
|
|
# Unit name: comfyui.service (container name: comfyui)
|
|
#
|
|
# WHY THIS FILE EXISTS. ComfyUI ran from `dankclaw/compose.yaml` through a
|
|
# hand-written `~/.config/systemd/user/comfyui.service` that called
|
|
# `podman compose up -d`. Its container was created 2026-09-15 14:12, BEFORE the
|
|
# GPU declarations were added to the compose service, and `restart:
|
|
# unless-stopped` then kept restarting that stale container — so it started
|
|
# without /dev/kfd, without /dev/dri and without keep-groups, died on
|
|
# `RuntimeError: No HIP GPUs are available`, and had restarted 9,146 times when
|
|
# this was found. A recreate via compose would have fixed the container; a unit
|
|
# fixes the class: one owner per container name, repo-tracked, boot-persistent
|
|
# through the generator.
|
|
#
|
|
# GPU ACCESS. /dev/kfd + /dev/dri plus keep-groups. A literal `render` group
|
|
# entry cannot work under rootless Podman (the group name does not resolve
|
|
# inside the user namespace), and the companion udev rule
|
|
# (dankclaw/udev/99-comfyui-gpu-access.rules) keeps those nodes MODE 0666 so a
|
|
# user-unit spawn — which carries no supplementary groups — can still open them.
|
|
# Both halves are asserted by tests/comfyui_rocm.bats.
|
|
#
|
|
# EXPOSURE. LAN-reachable, no auth. ComfyUI has no authentication and executes
|
|
# arbitrary node graphs. It is internal-only (no public vhost, no guard chain);
|
|
# it is reached on the LAN via the Pi-hole DNS record
|
|
# (comfyui.franksdank.cloud -> 192.168.0.143, in dankclaw/pihole/addn-hosts),
|
|
# which resolves to this host's IP — so the bind is widened from loopback to
|
|
# 0.0.0.0:8188. The homepage admin card links to that URL and probes
|
|
# 127.0.0.1:8188.
|
|
#
|
|
# DATA. Models, input, output and custom_nodes live under
|
|
# /home/dank/comfyui-data (host state, not in the repo).
|
|
[Unit]
|
|
Description=ComfyUI (gfx1151 ROCm image generation)
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Container]
|
|
ContainerName=comfyui
|
|
Image=localhost/comfyui-rocm:gfx1151
|
|
Pull=never
|
|
Network=dankclaw_default
|
|
PublishPort=0.0.0.0:8188:8188
|
|
AddDevice=/dev/kfd
|
|
AddDevice=/dev/dri
|
|
GroupAdd=keep-groups
|
|
Volume=/home/dank/comfyui-data/models:/opt/ComfyUI/models
|
|
Volume=/home/dank/comfyui-data/input:/opt/ComfyUI/input
|
|
Volume=/home/dank/comfyui-data/output:/opt/ComfyUI/output
|
|
Volume=/home/dank/comfyui-data/custom_nodes:/opt/ComfyUI/custom_nodes
|
|
Volume=/home/dank/serverAppConfigs/dankclaw/comfyui/comfyui-healthcheck.py:/usr/local/bin/comfyui-healthcheck.py:ro
|
|
Exec=/opt/ComfyUI/comfyui-start.sh
|
|
# The probe lives in a file because the podman 5.x v1 generator splits
|
|
# HealthCmd on spaces into an argv array; an inline `python3 -c "..."` becomes
|
|
# a puzzle of quoting that fails silently.
|
|
HealthCmd=python3 /usr/local/bin/comfyui-healthcheck.py
|
|
HealthInterval=30s
|
|
HealthTimeout=10s
|
|
HealthRetries=3
|
|
# First start loads torch and the node graph; give it room before the probe
|
|
# counts against it.
|
|
HealthStartPeriod=300s
|
|
|
|
[Service]
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=default.target
|