@NodeSeek #28 你是指哪儿?
用户 ID 18291 · 当前名首次快照 2026-08-12 10:22:05 · 当前名始于 2026-08-12 10:22:05 · 原站主页: https://linux.sb/user/18291
共 10 楼
支持iCloud邮箱吗?
本文介绍如何把 acme.sh 已签发的 ZeroSSL ECC 证书自动复制到 Db2 服务器,再使用 OpenSSL 和 IBM GSKit 转换、导入 Db2 可识别的 KDB 密钥数据库,最后配置 Db2 TLS。
示例域名为
example.com,Db2 实例用户为db2inst1,服务器为db2.example.com(域名和IP地址皆可)。请按实际环境替换。
1. acme.sh 从 ZeroSSL 获取或续期证书;
2. SSH deploy hook 将服务器私钥、服务器证书和中间 CA 复制到 Db2 主机;
3. 远程执行 update-db2-cert.sh;
4. 脚本从系统信任库提取 USERTrust ECC 根证书;
5. OpenSSL 将私钥、服务器证书和中间证书打包为 PKCS#12;
6. GSKit 创建 KDB,导入个人证书及完整信任链;
7. 更新 Db2 Database Manager Configuration 并重启服务。
证书链通常为:
example.com 服务器证书
└─ ZeroSSL ECC DV SSL CA 2(中间 CA)
└─ USERTrust ECC Certification Authority(根 CA)KDB 中必须具备带私钥的服务器证书(personal certificate),以及中间 CA、根 CA(signer certificate)。
Db2 服务器需要安装 IBM Db2、GSKit、OpenSSL 和 trust(通常来自 p11-kit):
command -v db2
command -v gsk9certutil_64
command -v openssl
command -v trust创建证书目录和密码文件:
# 这里假定你创建db2实例是使用的用户的默认用户组是db2iadm1
sudo install -d -m 700 -o db2inst1 -g db2iadm1 /home/db2inst1/ssl
sudo -u db2inst1 sh -c 'umask 077; printf "%s\n" "替换为高强度密码" > /home/db2inst1/ssl/.kdb_password'建议私钥、KDB、stash 和密码文件权限为 600。.sth 虽不是明文密码文件,仍应按敏感凭据保护。
如果脚本通过 systemd 管理 Db2,需给 db2inst1 最小化 sudo 权限。先确认服务单元和 systemctl 路径,再通过 visudo 配置,例如:
db2inst1 ALL=(root) NOPASSWD: /usr/bin/systemctl stop db2inst1, /usr/bin/systemctl start db2inst1本文使用服务名 db2cs_db2inst1。确保 /etc/services 中有对应条目:
db2cs_db2inst1 50001/tcp验证并开放防火墙端口:
getent services db2cs_db2inst1将以下内容保存为 /home/db2inst1/ssl/update-db2-cert.sh:
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
SSL_DIR="/home/db2inst1/ssl"
KDB="$SSL_DIR/db2.kdb"
P12="$SSL_DIR/db2.p12"
ACME_DOMAIN_NAME="example.com" # 换成你自己的域名
ROOT_CA="$SSL_DIR/usertrust-ecc-root.pem"
KEY_FILE="$SSL_DIR/$ACME_DOMAIN_NAME.key.pem"
CERT_FILE="$SSL_DIR/$ACME_DOMAIN_NAME.pem"
CA_FILE="$SSL_DIR/ca.pem"
PASSWORD_FILE="$SSL_DIR/.kdb_password"
CERT_LABEL="CN=$ACME_DOMAIN_NAME"
DB2_SSL_SERVICE="db2cs_db2inst1"
SYSTEMD_UNIT="db2inst1"
# SSH 非交互会话通常不会自动加载 Db2 环境。
. /home/db2inst1/sqllib/db2profile
cd "$SSL_DIR"
TMP_DIR=""
cleanup() {
rm -f "$P12"
if [[ -n "$TMP_DIR" && -d "$TMP_DIR" ]]; then
rm -rf "$TMP_DIR"
fi
}
trap cleanup EXIT
for cmd in openssl trust gsk9certutil_64 db2; do
command -v "$cmd" >/dev/null 2>&1 || {
echo "错误:找不到命令 $cmd" >&2
exit 1
}
done
for file in "$KEY_FILE" "$CERT_FILE" "$CA_FILE" "$PASSWORD_FILE"; do
[[ -s "$file" ]] || {
echo "错误:文件不存在或为空:$file" >&2
exit 1
}
done
PASSWORD="$(<"$PASSWORD_FILE")"
[[ -n "$PASSWORD" ]] || { echo "错误:KDB 密码为空" >&2; exit 1; }
# 至少保证证书在未来 24 小时内仍有效。
openssl x509 -in "$CERT_FILE" -checkend 86400 -noout
# ECC/RSA 均适用:比较公钥摘要,确认私钥与证书匹配。
CERT_PUBKEY_HASH="$(openssl x509 -in "$CERT_FILE" -pubkey -noout | openssl pkey -pubin -outform DER | openssl sha256)"
KEY_PUBKEY_HASH="$(openssl pkey -in "$KEY_FILE" -pubout -outform DER | openssl sha256)"
[[ "$CERT_PUBKEY_HASH" == "$KEY_PUBKEY_HASH" ]] || {
echo "错误:证书与私钥不匹配" >&2
exit 1
}
echo "[1/10] 停止 Db2"
sudo systemctl stop "$SYSTEMD_UNIT" || true
echo "[2/10] 提取 USERTrust ECC 根 CA"
TMP_DIR="$(mktemp -d)"
trust extract --format=pem-bundle --filter=ca-anchors "$TMP_DIR/ca-bundle.pem"
awk -v dir="$TMP_DIR" '
/BEGIN CERTIFICATE/ { n++ }
n > 0 { print > (dir "/cert-" n ".pem") }
' "$TMP_DIR/ca-bundle.pem"
FOUND=0
for cert in "$TMP_DIR"/cert-*.pem; do
if openssl x509 -in "$cert" -subject -noout 2>/dev/null | grep -Fq "USERTrust ECC Certification Authority"; then
cp "$cert" "$ROOT_CA"
FOUND=1
break
fi
done
[[ "$FOUND" -eq 1 ]] || { echo "错误:未找到 USERTrust ECC 根 CA" >&2; exit 1; }
echo "[3/10] 删除旧 KDB"
rm -f "$KDB" "${KDB%.kdb}.rdb" "${KDB%.kdb}.crl" "${KDB%.kdb}.sth" "$P12"
echo "[4/10] 创建 KDB"
gsk9certutil_64 -keydb -create -db "$KDB" -pw "$PASSWORD" -type kdb -stash
echo "[5/10] 创建 PKCS#12"
openssl pkcs12 -export \
-inkey "$KEY_FILE" \
-in "$CERT_FILE" \
-certfile "$CA_FILE" \
-name "$CERT_LABEL" \
-out "$P12" \
-passout pass:"$PASSWORD"
echo "[6/10] 导入服务器证书"
gsk9certutil_64 -cert -import \
-file "$P12" -type p12 -pw "$PASSWORD" \
-target "$KDB" -target_type kdb -target_pw "$PASSWORD"
echo "[7/10] 导入中间 CA"
# PKCS#12 导入后中间证书可能已存在;如版本行为不同,可保留此显式导入。
if ! gsk9certutil_64 -cert -list -db "$KDB" -pw "$PASSWORD" | grep -Fq "ZeroSSL ECC DV SSL CA 2"; then
gsk9certutil_64 -cert -add -db "$KDB" -pw "$PASSWORD" \
-file "$CA_FILE" -label "ZeroSSL ECC DV SSL CA 2"
fi
echo "[8/10] 导入根 CA"
if ! gsk9certutil_64 -cert -list -db "$KDB" -pw "$PASSWORD" | grep -Fq "USERTrust ECC Certification Authority"; then
gsk9certutil_64 -cert -add -db "$KDB" -pw "$PASSWORD" \
-file "$ROOT_CA" -label "USERTrust ECC Certification Authority"
fi
echo "[9/10] 验证 KDB"
gsk9certutil_64 -cert -list -db "$KDB" -pw "$PASSWORD"
gsk9certutil_64 -cert -details -db "$KDB" -pw "$PASSWORD" -label "$CERT_LABEL"
chmod 600 "$KDB" "${KDB%.kdb}.sth" "$PASSWORD_FILE" "$KEY_FILE"
echo "[10/10] 配置 Db2 TLS"
db2 update dbm cfg using SSL_SVR_KEYDB "$KDB"
db2 update dbm cfg using SSL_SVR_STASH "${KDB%.kdb}.sth"
db2 update dbm cfg using SSL_SVR_LABEL "$CERT_LABEL"
db2 update dbm cfg using SSL_SVCENAME "$DB2_SSL_SERVICE"
db2set DB2COMM=TCPIP,SSL
sudo systemctl start "$SYSTEMD_UNIT"
echo "完成"db2无法使用fullchain证书公钥,必须将证书链层层拆开
赋予执行权限:
chown db2inst1:db2iadm1 /home/db2inst1/ssl/update-db2-cert.sh
chmod 700 /home/db2inst1/ssl/update-db2-cert.shShell 续行符
\后不能有空格。复制脚本时请勿把显示层的空格带到反斜杠后面。
首先在db2的证书存储路径先创建证书的同名文件占位,防止acme脚本失败(它会备份旧的证书,如果路径里找不到证书同名文件,会直接报错)
cd /home/db2inst1/ssl/
touch example.com.key.pem" # 将“example.com”换成你的域名
touch example.com.pem" # 将“example.com”换成你的域名接下来,推荐使用 multideploy 的 delployhook 来部署证书。
在 acme.sh 的配置存储路径中新建multideploy.ymltouch ~/.acme.sh/example.com_ecc/multideploy.yml 将“example.com”换成你的域名
示例节选:
version: "1.0"
services:
- name: "db2"
hook: "ssh"
environment:
DEPLOY_SSH_USER: "db2inst1"
DEPLOY_SSH_SERVER: "db2.example.com" # 将db2.example.com换成你的db2服务器的域名/IP地址
DEPLOY_SSH_KEYFILE: "/home/db2inst1/ssl/example.com.key.pem" # 将“example.com”换成你的域名
DEPLOY_SSH_CERTFILE: "/home/db2inst1/ssl/example.com.pem" # 将“example.com”换成你的域名
DEPLOY_SSH_CAFILE: "/home/db2inst1/ssl/ca.pem"
DEPLOY_SSH_REMOTE_CMD: "/home/db2inst1/ssl/update-db2-cert.sh"
DEPLOY_SSH_USE_SCP: "yes"脚本写完之后,部署证书:
acme.sh --deploy -d example.com --deploy-hook multideploy # 将“example.com”换成你的域名注意:原配置中的 DEPLOY_SSH_USE_SCP: "yes 缺少右侧双引号,会导致 YAML 解析失败。
这些路径表示证书和脚本的远端存储位置。acme.sh 在续期成功后复制证书并执行远程命令。首次自动部署前,建议先手工运行脚本验证 sudo、Db2 profile、GSKit 和服务名均正确。
SSL_SVR_LABEL 必须指向 KDB 中包含私钥的个人证书标签,而不是 CA 标签。PKCS#12 导入时标签可能来自 friendlyName,也可能被工具按证书主题生成。
脚本通过以下参数固定标签:
openssl pkcs12 -export -name "CN=example.com" ...随后 Db2 使用同一个值:
db2 update dbm cfg using SSL_SVR_LABEL "CN=example.com"务必以实际列表为准:
gsk9certutil_64 -cert -list -db /home/db2inst1/ssl/db2.kdb -stashed如果 GSKit 版本未保留 friendlyName,应把 CERT_LABEL 和 SSL_SVR_LABEL 改为 KDB 中实际显示的个人证书标签。
查看 Db2 配置:
db2 get dbm cfg | grep -i SSL
db2set -all | grep DB2COMM查看监听端口:
ss -lntp | grep 50001从客户端检查握手和证书链:
openssl s_client \
-connect db2.example.com:50001 \
-servername example.com # 换成你申请证书的域名\
-showcerts \
-verify_return_error </dev/null应重点确认:
example.com 证书;Verify return code: 0 (ok)。客户端连接时必须使用 SSL 端口并启用 SSL。不同 Db2 驱动的参数名称不同,常见形式为 security=SSL 或 sslConnection=true。
acme.sh 输出通常是 PEM:私钥与证书分别存储。Db2 服务端使用 GSKit KDB,服务器证书必须在 KDB 中与私钥关联。PKCS#12 是两者之间的通用中间格式,可同时携带私钥、服务器证书和附加证书链。
创建 KDB 时可能出现:
db2.kdb:密钥数据库;db2.sth:stash 文件,供 Db2 无人值守读取 KDB;db2.rdb:请求数据库;db2.crl:证书吊销相关数据库。SSL_SVR_STASH 必须指向实际生成的 db2.sth。
只有服务器证书和私钥时,GSKit 或客户端可能无法构建完整证书链。中间 CA 通常必须由服务端提供;根 CA主要用于建立信任。显式导入中间证书和根证书可减少不同 GSKit 版本、PKCS#12 导入行为和系统信任库差异造成的问题。
传统 RSA 脚本常比较 modulus,但 ECC 证书没有 RSA modulus。本文提取证书和私钥的 DER 公钥并计算 SHA-256,因而同时适用于 RSA 和 ECC。
本文每次续期都重建 KDB,优点是流程确定、不会残留旧标签;缺点是脚本失败期间服务可能处于停止状态,且会移除 KDB 中其他证书。若同一 KDB 还保存其他用途证书,应改为原位更新,或为 Db2 TLS 使用独立 KDB。
生产环境还可先构建临时 KDB,验证成功后再原子替换,以缩短中断并保留回滚能力。
db2: command not foundSSH 非交互会话没有加载实例环境。确认脚本包含:
. /home/db2inst1/sqllib/db2profile检查系统是否安装或更新 CA 信任库:
trust list | grep -A3 -B3 "USERTrust ECC"也可将经过校验的根证书固定放入 SSL 目录,但不要从不可信 URL 临时下载后直接导入。
SSL_SVR_LABEL 不存在列出 KDB,找到带私钥的个人证书标签,并同步更新 CERT_LABEL 与 Db2 配置。不要误用中间 CA 或根 CA 标签。
检查 /etc/services、SSL_SVCENAME、DB2COMM、防火墙和 Db2 日志;修改 Database Manager Configuration 后通常需要重启实例。
客户端连接名必须存在于证书 SAN。使用 IP 地址连接时,证书通常没有对应 IP SAN;应使用证书中的 DNS 名,并保证 DNS 或 hosts 解析正确。
当前脚本采取 fail-fast 策略。生产环境建议增加失败恢复 trap、保留上一套 KDB,或先在临时路径完成构建和验证,再切换文件并重启。
.kdb_password、私钥、KDB、stash 提交到 Git;DB2COMM=SSL,避免同时暴露明文 TCP 监听;完成以上配置后,后续 acme.sh 续期成功时即可自动复制新证书、重建 Db2 KDB 并使新证书生效。
@Sam.Altman #9 我是支付宝PockytShop应用买的美区礼品卡,实在不行美区官网也能买
@aiddup #5 以后,可能不止用这一家的,家里Mac mini过一两年可能会换,到时候不想东一个域名西一个IP地址的,先部署个网关(Cloudflare AI Gateway延迟太高),看看流程能不能跑通。我现在实际使用的是Open WebUI,后端接的LiteLLM。
services:
frontend:
image: ghcr.nju.edu.cn/open-webui/open-webui:main
restart: unless-stopped
pull_policy: always
hostname: openwebui
ports:
- "8080:8080"
environment:
WEBUI_URL: ${OPEN_WEBUI_URL}
ENABLE_SIGNUP: ${OPEN_WEBUI_ENABLE_SIGNUP}
ENABLE_INITIAL_ADMIN_SIGNUP: ${OPEN_WEBUI_ENABLE_INITIAL_ADMIN_SIGNUP}
WEBUI_ADMIN_EMAIL: ${OPEN_WEBUI_ADMIN_EMAIL}
WEBUI_ADMIN_PASSWORD: ${OPEN_WEBUI_ADMIN_PASSWORD}
WEBUI_ADMIN_NAME: ${OPEN_WEBUI_ADMIN_NAME}
ENABLE_LOGIN_FROM: ${OPEN_WEBUI_ENABLE_LOGIN_FROM}
ENABLE_PASSWORD_CHANGE_FORM: ${OPEN_WEBUI_ENABLE_PASSWORD_CHANGE_FORM}
ENABLE_PASSWORD_AUTH: ${OPEN_WEBUI_ENABLE_PASSWORD_AUTH}
DEFAULT_LOCALE: ${OPEN_WEBUI_DEFAULT_LOCALE}
DEFAULT_USER_ROLE: ${OPEN_WEBUI_DEFAULT_USER_ROLE}
ENABLE_CALENDAR: ${OPEN_WEBUI_ENABLE_CALENDAR}
ENABLE_CHANNELS: ${OPEN_WEBUI_ENABLE_CHANNELS}
CHANNEL_MODEL_RESPONSE_MODE: ${OPEN_WEBUI_CHANNEL_MODEL_RESPONSE_MODE}
ENABLE_FOLDERS: ${OPEN_WEBUI_ENABLE_FOLDERS}
ENABLE_AUTOMATIONS: ${OPEN_WEBUI_ENABLE_AUTOMATIONS}
ENABLE_SUBAGENTS: ${OPEN_WEBUI_ENABLE_SUBAGENTS}
THREAD_POOL_SIZE: ${OPEN_WEBUI_THREAD_POOL_SIZE}
SHOW_ADMIN_DETAILS: ${OPEN_WEBUI_SHOW_ADMIN_DETAILS}
ENV: ${OPEN_WEBUI_ENV}
WEBUI_NAME: ${OPEN_WEBUI_NAME}
PORT: ${OPEN_WEBUI_PORT}
DOCKER: True
OPENAI_API_BASE_URL: ${OPEN_WEBUI_OPENAI_API_BASE_URL:-http://gateway:4000/v1}
OPENAI_API_KEY: ${OPEN_WEBUI_OPENAI_API_KEY}
ENABLE_OPENAI_API_PASSTHROUGH: True
WEBUI_SECRET_KEY: ${OPEN_WEBUI_WEBUI_SECRET_KEY}
VECTOR_DB: ${OPEN_WEBUI_VECTOR_DB}
PGVECTOR_DB_URL: ${OPEN_WEBUI_DATABASE_URL}
PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH: ${OPEN_WEBUI_PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH}
PGVECTOR_CREATE_EXTENSION: ${OPEN_WEBUI_PGVECTOR_CREATE_EXTENSION}
PGVECTOR_INDEX_METHOD: ${OPEN_WEBUI_PGVECTOR_INDEX_METHOD}
RAG_EMBEDDING_ENGINE: ${OPEN_WEBUI_RAG_EMBEDDING_ENGINE}
RAG_EMBEDDING_MODEL: ${OPEN_WEBUI_RAG_EMBEDDING_MODEL}
RAG_OPENAI_API_BASE_URL: ${OPEN_WEBUI_OPENAI_API_BASE_URL:-http://gateway:4000/v1}
RAG_OPENAI_API_KEY: ${OPEN_WEBUI_OPENAI_API_KEY}
ENABLE_WEB_SEARCH: ${OPEN_WEBUI_ENABLE_WEB_SEARCH}
WEB_SEARCH_ENGINE: ${OPEN_WEBUI_WEB_SEARCH_ENGINE}
SEARXNG_QUERY_URL: ${OPEN_WEBUI_SEARXNG_QUERY_URL}
WEB_LOADER_ENGINE: ${OPEN_WEBUI_WEB_LOADER_ENGINE}
FIRECRAWL_API_BASE_URL: ${OPEN_WEBUI_FIRECRAWL_API_BASE_URL}
ENABLE_IMAGE_GENERATION: ${OPEN_WEBUI_ENABLE_IMAGE_GENERATION}
IMAGE_GENERATION_ENGINE: ${OPEN_WEBUI_IMAGE_GENERATION_ENGINE}
IMAGE_GENERATION_MODEL: ${OPEN_WEBUI_IMAGE_GENERATION_MODEL}
ENABLE_IMAGE_EDIT: ${OPEN_WEBUI_ENABLE_IMAGE_EDIT}
ENABLE_OAUTH: ${OPEN_WEBUI_ENABLE_OAUTH}
ENABLE_OAUTH_SIGNUP: ${OPEN_WEBUI_ENABLE_OAUTH_SIGNUP}
OAUTH_AUTO_REDIRECT: ${OPEN_WEBUI_OAUTH_AUTO_REDIRECT}
OAUTH_MERGE_ACCOUNTS_BY_EMAIL: ${OPEN_WEBUI_OAUTH_MERGE_ACCOUNTS_BY_EMAIL}
OAUTH_UPDATE_PICTURE_ON_LOGIN: ${OPEN_WEBUI_OAUTH_UPDATE_PICTURE_ON_LOGIN}
OAUTH_CLIENT_INFO_ENCRYPTION_KEY: ${OPEN_WEBUI_OAUTH_CLIENT_KEY}
OAUTH_SESSION_TOKEN_ENCRYPTION_KEY: ${OPEN_WEBUI_OAUTH_SESSION_KEY}
OAUTH_CLIENT_ID: ${OPEN_WEBUI_OAUTH_CLIENT_ID}
OAUTH_CLIENT_SECRET: ${OPEN_WEBUI_OAUTH_CLIENT_SECRET}
OPENID_PROVIDER_URL: ${OPEN_WEBUI_OPENID_PROVIDER_URL}
OPENID_REDIRECT_URI: ${OPEN_WEBUI_OPENID_REDIRECT_URI}
OAUTH_SCOPES: ${OPEN_WEBUI_OAUTH_SCOPES}
# OAUTH_CODE_CHALLENGE_METHOD: ${OPEN_WEBUI_OAUTH_CODE_CHALLENGE_METHOD}
OAUTH_PROVIDER_NAME: ${OPEN_WEBUI_OAUTH_PROVIDER_NAME}
STORAGE_PROVIDER: ${OPEN_WEBUI_STORAGE_PROVIDER}
STORAGE_LOCAL_CACHE: ${OPEN_WEBUI_STORAGE_LOCAL_CACHE}
S3_ACCESS_KEY_ID: ${OPEN_WEBUI_S3_ACCESS_KEY_ID}
S3_ADDRESSING_STYLE: ${OPEN_WEBUI_S3_ADDRESSING_STYLE}
S3_BUCKET_NAME: ${OPEN_WEBUI_S3_BUCKET_NAME}
S3_ENDPOINT_URL: ${OPEN_WEBUI_S3_ENDPOINT_URL}
S3_REGION_NAME: ${OPEN_WEBUI_S3_REGION_NAME}
S3_SECRET_ACCESS_KEY: ${OPEN_WEBUI_S3_SECRET_ACCESS_KEY}
DATABASE_URL: ${OPEN_WEBUI_DATABASE_URL}
REDIS_URL: ${OPEN_WEBUI_REDIS_URL}
# http_proxy: ${OPEN_WEBUI_HTTP_PROXY}
# https_proxy: ${OPEN_WEBUI_HTTPS_PROXY}
# no_proxy: ${OPEN_WEBUI_NO_PROXY}
PIP_OPTIONS: ${OPEN_WEBUI_PIP_OPTIONS}
PIP_PACKAGE_INDEX_OPTIONS: ${OPEN_WEBUI_PIP_PACKAGE_INDEX_OPTIONS}
volumes:
- ${OPEN_WEBUI_LOCAL_DATA_PATH}:/app/backend/data
networks:
- backend
gateway:
image: docker.litellm.ai/berriai/litellm-database:latest
restart: unless-stopped
pull_policy: always
hostname: litellm
ports:
- "4000:4000"
environment:
LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY}
LITELLM_SALT_KEY: ${LITELLM_SALT_KEY}
DATABASE_URL: ${LITELLM_DATABASE_URL}
SEARXNG_API_BASE: ${LITELLM_SEARXNG_API_BASE}
STORE_MODEL_IN_DB: "True"
networks:
- backend
upstream:
image: ${CLI_PROXY_IMAGE:-eceasy/cli-proxy-api:latest}
restart: unless-stopped
pull_policy: always
hostname: cliproxyapi
volumes:
- ${CLI_PROXY_CONFIG_PATH:-./config.yaml}:/CLIProxyAPI/config.yaml
- ${CLI_PROXY_AUTH_PATH:-./auths}:/root/.cli-proxy-api
- ${CLI_PROXY_LOG_PATH:-./logs}:/CLIProxyAPI/logs
- ${CLI_PROXY_PLUGIN_PATH:-./plugins}:/CLIProxyAPI/plugins
networks:
- backend
mcpo:
image: ghcr.nju.edu.cn/open-webui/mcpo:main
restart: unless-stopped
pull_policy: always
hostname: mcpo
command:
- "--config"
- "/config.json"
- "--host"
- "0.0.0.0"
- "--port"
- "8000"
volumes:
- ${MCPO_CONFIG_PATH}:/config.json:ro
networks:
- backend
networks:
backend:
driver: bridge我用的是原版的GPT Plus账号,docker compose跑CLIProxyAPI+LiteLLM,然后有LiteLLM提供的兼容API的。
就是对邮箱域名有限定,但好歹是能注册上了
支持更多邮箱,如iCloud、Outlook等。有类似于限流的问题吗?我看到了有关Gmail限流导致无法发送验证码的帖子