Developer技术博客 DevEngineer:林建有

Nginx搭建ComfyUI API

2026-02-02

ComfyUI API 接口搭建,以便UI程序调用工作流生成图片等。

一、存在问题:

本地安装的ComfyUI运行后,都未有授权或认证的任何限制,若添加自定义域名自己暴露映射8188端口的comfyUI API,面临着重大安全隐患:

  • 任何人可以:
    • 调接口跑图

    • 消耗你 GPU

    • 跑满显存、OOM、拖垮机器

  • Prompt / Workflow 可被读取
    • 包含你私有 workflow

    • 模型路径、节点配置

  • ComfyUI 支持文件上传
    • 可被当成“隐形文件中转站”
  • 自动化扫描会很快打到
    • Shodan / ZoomEye 会扫到

    • 几小时内就有人用你 GPU

二、⚠️ 正确姿势:ComfyUI 永远不要直接暴露公网

🥇 方案一:反向代理 + 强认证(生产推荐)

架构 公网 ↓ Nginx / Caddy(认证) ↓ ComfyUI(仅监听 127.0.0.1)

ComfyUI 启动方式(关键) python main.py –listen 127.0.0.1 –port 8188

❌ 不要 0.0.0.0

Nginx + Basic Auth(最快) 1️⃣ 创建密码 sudo apt install apache2-utils htpasswd -c /etc/nginx/comfy.htpasswd comfyuser

