Files
oci-portal/README.md
T
wangdefa 0a86b5a291
CI / test (push) Successful in 32s
Release / release (push) Successful in 1m4s
AI网关新增TTS/重排/审核端点,xAI工具扩展,swagger修缺
- 新端点 /ai/v1/audio/speech(xai.grok-tts)、/rerank(cohere.rerank-v4)、/moderations(OCI Guardrails)
- Responses 放行 code_interpreter 与远程 mcp 工具,web_search/x_search 解除仅非流式限制
- 模型能力映射扩展:TEXT_RERANK→RERANK、TEXT_TO_AUDIO→TTS
- AI 网关文档独立 docs/ai-gateway.md,字段兼容矩阵只列支持项;README 精简引用
- swagger 修缺:135 处响应注解具体化,RawMessage/联合类型统一渲染 AnyJSON,overrides 迁至 docs/.swaggo
- CHANGELOG 0.4.0,版本段不再记日期;DASH_VERSION v0.4.0
2026-07-13 20:17:06 +08:00

12 KiB
Raw Permalink Blame History

OCI Portal logo

OCI Portal

自托管的 OCI 多租户管理面板与 GenAI 兼容网关

Release Go Docker License

快速开始 · 核心能力 · 生产部署 · AI 网关 · 开发

OCI Portal 将多份 OCI API Key、云资源、自动化任务、审计事件和 OCI GenAI 渠道集中到一个管理界面。Vue 前端通过 go:embed 嵌入 Go 服务,Release 以单个二进制和多架构容器镜像交付。

本仓库为后端与发行仓库;前端源码位于 oci-portal-dash

界面预览

总览 登录
总览 登录
租户 任务
租户 任务
AI 网关 通知设置
AI 网关 通知设置

核心能力

  • 租户与区域:集中管理多份 OCI API Key,支持分组、批量测活、账户画像、订阅区域缓存与区域切换;私钥和口令使用 AES-256-GCM 加密落库
  • 计算、网络与存储:实例创建与电源操作、公网 IP、IPv6、VNIC、串行控制台连接,VCN / 子网 / 安全列表,引导卷与块存储挂载,限额和成本查询
  • 自动化任务:抢机、租户测活、成本同步、AI 渠道探测四类 cron 任务,提供执行日志、重叠执行防护、熔断与结果通知
  • 网页控制台:浏览器内使用 xterm 串行终端和 noVNC,通过 OCI 控制台连接建立两跳 SSH 隧道
  • 身份与审计IAM 用户、MFA、API Key、密码策略、SAML 身份提供商、通知收件人和多 Identity Domain 管理;OCI Audit 事件可经 Service Connector Hub 与 Notifications 回传,关键事件按类别通过「云端事件」通知推送
  • 通知与安全Telegram、Webhook、ntfy、Bark、SMTP 五类渠道;JWT、bcrypt、TOTP、OIDC / GitHub 登录、登录锁定、IP 限速、会话撤销和系统操作审计
  • AI 网关:提供 OpenAI Responses、Chat Completions、Embeddings 与 Anthropic Messages 兼容接口,支持渠道分组、加权路由、熔断探测、模型黑白名单、密钥管理和调用日志

运行形态

浏览器 / API 客户端
        │
        ▼
