Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Build and Push Docker Image to GHCR

on:
push:
branches:
- main
tags:
- "v*.*.*"
pull_request:
branches:
- main

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-,format=short

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Bun](https://img.shields.io/badge/runtime-Bun-black)](https://bun.sh)
[![TypeScript](https://img.shields.io/badge/language-TypeScript-blue)](https://www.typescriptlang.org)
[![Docker Image](https://img.shields.io/badge/ghcr.io-gojam11%2Fllmrelayservice-blue?logo=docker)](https://github.com/GoJam11/LLMRelayService/pkgs/container/llmrelayservice)

LRS 是一个基于 **Bun + Hono** 的轻量 LLM 中继服务。它将多个 AI 服务商统一在单一入口下,配合内置的 Web 控制台,让你精确观测每一笔请求的延迟、Token 用量与缓存命中情况。

Expand Down Expand Up @@ -123,15 +124,11 @@ Railway / Render 等平台部署时构建命令同上。
### Docker 部署

```bash
# 1. 复制并配置环境变量
# 1. 复制并配置环境变量(至少设置 GATEWAY_API_KEY,PASSWORD 可选)
cp .env.example .env
# 至少设置 GATEWAY_API_KEY(PASSWORD 可选)

# 2. 启动服务(包含内置 PostgreSQL)
GATEWAY_API_KEY=your-key docker compose up -d

# 或者使用 .env 文件
docker compose up -d
```

访问 `http://localhost:3000` 打开控制台。
Expand Down
11 changes: 10 additions & 1 deletion changelog/2026-04-30.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

### 新增

- 添加 GitHub Actions 工作流 `.github/workflows/docker-publish.yml`,使用 GHCR(`ghcr.io`)自动构建并推送 Docker 镜像:
- 触发条件:推送到 `main` 分支、推送语义版本 tag(`v*.*.*`)、以及针对 `main` 的 Pull Request(仅构建不推送)
- 使用 `docker/metadata-action` 自动生成 tag(branch、semver、short SHA)
- 启用 GitHub Actions 缓存加速构建(`cache-from/cache-to: type=gha`)
- 使用内置 `GITHUB_TOKEN` 进行 GHCR 认证,无需额外配置 Secret
- 更新 `README.md` 及 `docker-compose.yml` 完善 Docker 部署指南:
- `docker-compose.yml` 改为默认使用 GHCR 预构建镜像(`ghcr.io/gojam11/llmrelayservice:main`)
- README Docker 部分精简为纯用户视角的启动步骤,去除 CI 内部细节与本地构建说明
- 顶部徽章区新增 GHCR 镜像徽章
- **API Key 模型限制**:新增通过 API key 限制可使用模型的白名单机制,前后端全实现。
- 数据库 `console_api_keys` 表新增 `allowed_models_json` 列(JSON 字符串数组,空数组=不限制),通过启动时 inline migration 自动迁移(迁移编号 0015)。
- 后端 `src/api-keys.ts`:`StoredApiKeyRecord` 和 `AuthenticatedApiKeyInfo` 均增加 `allowed_models: string[]` 字段;新增 `setApiKeyAllowedModels(id, models)` 函数;`authenticateManagedApiKey` 返回携带 `allowed_models` 的完整信息。
Expand All @@ -14,9 +23,9 @@

### 变更

- `.github/workflows/docker-publish.yml` 新增 `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true`,主动 opt-in Node.js 24 运行时(强制切换时间:2026-06-02)
- **API Key 模型限制 review 修复**:
- `src/index.ts`:`authenticateGateway()` 返回类型改为正确使用 `AuthenticatedApiKeyInfo | null`;限制检查变量重命名为 `clientRequestedModel` 并添加注释说明检查对象是 pre-resolution 的 alias/model 名,而非 resolved 上游模型;配置了非空 `allowed_models` 的 key 遇到 `unknown` 模型时 fail closed(返回 403)。
- `src/api-keys.ts`:导出纯函数 `isModelAllowed(model, patterns)`;`parseAllowedModels` 读取时 trim + dedup;`setApiKeyAllowedModels` 写入时 `Array.from(new Set(...))` 去重。
- `src/db/migrate.ts`:注释编号整理,将 `token_usage_estimated` migration 编号从 `0014` 更正为 `0016`,确保编号唯一有序。
- `test/api-key-model-restrictions.test.ts`:新增完整测试覆盖 `isModelAllowed` exact/wildcard、normalize/parse、gateway enforcement,以及 alias 语义(允许 alias 访问、拒绝直接访问底层模型、unknown 模型 fail closed、admin key 绕过)。

2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
app:
build: .
image: ghcr.io/gojam11/llmrelayservice:main
ports:
- "3000:3000"
environment:
Expand Down
Loading