2️⃣ Nginx 配置 server { server_name comfy.example.com;

auth_basic "ComfyUI";
auth_basic_user_file /etc/nginx/comfy.htpasswd;

location / {
    proxy_pass http://127.0.0.1:8188;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

}

✅ 访问时必须用户名密码 ✅ API / Web 都受保护

🥈 方案二:IP 白名单(只给自己/公司)

location / { allow 1.2.3.4; allow 5.6.7.8; deny all;

proxy_pass http://127.0.0.1:8188;

}

📌 适合:

固定办公 IP

内部系统调用

安装Nginx

1、Docker方式

2、直接linux里安装

1. Docker方式

  • 创建一个docker目录下的compose文件docker-compose.yml
services:
  nginx:
    image: nginx:alpine
    container_name: nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./nginx/auth:/etc/nginx/auth:ro
      - ./nginx/logs:/var/log/nginx
  • 在docker目录下创建对应的volumes挂载目录
.
├── docker-compose.yml
└── nginx
    ├── auth
    │   └── comfy.htpasswd
    ├── conf.d
    │   └── comfy.conf
    ├── html
    ├── logs
    │   ├── access.log
    │   └── error.log
    └── nginx.conf
  • 创建登录用户授权信息 用户名是:comfyuser,执行命令后会提示输入密码,并后面会保存到/home/user/comfy/ComfyUI/docker/nginx/auth
docker run --rm -it \
  -v /home/user/comfy/ComfyUI/docker/nginx/auth:/auth \
  httpd:alpine \
  htpasswd -c /auth/comfy.htpasswd comfyuser


这是真正干活的命令 👇

htpasswd -c /auth/comfy.htpasswd comfyuser

拆开看: | 部分 | 含义 | | ———————- | —————— | | htpasswd | 创建 / 修改密码文件 | | -c | 创建新文件(⚠️只第一次用) | | /auth/comfy.htpasswd | 密码文件路径 | | comfyuser | 用户名 |

执行后你会看到:

New password:
Re-type new password:

👉 输入密码(不显示) 👉 再输入一次确认

  • 配置comfy.conf
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name gen.okforks.com;

    auth_basic "ComfyUI";
    auth_basic_user_file /etc/nginx/auth/comfy.htpasswd;

    location / {
        proxy_pass http://host.docker.internal:8188;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # 关键:把 Basic Auth 透传给后端(ComfyUI 插件有时需要)
        proxy_set_header Authorization $http_authorization;

        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}
  • 配置nginx.conf
user  nginx;
worker_processes auto;

events {
worker_connections 1024;
}

http {
include       /etc/nginx/mime.types;
default_type  application/octet-stream;

sendfile        on;
keepalive_timeout  65;

include /etc/nginx/conf.d/*.conf;
}
  • 启动docker nginx,在docker目录下包含了docker-compose.yml执行如下命令启动并在后台运行(-d表示后台运行)。
docker compose up -d
#或
#docker compose -f docker-compose.yml up -d

ComfyUI 创建linux自启动后台服务

/etc/systemd/system/目录下创建一个名叫coomfyui.service的服务文件

sudo nano /etc/systemd/system/coomfyui.service

comfyui.service内容:

[Unit]
Description=ComfyUI
After=network.target

[Service]
Type=simple
User=user
WorkingDirectory=/home/user/comfy/ComfyUI
ExecStart=/home/user/comfy/ComfyUI/.venv/bin/python /home/user/comfy/ComfyUI/main.py --listen 0.0.0.0 --port 8188
Restart=always
RestartSec=3
Environment=ENV=prod

[Install]
WantedBy=multi-user.target

:::注意 此处的--listen 0.0.0.0如何设置成localhost或127.0.0.1的话,前面的docker nginx的host.docker.internal网络就会访问不到8188的程序接口了。需要设置为暴露0.0.0.0给docker,但不要暴露到公网里。

创建comfy.service后启动并查看状态,

sudo systemctl daemon-reload
sudo systemctl start comfyui
sudo systemctl status comfyui

允许开机自启动

sudo systemctl enable comfyui

Nginx更安全的授权配置

只允许带 token 的请求

server {
    listen 80;
    server_name gen.okforks.com;

    # Web 界面依然用 Basic Auth
    auth_basic "ComfyUI";
    auth_basic_user_file /etc/nginx/auth/comfy.htpasswd;

    location /api/ {
        # 只允许带 token 的请求
        if ($http_x_api_key != "你的密钥") {
            return 401;
        }

        proxy_pass http://host.docker.internal:8188;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location / {
        proxy_pass http://host.docker.internal:8188;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Authorization $http_authorization;
    }
}

加密传输token请求:HTTPS + Token

  • Nginx 端启用 HTTPS(推荐 Let’s Encrypt)
server {
    listen 443 ssl;
    server_name gen.okforks.com;

    ssl_certificate /etc/letsencrypt/live/gen.okforks.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gen.okforks.com/privkey.pem;

    location /api/ {
        if ($http_x_api_key != "你的密钥") { return 401; }
        proxy_pass http://host.docker.internal:8188;
        ...
    }
}
  • 客户端调用 API 使用 HTTPS
curl -k -H "X-API-KEY: my-secret-token" https://gen.okforks.com/api/prompt -d '{"text":"Hello"}'
  • 密钥token生成方式:
openssl rand -hex 32
#示例:84555f12f63922ace2ca8d44a8b8c6f6e1e714e87b74d7dbd18600bc4b70ef61
  • Let’s Encrypt生成ssl证书

docker-compose.yml需要修改

services:
  nginx:
    image: nginx:alpine
    container_name: nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./nginx/auth:/etc/nginx/auth:ro
      - ./nginx/logs:/var/log/nginx
      - ./nginx/certbot/www:/var/www/certbot
      - ./nginx/certbot/conf:/etc/letsencrypt
    command: ["/bin/sh", "-c", "while :; do sleep 6h & wait $${!}; certbot renew --webroot -w /var/www/certbot; done & nginx -g 'daemon off;'"]

  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - ./nginx/certbot/www:/var/www/certbot
      - ./nginx/certbot/conf:/etc/letsencrypt
    entrypoint: >
      sh -c "certbot certonly --webroot --webroot-path /var/www/certbot --agree-tos --email jaysen.lin@foxmail.com -d gen.okforks.com --non-interactive && exit 0"
    extra_hosts:
      - "host.docker.internal:host-gateway"

先创建一下cert的证书;: 前题是gen.okforks.com需要先解析到宿主机,前面有让Nginx代理到80端口。 此时需要添加一个location的Nginx的配置comfy.conf

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name gen.okforks.com;

    auth_basic "ComfyUI";
    auth_basic_user_file /etc/nginx/auth/comfy.htpasswd;

    #证书自动生成验证的地址
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

然后再执行,先生成Let’s Encrypt的证书。

 docker compose run --rm certbot

然后再修改comfy.conf的解析路径配置,添加ssl支持

map $http_upgrade $connection_upgrade{
    default upgrade;
    ''      close;
}
map $http_x_api_key $api_allowed {
    default 0;
    "你的API key token" 1;
}
server {
    listen 80;
    server_name gen.okforks.com;
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    # 所有访问自动跳转到 HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    listen 443 ssl;
    server_name gen.okforks.com;

    # Web 界面依然用 Basic Auth
    auth_basic "ComfyUI";
    auth_basic_user_file /etc/nginx/auth/comfy.htpasswd;

    #启用https证书
    ssl_certificate /etc/letsencrypt/live/gen.okforks.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gen.okforks.com/privkey.pem;

    location /api/ {
        # 只允许带 token 的请求
        if ($api_allowed = 0) {
            return 401;
        }

        proxy_pass http://host.docker.internal:8188;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }

    location / {
        proxy_pass http://host.docker.internal:8188;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # 关键:把 Basic Auth 透传给后端(ComfyUI 插件有时需要)
        proxy_set_header Authorization $http_authorization;

        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

但此方法在有CloudFlared内网穿透就不管用了。 cloudflared本身有TSL功能,外网有https,所有Nginx不需要那么麻烦的设置证书了。 化繁为简:

# 映射 WebSocket Upgrade
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# API Key 授权
map $http_x_api_key $api_allowed {
    default 0;
    "你的API key" 1;
}

server {
    listen 80;
    server_name localhost;

    # Web UI Basic Auth
    auth_basic "ComfyUI";
    auth_basic_user_file /etc/nginx/auth/comfy.htpasswd;

    # **先定义 /api/**,保证不会被 / 覆盖
    location /api/ {
        # API Key 验证
        if ($api_allowed = 0) {
            return 401;
        }

        proxy_pass http://host.docker.internal:8188;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }

    # Web UI 和其他路径
    location / {
        proxy_pass http://host.docker.internal:8188;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # 透传 Basic Auth
        proxy_set_header Authorization $http_authorization;

        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

Comments

Content