┌──────────────────── OCI Portal 单个 Go 进程 ────────────────────┐
│  Vue 3 静态资源(go:embed                                     │
│  /api/v1  → Gin → Service → OCI SDK                            │
│  /ai/v1   → 兼容转换与路由 → OCI Generative AI                 │
│  GORM      → SQLite(默认)/ MySQL / PostgreSQLexperimental │
└─────────────────────────────────────────────────────────────────┘

默认推荐 SQLite 单实例部署。MySQL 和 PostgreSQL 适配仍属 experimental,不应据此推断服务支持多副本并发运行。

快速开始

Docker Compose(推荐)

前置条件:Docker、Docker Compose v2、OpenSSL。

  1. 克隆仓库并生成一份需要长期保存的 .env

    git clone https://github.com/wangdefaa/oci-portal.git
    cd oci-portal
    
    umask 077
    printf 'DATA_KEY=%s\nJWT_SECRET=%s\nADMIN_PASSWORD=%s\n' \
      "$(openssl rand -hex 32)" \
      "$(openssl rand -hex 32)" \
      "$(openssl rand -base64 24)" > .env
    chmod 600 .env
    
  2. 准备数据目录并启动:

    mkdir -p data
    
    # Linux bind mount 需要让镜像内的 nonroot 用户(uid 65532)可写。
    sudo chown 65532:65532 data
    
    docker compose up -d
    docker compose ps
    
  3. 查看初始管理员密码并登录:

    grep '^ADMIN_PASSWORD=' .env
    

    访问 http://127.0.0.1:18888,默认用户名为 admin

DATA_KEY 用于解密数据库中的 OCI 私钥、口令和渠道凭据。它只能生成一次并持续复用;丢失或更换后,已有密文无法恢复。请将 .envdata/oci-portal.db 一起备份。

二进制运行

Release 提供 Linux amd64 / arm64 二进制。以下以 amd64 为例;arm64 主机将文件名中的 amd64 替换为 arm64

curl -fLO https://github.com/wangdefaa/oci-portal/releases/latest/download/oci-portal-server-linux-amd64
chmod +x oci-portal-server-linux-amd64

# 复用上文生成并妥善保存的 .env。
set -a
. ./.env
set +a

./oci-portal-server-linux-amd64

默认访问地址为 http://localhost:8080ADMIN_PASSWORD 只在数据库中没有用户时创建初始管理员,后续启动不会用它重置密码。

源码构建

源码构建要求 Go 1.26.5、curlunzipsha256sum。仓库只保留前端占位页,编译完整单文件前应下载 DASH_VERSION 指定的前端产物并校验:

DASH_TAG="$(tr -d '\r\n' < DASH_VERSION)"
DASH_BASE="https://github.com/wangdefaa/oci-portal-dash/releases/download/${DASH_TAG}"

curl -fL -o dist.zip "${DASH_BASE}/dist.zip"
curl -fL -o dist.zip.sha256 "${DASH_BASE}/dist.zip.sha256"
sha256sum -c dist.zip.sha256

rm -rf internal/webui/dist
mkdir -p internal/webui/dist
unzip -q dist.zip -d internal/webui/dist

CGO_ENABLED=0 go build -trimpath -o bin/oci-portal-server ./cmd/server

本地构建显示 dev 版本;Release 工作流会注入正式版本和构建时间。internal/webui/dist 中的真实前端产物不应提交到仓库。

生产部署

服务本身只提供 HTTP。除本机试用外,应保持服务仅监听回环地址或容器内部网络,并由 TLS 反向代理提供 HTTPS;否则管理员密码、JWT、AI 密钥和租户凭据会经明文连接传输。

Caddy

portal.example.com {
    reverse_proxy 127.0.0.1:18888
}

Caddy 会自动处理 WebSocket。使用 nginx、Traefik 或其他反向代理时,还需要满足:

  • 为串行终端和 VNC 转发 WebSocket Upgrade 头
  • 为 AI 流式响应和控制台连接设置较长的读写超时,建议 1h
  • 整站请求体上限至少为 10MB;后端会继续限制面板 API 为 1MB、AI 网关为 10MB
  • 将面板内「设置 → 安全 → 真实 IP 请求头」配置为反向代理实际写入的头;系统审计、登录锁定和 IP 限速依赖它
  • 配置 PUBLIC_URL 或面板地址,供 OAuth 回调和 OCI 日志回传链路使用
nginx 最小示例
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}

server {
    listen 443 ssl;
    server_name portal.example.com;

    ssl_certificate     /etc/nginx/certs/portal.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/portal.example.com.key;

    client_max_body_size 10m;

    location / {
        proxy_pass http://127.0.0.1:18888;
        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-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 1h;
        proxy_send_timeout 1h;
    }
}

