ヘッドレス版ComfyUI:サービスとして実行し、どこからでも利用する方法
- カテゴリ
- AIとローカルLLM
- 公開日
- 2026年7月11日
- 更新日
- 2026年9月16日
- 著者
- Jacob Lloyd — プロジェクト完了後、AIの支援を受けて執筆
- 読了時間
- 約15分で読めます
かんたんに言うと: 私の画像生成用コンピュータでは、ComfyUIが常にバックグラウンドで稼働しています。モニターはなく、誰もデスクトップにログインしていません。一行のコマンドを実行するだけで、プログラムを起動したり状態を確認したり、画像生成を依頼したりできます。また、暗号化されたプライベート接続を通じて、ノートパソコンやスマートフォンからComfyUIのフルインターフェースを開くことも可能です。私が作成した小さなプラグインにより、どのデバイスから保存されたワークフローも必ずそのコンピュータに保存されるため、データが散らばる心配もありません。
更新情報:2026年9月16日 現在、私は自身のPC上でこのComfyUI環境を運用していません。日常的な画像生成は遠隔地にあるGPUマシンから行っています。ただし、ご自身でヘッドレスモードでComfyUIを動かしたい場合でも、以下の手順は変更されておらず引き続き利用可能です。
前回の記事では、AMD製のミニPC上でComfyUIおよびZ-Image Turboを使い、1024ピクセルサイズの画像を約27秒で生成することに成功しました。今回はその続きとして、デスクトップセッションやターミナルの操作なしに常時稼働する装置へとこの環境を作り上げる手順を紹介します。こうすれば家の中のどの機器からでも利用でき、生成された画像や保存されたワークフローもすべてその一台のマシン内に留まります。
要約
- 概要: systemdのユーザーサービス下でヘッドレスモードで動作するComfyUI。小さなCLIツールで制御可能で、HTTP API経由でスクリプトから操作でき、さらにメッシュVPNとHTTPSを通じて他の機器からもアクセス可能です。
- 費用: 無料です。この仕組みに必要なVPNサービス(Tailscale個人版)も無料です。
- 準備物: ComfyUIが正常に動作する環境と、一晩程度の時間だけあれば十分です。
- 完成形: どのシェルからでも
comfyctl generate "..."を実行可能。ノートPCやスマホ上でフル機能のUIが利用でき、保存されたワークフローはサーバー上の同一フォルダ内にまとめられます。
完成形のイメージ
日常的な利用形態としては、大きく分けて3つのパターンがあり、いずれもそのマシンの前に座る必要はありません。
comfyctl status # server health + systemd state + newest output file
comfyctl generate "a foggy harbor at dawn, cinematic"
comfyctl logs 100
…あるいは別のマシン上のスクリプトからHTTP APIへプロンプトをPOSTしたり、家の中のノートPCのブラウザでフル機能のノードグラフUIを開いたりします。これらはすべてHTTPS経由かつVPN越しに行われ、生成結果はサーバーのディスクに保存されます。
なぜヘッドレスモードなのか
Web UIはワークフローを設計するためのものです。しかし200回目以降の実行には全く向いていません。一度ワークフローが確定すれば、求められるのは常時稼働し、どんなリクエストにも応答できる装置です。シェル上の単一コマンドでも、cronジョブでも、午前3時に新しいアバターを必要とするチャットボットでも構いません。これは私がローカルハードウェア上で公開用チャットボットを運用する際にも採用した仕組みそのものです。
ここでの「ヘッドレス」とは「UIが全く存在しない」という意味ではありません。サーバー側にはデスクトップセッションやブラウザは存在しませんが、UI自体はHTTP経由で他の機器から利用可能なままです。実際の処理はサーバー側で行われ、他の端末は単なる画面に過ぎません。
systemdユーザーサービス
サービスの構成は前回の記事と同様ですので簡潔に述べます。systemdのユーザーユニットは ~/.config/systemd/user/comfyui.service に配置します:
[Unit]
Description=ComfyUI server
After=network-online.target
[Service]
ExecStart=%h/comfy/start-comfyui.sh
WorkingDirectory=%h/comfy/ComfyUI
EnvironmentFile=-%h/comfy/comfy.env
Restart=on-failure
RestartSec=5
TimeoutStartSec=120
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user enable --now comfyui.service
loginctl enable-linger $USER # keep user services running with nobody logged in
最後の行がヘッドレス環境特有のポイントです。linger機能が無効な場合、ユーザーユニットは最後のセッション終了と同時に停止してしまいます。ヘッドレスマシンではこれが「即座に」を意味します。EnvironmentFile を使うことでポート番号や起動オプションを一箇所(comfy.env)で管理でき、他のツールが8188という固定値をコード内に書き込む必要がなくなります。
comfyctl風制御スクリプト
本来は systemctl でも動作しますが、薄いラッパースクリプトを用意するとまるで製品のように扱えます。私が作成したのは約100行のBashスクリプトで、名前は comfyctl です:
comfyctl start # systemctl start + poll /system_stats until healthy
comfyctl stop
comfyctl restart
comfyctl status # health + unit state + newest output PNG
comfyctl generate "<prompt>" [--seed N --steps 8 --width 1024 --out PATH]
comfyctl logs [N] # journalctl --user -u comfyui.service -n N
単に短いだけでなく使いやすさを実現しているポイントは以下の通りです:
- 「正常」とはプロセスが存在することを意味しない。
curl -sf http://127.0.0.1:$PORT/system_statsを60秒以内に応答が返るかどうかで判定します。systemd上で「active」状態でも、実際にはモデルサーバーがHTTPに応答していなければ未起動とみなされます。 - ポート番号はサービスと同じ環境変数ファイルから読み込むため、片方を変更しただけでツールが使えなくなる心配がありません。
generateコマンドは自動的にサーバーを起動する仕組みです。ヘルスチェックに失敗した場合はユニットを起動し、正常状態になるまで待機してからリクエストを送信します。呼び出し側はマシンが起動中かどうかを意識する必要がありません。statusではoutput/内の最新ファイル名を表示します。これにより「前回の生成は成功したか」を特別な操作なしに確認できます。
スクリプトからHTTP APIを利用する方法
UIで行えるすべての処理は同じHTTP API経由で実現され、基本的には3つのエンドポイントのみを使用します。ワークフローは単なるJSONデータであり(UI上の「Save (API format)」からエクスポート可能)、スクリプト側ではこれを読み込みプロンプトやシード値を書き換えて以下のように処理します:
import json, time, urllib.request
SERVER = "http://127.0.0.1:8188"
graph = json.load(open("workflow_api.json"))
graph["6"]["inputs"]["text"] = "a foggy harbor at dawn, cinematic" # your prompt node id
# 1. queue it
req = urllib.request.Request(f"{SERVER}/prompt",
data=json.dumps({"prompt": graph}).encode(),
headers={"Content-Type": "application/json"})
pid = json.load(urllib.request.urlopen(req))["prompt_id"]
# 2. poll history until done
while True:
hist = json.load(urllib.request.urlopen(f"{SERVER}/history/{pid}"))
if pid in hist: break
time.sleep(1)
# 3. fetch the image
img = hist[pid]["outputs"]["9"]["images"][0] # your SaveImage node id
url = f"{SERVER}/view?filename={img['filename']}&subfolder={img['subfolder']}&type={img['type']}"
open("result.png", "wb").write(urllib.request.urlopen(url).read())
標準ライブラリのみで実装されており、ComfyUI専用のクライアントパッケージやAPIキーは不要です。comfyctl generate もこの仕組みを利用しています。これにより、HTTPリクエストが送れる環境であればどこからでも画像生成が可能となり、そのマシンはインフラの一部として機能するようになります。
Workbenchプラグイン:ワークフローライブラリをサーバー上に集約
遠隔利用を始めた最初の週に問題が顕在化しました。ComfyUI標準の「Export」機能では、ワークフローのJSONデータがブラウザのダウンロード機能を通じて閲覧中の端末へ保存されてしまうのです。3台の異なる機器からUIを利用していると、ワークフローはそれぞれの端末の「Downloads」フォルダに散らばり、実際に処理を行っているマシン上には何も残りません。
そこで私は重力の方向を正すための小さなカスタムノード「Workbench」を作成しました。これは通常の custom_nodes プラグインであり、Python側ではComfyUI自身のWebサーバー上に複数のルートを登録し、JS側ではサイドバータブを追加します。このプラグインは2つの役割を果たします:
1. 作業フォルダへの保存/開き直し
サイドバーの「保存」ボタンを押すと、現在のグラフがプラグインにPOST送信され、ComfyUI側の標準的な user/default/workflows フォルダ内に サーバー上で書き込まれます。ファイル名は適切に処理され、そのフォルダ内のみに保存され、一時ファイルの作成および名前変更という形でアトミックな書き込みが行われます。また、上書きされる内容の履歴として .bak.json ファイルも随時生成されます。「開く」機能では、同じフォルダ内のファイル一覧が最新順に表示されます。
重要な点は:UIは遠隔地のブラウザ上で動作するものの、保存処理はサーバーのローカルディスクへ行われるということです。ノートパソコンから保存し、スマートフォンから開き直ったり、スクリプトから実行したりすることも可能です。GPUを搭載したマシン上に、一つのライブラリと一つのフォルダのみが存在するだけです。(私の環境では、そのフォルダは ~/comfy/workflows ディレクトリへシンボリックリンクされているため、バックアップも容易に取れます。)フロントエンド側は読み込まれたサーバーのオリジン相対パスでしか通信しないため、localhostでもプロキシ経由でも同じ挙動となり、各デバイスごとの設定は一切不要です。
2. 不足モデルの検出と許可済みサイトからのダウンロード
リモート利用におけるもう一つの問題点は、ワークフローを開いた際にそのマシンに存在しないモデルファイルが必要になるケースです。12GBものデータをスマホにダウンロードしてから再アップロードするのは明らかに不適切です。このプラグインは読み込まれたワークフローを、登録済みのすべてのモデルフォルダと照合し、不足しているモデルを一覧表示します。そして サーバー側で直接、適切な models/<folder> ディレクトリに ダウンロードを行います。ダウンロードデータは .part ファイルとしてストリーム配信され、HTTP Range機能により中断からの再開も可能です。さらに sha256による検証も選択でき、進捗状況はウェブソケットを通じてUIに反映されます。
「ブラウザがサーバーに対して任意のURLからファイルをディスクにダウンロードさせる」というのは非常に危険な挙動ですので、以下の制限が設けられています:
- HTTPSのみが利用可能で、ホスト名は
config.jsonに記載された許可リストと一致する必要があります(例:huggingface.co、civitai.com、*.hf.coのようなワイルドカード)。また すべてのリダイレクト先も同様に検証される点が重要です。なぜなら、どこへでもリダイレクトできる仕組みは許可リストを回避する典型的な手段だからです。 - ファイル名は適切に処理されたベース名のみとなり、許可された拡張子(
.safetensorsなど)で終わる必要があります。また保存先は登録済みのモデルフォルダのみであり、パストラバーサルは禁止されています。 - 既存ファイルは決して上書きされず、ダウンロード可能なサイズにも上限(デフォルト30GB)が設けられています。またダウンロードは一つずつ順番に実行されます。
安全なリモートアクセス:メッシュVPNとHTTPS
このマシン上のComfyUIは 127.0.0.1 のみでリスニングしています。これはハードコーディングされており、設定フラグなどは存在しません。ログインページもないため、インターネット上に公開しては絶対にいけませんし、単なるLAN内でも公開すべきではありません。最適な解決策はTailscaleのようなメッシュVPNです。各デバイスに暗号化された専用アドレスが割り当てられ、自分のアカウント外からは一切アクセスできません。またその serve 機能はローカルなHTTPSリバースプロキシとしても機能します:
tailscale serve --bg --https=8443 http://127.0.0.1:8188
これにより https://<your-machine>.<your-tailnet>.ts.net:8443 から、実際に自動生成されたTLS証明書を用いて、自分のデバイスのみに完全なUIが提供されます。ComfyUI自体は引き続きlocalhostからの通信しか受け付けません。つまりプロキシが唯一の入り口となるわけです。
ここでのHTTPSは単なる配慮事項ではありません。ブラウザは非localhost由来の平文HTTP接続に対して、クリップボードやウェブソケットの挙動などを次第に制限するようになっています。またプロンプトや画像もネットワーク上で送信されるため、HTTPSが不可欠です。メッシュVPNを利用すればドメインを所有したりポートを開放したりすることなく、実用的な証明書を手に入れられます。ちなみに実用上の注意点としては、マシンのDNS名で接続するべきであり、単なるVPN IPではいけません。TLS証明書はその名前向けに発行されるため、IPアドレスでは証明書検証に失敗してしまうからです。
注意点
- リモート接続時のみ発生する403エラーは認証の問題ではなくオリジンチェックによるものです。 ComfyUIのサーバーミドルウェアは状態変更を伴うリクエストにおいて
Origin/Hostなどのヘッダーを検証します。一部のプロキシ設定では期待される値と一致しないヘッダーが転送されてしまい、これが原因でエラーが発生する場合があります(私も別ツールを接続する際にSec-Fetch-Site関連の403エラーに直面しました)。プロキシの転送ヘッダーを修正するか、ComfyUIのCORS設定(--enable-cors-header)で信頼できるオリジンのみを指定してください。決して*にしてはいけません。 - VPNのホスト名を使ってください。IPアドレスではいけません。 メッシュVPN経由のHTTPSは名前ごとに証明書が発行される仕組みです。単なるIPアドレスで接続するとTLSエラーが発生し、サーバーが故障しているように見えてしまいます。
- カスタムノード用フロントエンドはオリジン相対パスを使う必要があります。 プラグインのJavaScript内で
http://127.0.0.1:8188/...のようにハードコーディングされたパスは、マシン上では問題なく動作しますがプロキシ越しには正常に機能しません。ComfyUIのapi.fetchApi()や相対パスを利用してください。 - プロキシ経由でのウェブソケット接続は切断される可能性があります。 ダウンロード進捗情報もウェブソケット経由で送信されますが、プロキシの背後では時折静かに接続が切れることがあります。そのため Workbenchでは代替手段としてポーリング処理も実装されています。設計時にはこの点を考慮してください。
loginctl enable-lingerを行わないとログアウト時に「サービス」が停止してしまいます。- 「ユニットがアクティブ状態」=「サーバーが稼働中」とは限りません。
- ダウンロード許可リストは厳格に管理してください。
- 絶対にインターネット向けにポートフォワーディングしてはいけません。 認証機能がなく、任意のワークフロー実行が可能であり、ダウンローダーがあればディスクへの書き込みも可能です。メッシュVPN以外の手段はあり得ません。
前回の記事では画像生成が可能なコンピュータを紹介しましたが、本稿で紹介するのはそれよりも優れた存在です。つまり、私が持つすべてのデバイスやスクリプトから利用できる静かなマシンであり、生成されたすべてのデータを一箇所に保管してくれるのです。
関連記事:AMD(ROCm)上でのローカルAI画像生成:ComfyUIとZ-Image Turbo · 自前のハードウェア上で公開用チャットボットを構築する · StudioForge:LM Studioに代わるGPU専用LLMサーバー · 1台のミニPCで運用する小規模AIエージェント群:私のOpenClawスタック