若前端静态文件与后端分离部署,/api/*/ai/* 必须代理到后端,其余路径由 SPA 静态服务处理并回退到 index.html。Traefik 通过容器网络连接时应直达容器端口 8080,无需暴露宿主机端口。

AI 网关

面板内置 OpenAI / Anthropic 兼容的 GenAI 网关:独立密钥鉴权(Authorization: Bearer sk-...x-api-key),支持渠道分组、加权路由、熔断探测、模型黑白名单、内容日志与调用日志。

端点 定位 流式
POST /ai/v1/responses OpenAI Responses,无状态主接口(xAI 服务端工具 / MCP) SSE
POST /ai/v1/chat/completions OpenAI Chat Completions 兼容层 SSE
POST /ai/v1/messages Anthropic Messages 转换层 SSE
POST /ai/v1/embeddings OpenAI Embeddings
POST /ai/v1/audio/speech 文本转语音(xAI Voice
POST /ai/v1/rerank 文档重排(Cohere Rerank
POST /ai/v1/moderations 内容审核(OCI Guardrails
GET /ai/v1/models 当前密钥可见的模型列表

协议兼容边界、已知上游限制与逐字段兼容矩阵见 AI 网关文档

API 与配置

API 文档

路径 鉴权 用途
/api/v1/* 登录返回的 JWT Bearer Token 面板管理 API
/ai/v1/* AI 网关密钥 OpenAI / Anthropic 兼容接口
/api/v1/webhooks/oci-logs/:secret URL 中的独立回传密钥 OCI Notifications 日志回传

OpenAPI 文件随仓库维护:docs/swagger.yaml · docs/swagger.json

运行进程时设置 SWAGGER=1 可开放 /swagger/index.html。Swagger 默认关闭,生产环境建议仅在受控网络内按需开启。接口注释变更后必须重新生成 OpenAPI。

环境变量

变量 必填 默认值 说明
DATA_KEY 敏感字段加密主密钥;必须持久保存,不能随意轮换
JWT_SECRET JWT 签名密钥;更换会使已有登录令牌失效
ADMIN_USERNAME admin 初始管理员用户名
ADMIN_PASSWORD 首次启动 仅在数据库无用户时创建管理员,不会重置已有密码
ADDR :8080 HTTP 监听地址
DB_DRIVER sqlite sqlite / mysql / postgres;后两者为 experimental
DB_PATH SQLite oci-portal.db SQLite 文件路径
DB_DSN 外部数据库 MySQL 需 parseTime=True;不要在日志或文档中暴露凭据
PUBLIC_URL 面板公网基址,作为 OAuth 回调和日志回传引导的回退值
TZ 系统时区 cron 表达式的解释时区;容器示例使用 Asia/Shanghai
HTTP_PROXY / HTTPS_PROXY / NO_PROXY Go 标准出站代理变量;面板内显式代理配置优先用于对应业务
SWAGGER 关闭 设为 1 时开放 Swagger UI
GIN_MODE release debug / release

升级与备份

  • 升级前同时备份 .env 和数据库;SQLite Compose 部署的数据文件为 data/oci-portal.db
  • 保持 DATA_KEY 不变;只恢复数据库而没有原密钥,敏感字段无法解密
  • 服务启动时会自动执行数据库迁移;跨版本升级前先阅读 CHANGELOG
  • Compose 部署使用 docker compose pull && docker compose up -d 更新镜像
  • OCI API Key 应遵循最小权限原则;生产环境保持 Swagger 关闭并限制管理面访问来源

开发

gofmt -l .
go vet ./...
go test ./...

# Handler 注释变更后重新生成唯一的对外 API 文档。
go tool swag init -g cmd/server/main.go -o docs --parseInternal --parseDependency --overridesFile docs/.swaggo

License

MIT