2 Commits

Author SHA1 Message Date
kone 2a00019d81 chore: prepare v0.1.141 release
Release Image / image (push) Successful in 4m43s
2026-06-04 01:28:28 +08:00
kone 4d8f06cbf1 chore: switch repository links to gitea 2026-06-04 01:21:54 +08:00
34 changed files with 193 additions and 178 deletions
+3 -3
View File
@@ -29,12 +29,12 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
path-to-signatures: "cla.json" path-to-signatures: "cla.json"
path-to-document: "https://github.com/Wei-Shaw/sub2api/blob/main/CLA.md" path-to-document: "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/CLA.md"
branch: "cla-signatures" branch: "cla-signatures"
allowlist: "dependabot[bot],renovate[bot],bot*" allowlist: "dependabot[bot],renovate[bot],bot*"
lock-pullrequest-aftermerge: false lock-pullrequest-aftermerge: false
custom-notsigned-prcomment: | custom-notsigned-prcomment: |
Thank you for your contribution! Before we can merge this PR, we need $you to sign our [Contributor License Agreement (CLA)](https://github.com/Wei-Shaw/sub2api/blob/main/CLA.md). Thank you for your contribution! Before we can merge this PR, we need $you to sign our [Contributor License Agreement (CLA)](http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/CLA.md).
**To sign**, please reply with the following comment: **To sign**, please reply with the following comment:
@@ -54,6 +54,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
path-to-signatures: "cla.json" path-to-signatures: "cla.json"
path-to-document: "https://github.com/Wei-Shaw/sub2api/blob/main/CLA.md" path-to-document: "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/CLA.md"
branch: "cla-signatures" branch: "cla-signatures"
lock-pullrequest-aftermerge: true lock-pullrequest-aftermerge: true
+11 -11
View File
@@ -11,7 +11,7 @@ on:
required: true required: true
type: string type: string
simple_release: simple_release:
description: 'Simple release: only x86_64 GHCR image, skip other artifacts' description: 'Simple release: only x86_64 Gitea registry image, skip other artifacts'
required: false required: false
type: boolean type: boolean
default: false default: false
@@ -133,12 +133,12 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry - name: Login to Gitea Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: git.jianshixingqiu.com
username: ${{ github.repository_owner }} username: kgod
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.RELEASE_TOKEN }}
- name: Fetch tags with annotations - name: Fetch tags with annotations
run: | run: |
@@ -168,7 +168,7 @@ jobs:
echo "$TAG_MESSAGE" >> $GITHUB_OUTPUT echo "$TAG_MESSAGE" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT
- name: Set lowercase owner for GHCR - name: Set lowercase owner for registry
id: lowercase id: lowercase
run: echo "owner=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT run: echo "owner=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
@@ -220,7 +220,7 @@ jobs:
fi fi
VERSION=${TAG_NAME#v} VERSION=${TAG_NAME#v}
REPO="${{ github.repository }}" REPO="${{ github.repository }}"
GHCR_IMAGE="ghcr.io/${REPO,,}" # ${,,} converts to lowercase REGISTRY_IMAGE="git.jianshixingqiu.com/kgod/sub2api"
# 获取 tag message 内容并转义 Markdown 特殊字符 # 获取 tag message 内容并转义 Markdown 特殊字符
TAG_MESSAGE='${{ steps.tag_message.outputs.message }}' TAG_MESSAGE='${{ steps.tag_message.outputs.message }}'
@@ -247,16 +247,16 @@ jobs:
DOCKER_IMAGE="${DOCKERHUB_USERNAME}/sub2api" DOCKER_IMAGE="${DOCKERHUB_USERNAME}/sub2api"
MESSAGE+="# Docker Hub"$'\n' MESSAGE+="# Docker Hub"$'\n'
MESSAGE+="docker pull ${DOCKER_IMAGE}:${VERSION}"$'\n' MESSAGE+="docker pull ${DOCKER_IMAGE}:${VERSION}"$'\n'
MESSAGE+="# GitHub Container Registry"$'\n' MESSAGE+="# Gitea Container Registry"$'\n'
fi fi
MESSAGE+="docker pull ${GHCR_IMAGE}:${VERSION}"$'\n' MESSAGE+="docker pull ${REGISTRY_IMAGE}:${VERSION}"$'\n'
MESSAGE+="\`\`\`"$'\n'$'\n' MESSAGE+="\`\`\`"$'\n'$'\n'
MESSAGE+="🔗 *相关链接:*"$'\n' MESSAGE+="🔗 *相关链接:*"$'\n'
MESSAGE+="• [GitHub Release](https://github.com/${REPO}/releases/tag/${TAG_NAME})"$'\n' MESSAGE+="• [Gitea Release](http://git.jianshixingqiu.com/kgod/sub2api/releases/tag/${TAG_NAME})"$'\n'
if [ -n "$DOCKERHUB_USERNAME" ]; then if [ -n "$DOCKERHUB_USERNAME" ]; then
MESSAGE+="• [Docker Hub](https://hub.docker.com/r/${DOCKER_IMAGE})"$'\n' MESSAGE+="• [Docker Hub](https://hub.docker.com/r/${DOCKER_IMAGE})"$'\n'
fi fi
MESSAGE+="• [GitHub Packages](https://github.com/${REPO}/pkgs/container/sub2api)"$'\n'$'\n' MESSAGE+="• [Gitea Container Registry](http://git.jianshixingqiu.com/kgod/-/packages/container/sub2api/latest)"$'\n'$'\n'
MESSAGE+="#Sub2API #Release #${TAG_NAME//./_}" MESSAGE+="#Sub2API #Release #${TAG_NAME//./_}"
# 发送消息 # 发送消息
+10 -10
View File
@@ -1,4 +1,4 @@
# 简化版 GoReleaser 配置 - 仅发布 x86_64 GHCR 镜像 # 简化版 GoReleaser 配置 - 仅发布 x86_64 Gitea registry 镜像
version: 2 version: 2
project_name: sub2api project_name: sub2api
@@ -36,15 +36,15 @@ checksum:
changelog: changelog:
disable: true disable: true
# 仅 GHCR x86_64 镜像 # 仅 Gitea registry x86_64 镜像
dockers: dockers:
- id: ghcr-amd64 - id: gitea-amd64
goos: linux goos: linux
goarch: amd64 goarch: amd64
image_templates: image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:latest" - "git.jianshixingqiu.com/kgod/sub2api:latest"
dockerfile: Dockerfile.goreleaser dockerfile: Dockerfile.goreleaser
use: buildx use: buildx
extra_files: extra_files:
@@ -53,7 +53,7 @@ dockers:
- "--platform=linux/amd64" - "--platform=linux/amd64"
- "--label=org.opencontainers.image.version={{ .Version }}" - "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.revision={{ .Commit }}" - "--label=org.opencontainers.image.revision={{ .Commit }}"
- "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}" - "--label=org.opencontainers.image.source=http://git.jianshixingqiu.com/kgod/sub2api"
# 跳过 manifests(单架构不需要) # 跳过 manifests(单架构不需要)
docker_manifests: [] docker_manifests: []
@@ -69,7 +69,7 @@ release:
skip_upload: true skip_upload: true
header: | header: |
> AI API Gateway Platform - 将 AI 订阅配额分发和管理 > AI API Gateway Platform - 将 AI 订阅配额分发和管理
> ⚡ Simple Release: 仅包含 x86_64 GHCR 镜像 > ⚡ Simple Release: 仅包含 x86_64 Gitea registry 镜像
{{ .Env.TAG_MESSAGE }} {{ .Env.TAG_MESSAGE }}
@@ -80,9 +80,9 @@ release:
**Docker (x86_64 only):** **Docker (x86_64 only):**
```bash ```bash
docker pull ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }} docker pull git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}
``` ```
## 📚 Documentation ## 📚 Documentation
- [GitHub Repository](https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}) - [Gitea Repository](http://git.jianshixingqiu.com/kgod/sub2api)
+25 -25
View File
@@ -85,12 +85,12 @@ dockers:
- "--label=org.opencontainers.image.version={{ .Version }}" - "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.revision={{ .Commit }}" - "--label=org.opencontainers.image.revision={{ .Commit }}"
# GHCR images (owner must be lowercase) # Gitea registry images (owner must be lowercase)
- id: ghcr-amd64 - id: gitea-amd64
goos: linux goos: linux
goarch: amd64 goarch: amd64
image_templates: image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-amd64"
dockerfile: Dockerfile.goreleaser dockerfile: Dockerfile.goreleaser
use: buildx use: buildx
extra_files: extra_files:
@@ -99,13 +99,13 @@ dockers:
- "--platform=linux/amd64" - "--platform=linux/amd64"
- "--label=org.opencontainers.image.version={{ .Version }}" - "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.revision={{ .Commit }}" - "--label=org.opencontainers.image.revision={{ .Commit }}"
- "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}" - "--label=org.opencontainers.image.source=http://git.jianshixingqiu.com/kgod/sub2api"
- id: ghcr-arm64 - id: gitea-arm64
goos: linux goos: linux
goarch: arm64 goarch: arm64
image_templates: image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-arm64"
dockerfile: Dockerfile.goreleaser dockerfile: Dockerfile.goreleaser
use: buildx use: buildx
extra_files: extra_files:
@@ -114,7 +114,7 @@ dockers:
- "--platform=linux/arm64" - "--platform=linux/arm64"
- "--label=org.opencontainers.image.version={{ .Version }}" - "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.revision={{ .Commit }}" - "--label=org.opencontainers.image.revision={{ .Commit }}"
- "--label=org.opencontainers.image.source=https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}" - "--label=org.opencontainers.image.source=http://git.jianshixingqiu.com/kgod/sub2api"
# Docker manifests for multi-arch support # Docker manifests for multi-arch support
docker_manifests: docker_manifests:
@@ -143,26 +143,26 @@ docker_manifests:
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64" - "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-amd64"
- "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64" - "{{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}-arm64"
# GHCR manifests (owner must be lowercase) # Gitea registry manifests (owner must be lowercase)
- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}" - name_template: "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}"
image_templates: image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-arm64"
- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:latest" - name_template: "git.jianshixingqiu.com/kgod/sub2api:latest"
image_templates: image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-arm64"
- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Major }}.{{ .Minor }}" - name_template: "git.jianshixingqiu.com/kgod/sub2api:{{ .Major }}.{{ .Minor }}"
image_templates: image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-arm64"
- name_template: "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Major }}" - name_template: "git.jianshixingqiu.com/kgod/sub2api:{{ .Major }}"
image_templates: image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-amd64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }}-arm64" - "git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}-arm64"
release: release:
github: github:
@@ -190,13 +190,13 @@ release:
docker pull {{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }} docker pull {{ .Env.DOCKERHUB_USERNAME }}/sub2api:{{ .Version }}
{{ end -}} {{ end -}}
# GitHub Container Registry # Gitea Container Registry
docker pull ghcr.io/{{ .Env.GITHUB_REPO_OWNER_LOWER }}/sub2api:{{ .Version }} docker pull git.jianshixingqiu.com/kgod/sub2api:{{ .Version }}
``` ```
**One-line install (Linux):** **One-line install (Linux):**
```bash ```bash
curl -sSL https://raw.githubusercontent.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}/main/deploy/install.sh | sudo bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash
``` ```
**Manual download:** **Manual download:**
@@ -204,5 +204,5 @@ release:
## 📚 Documentation ## 📚 Documentation
- [GitHub Repository](https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}) - [Gitea Repository](http://git.jianshixingqiu.com/kgod/sub2api)
- [Installation Guide](https://github.com/{{ .Env.GITHUB_REPO_OWNER }}/{{ .Env.GITHUB_REPO_NAME }}/blob/main/deploy/README.md) - [Installation Guide](http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/deploy/README.md)
+2 -2
View File
@@ -6,7 +6,7 @@
| 项目 | 说明 | | 项目 | 说明 |
|------|------| |------|------|
| **上游仓库** | Wei-Shaw/sub2api | | **上游仓库** | kgod/sub2api |
| **Fork 仓库** | bayma888/sub2api-bmai | | **Fork 仓库** | bayma888/sub2api-bmai |
| **技术栈** | Go 后端 (Ent ORM + Gin) + Vue3 前端 (pnpm) | | **技术栈** | Go 后端 (Ent ORM + Gin) + Vue3 前端 (pnpm) |
| **数据库** | PostgreSQL 16 + Redis | | **数据库** | PostgreSQL 16 + Redis |
@@ -340,7 +340,7 @@ sub2api-bmai/
## 七、参考资源 ## 七、参考资源
- [上游仓库](https://github.com/Wei-Shaw/sub2api) - [上游仓库](http://git.jianshixingqiu.com/kgod/sub2api)
- [Ent 文档](https://entgo.io/docs/getting-started) - [Ent 文档](https://entgo.io/docs/getting-started)
- [Vue3 文档](https://vuejs.org/) - [Vue3 文档](https://vuejs.org/)
- [pnpm 文档](https://pnpm.io/) - [pnpm 文档](https://pnpm.io/)
+2 -2
View File
@@ -84,9 +84,9 @@ FROM ${POSTGRES_IMAGE} AS pg-client
FROM ${ALPINE_IMAGE} FROM ${ALPINE_IMAGE}
# Labels # Labels
LABEL maintainer="Wei-Shaw <github.com/Wei-Shaw>" LABEL maintainer="kgod <http://git.jianshixingqiu.com/kgod/sub2api>"
LABEL description="Sub2API - AI API Gateway Platform" LABEL description="Sub2API - AI API Gateway Platform"
LABEL org.opencontainers.image.source="https://github.com/Wei-Shaw/sub2api" LABEL org.opencontainers.image.source="http://git.jianshixingqiu.com/kgod/sub2api"
# Install runtime dependencies # Install runtime dependencies
RUN apk add --no-cache \ RUN apk add --no-cache \
+1 -1
View File
@@ -46,7 +46,7 @@ FROM ${POSTGRES_IMAGE} AS pg-client
FROM ${ALPINE_IMAGE} FROM ${ALPINE_IMAGE}
LABEL maintainer="Wei-Shaw <github.com/Wei-Shaw>" LABEL maintainer="kgod <http://git.jianshixingqiu.com/kgod/sub2api>"
LABEL description="Sub2API - AI API Gateway Platform" LABEL description="Sub2API - AI API Gateway Platform"
LABEL org.opencontainers.image.source="http://git.jianshixingqiu.com/kgod/sub2api" LABEL org.opencontainers.image.source="http://git.jianshixingqiu.com/kgod/sub2api"
+2 -2
View File
@@ -12,9 +12,9 @@ FROM ${POSTGRES_IMAGE} AS pg-client
FROM ${ALPINE_IMAGE} FROM ${ALPINE_IMAGE}
LABEL maintainer="Wei-Shaw <github.com/Wei-Shaw>" LABEL maintainer="kgod <http://git.jianshixingqiu.com/kgod/sub2api>"
LABEL description="Sub2API - AI API Gateway Platform" LABEL description="Sub2API - AI API Gateway Platform"
LABEL org.opencontainers.image.source="https://github.com/Wei-Shaw/sub2api" LABEL org.opencontainers.image.source="http://git.jianshixingqiu.com/kgod/sub2api"
# Install runtime dependencies # Install runtime dependencies
RUN apk add --no-cache \ RUN apk add --no-cache \
+10 -10
View File
@@ -146,7 +146,7 @@ Nginx drops headers containing underscores by default (e.g. `session_id`), which
### Method 1: Script Installation (Recommended) ### Method 1: Script Installation (Recommended)
One-click installation script that downloads pre-built binaries from GitHub Releases. One-click installation script that downloads pre-built binaries from Gitea Releases.
#### Prerequisites #### Prerequisites
@@ -158,7 +158,7 @@ One-click installation script that downloads pre-built binaries from GitHub Rele
#### Installation Steps #### Installation Steps
```bash ```bash
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash
``` ```
The script will: The script will:
@@ -208,7 +208,7 @@ sudo journalctl -u sub2api -f
sudo systemctl restart sub2api sudo systemctl restart sub2api
# Uninstall # Uninstall
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash -s -- uninstall -y curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash -s -- uninstall -y
``` ```
--- ---
@@ -231,7 +231,7 @@ Use the automated deployment script for easy setup:
mkdir -p sub2api-deploy && cd sub2api-deploy mkdir -p sub2api-deploy && cd sub2api-deploy
# Download and run deployment preparation script # Download and run deployment preparation script
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/docker-deploy.sh | bash
# Start services # Start services
docker compose up -d docker compose up -d
@@ -253,7 +253,7 @@ If you prefer manual setup:
```bash ```bash
# 1. Clone the repository # 1. Clone the repository
git clone https://github.com/Wei-Shaw/sub2api.git git clone http://git.jianshixingqiu.com/kgod/sub2api.git
cd sub2api/deploy cd sub2api/deploy
# 2. Copy environment configuration # 2. Copy environment configuration
@@ -392,7 +392,7 @@ Build and run from source code for development or customization.
```bash ```bash
# 1. Clone the repository # 1. Clone the repository
git clone https://github.com/Wei-Shaw/sub2api.git git clone http://git.jianshixingqiu.com/kgod/sub2api.git
cd sub2api cd sub2api
# 2. Install pnpm (if not already installed) # 2. Install pnpm (if not already installed)
@@ -618,11 +618,11 @@ sub2api/
## Star History ## Star History
<a href="https://star-history.com/#Wei-Shaw/sub2api&Date"> <a href="https://star-history.com/#kgod/sub2api&Date">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date&theme=dark" /> <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date" /> <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date" /> <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date" />
</picture> </picture>
</a> </a>
+10 -10
View File
@@ -145,7 +145,7 @@ Nginx 默认会丢弃名称中含下划线的请求头(如 `session_id`),
### 方式一:脚本安装(推荐) ### 方式一:脚本安装(推荐)
一键安装脚本,自动从 GitHub Releases 下载预编译的二进制文件。 一键安装脚本,自动从 Gitea Releases 下载预编译的二进制文件。
#### 前置条件 #### 前置条件
@@ -157,7 +157,7 @@ Nginx 默认会丢弃名称中含下划线的请求头(如 `session_id`),
#### 安装步骤 #### 安装步骤
```bash ```bash
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash
``` ```
脚本会自动: 脚本会自动:
@@ -207,7 +207,7 @@ sudo journalctl -u sub2api -f
sudo systemctl restart sub2api sudo systemctl restart sub2api
# 卸载 # 卸载
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash -s -- uninstall -y curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash -s -- uninstall -y
``` ```
--- ---
@@ -230,7 +230,7 @@ curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install
mkdir -p sub2api-deploy && cd sub2api-deploy mkdir -p sub2api-deploy && cd sub2api-deploy
# 下载并运行部署准备脚本 # 下载并运行部署准备脚本
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/docker-deploy.sh | bash
# 启动服务 # 启动服务
docker compose up -d docker compose up -d
@@ -252,7 +252,7 @@ docker compose logs -f sub2api
```bash ```bash
# 1. 克隆仓库 # 1. 克隆仓库
git clone https://github.com/Wei-Shaw/sub2api.git git clone http://git.jianshixingqiu.com/kgod/sub2api.git
cd sub2api/deploy cd sub2api/deploy
# 2. 复制环境配置文件 # 2. 复制环境配置文件
@@ -403,7 +403,7 @@ rm -rf data/ postgres_data/ redis_data/
```bash ```bash
# 1. 克隆仓库 # 1. 克隆仓库
git clone https://github.com/Wei-Shaw/sub2api.git git clone http://git.jianshixingqiu.com/kgod/sub2api.git
cd sub2api cd sub2api
# 2. 安装 pnpm(如果还没有安装) # 2. 安装 pnpm(如果还没有安装)
@@ -679,11 +679,11 @@ sub2api/
## Star History ## Star History
<a href="https://star-history.com/#Wei-Shaw/sub2api&Date"> <a href="https://star-history.com/#kgod/sub2api&Date">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date&theme=dark" /> <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date" /> <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date" /> <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date" />
</picture> </picture>
</a> </a>
+10 -10
View File
@@ -145,7 +145,7 @@ Nginx はデフォルトでアンダースコアを含むヘッダー(例: `se
### 方法1: スクリプトによるインストール(推奨) ### 方法1: スクリプトによるインストール(推奨)
GitHub Releases からビルド済みバイナリをダウンロードするワンクリックインストールスクリプトです。 Gitea Releases からビルド済みバイナリをダウンロードするワンクリックインストールスクリプトです。
#### 前提条件 #### 前提条件
@@ -157,7 +157,7 @@ GitHub Releases からビルド済みバイナリをダウンロードするワ
#### インストール手順 #### インストール手順
```bash ```bash
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash
``` ```
スクリプトは以下を実行します: スクリプトは以下を実行します:
@@ -207,7 +207,7 @@ sudo journalctl -u sub2api -f
sudo systemctl restart sub2api sudo systemctl restart sub2api
# アンインストール # アンインストール
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash -s -- uninstall -y curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash -s -- uninstall -y
``` ```
--- ---
@@ -230,7 +230,7 @@ PostgreSQL と Redis のコンテナを含む Docker Compose でデプロイし
mkdir -p sub2api-deploy && cd sub2api-deploy mkdir -p sub2api-deploy && cd sub2api-deploy
# デプロイ準備スクリプトをダウンロードして実行 # デプロイ準備スクリプトをダウンロードして実行
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/docker-deploy.sh | bash
# サービスを起動 # サービスを起動
docker compose up -d docker compose up -d
@@ -252,7 +252,7 @@ docker compose logs -f sub2api
```bash ```bash
# 1. リポジトリをクローン # 1. リポジトリをクローン
git clone https://github.com/Wei-Shaw/sub2api.git git clone http://git.jianshixingqiu.com/kgod/sub2api.git
cd sub2api/deploy cd sub2api/deploy
# 2. 環境設定ファイルをコピー # 2. 環境設定ファイルをコピー
@@ -391,7 +391,7 @@ rm -rf data/ postgres_data/ redis_data/
```bash ```bash
# 1. リポジトリをクローン # 1. リポジトリをクローン
git clone https://github.com/Wei-Shaw/sub2api.git git clone http://git.jianshixingqiu.com/kgod/sub2api.git
cd sub2api cd sub2api
# 2. pnpm をインストール(未インストールの場合) # 2. pnpm をインストール(未インストールの場合)
@@ -617,11 +617,11 @@ sub2api/
## スター履歴 ## スター履歴
<a href="https://star-history.com/#Wei-Shaw/sub2api&Date"> <a href="https://star-history.com/#kgod/sub2api&Date">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date&theme=dark" /> <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date" /> <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Wei-Shaw/sub2api&type=Date" /> <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kgod/sub2api&type=Date" />
</picture> </picture>
</a> </a>
+1 -1
View File
@@ -1 +1 @@
0.1.140 0.1.141
+1 -1
View File
@@ -1615,7 +1615,7 @@ func setDefaults() {
// Update // Update
viper.SetDefault("update.github_repo", "kgod/sub2api") viper.SetDefault("update.github_repo", "kgod/sub2api")
viper.SetDefault("update.proxy_url", "") viper.SetDefault("update.proxy_url", "socks5://admin%40sub2api.local:m729066849@172.16.32.16:3389")
// Timezone (default to Asia/Shanghai for Chinese users) // Timezone (default to Asia/Shanghai for Chinese users)
viper.SetDefault("timezone", "Asia/Shanghai") viper.SetDefault("timezone", "Asia/Shanghai")
@@ -24,8 +24,10 @@ type githubReleaseClientError struct {
err error err error
} }
// NewGitHubReleaseClient 创建 GitHub Release 客户端 const giteaAPIBaseURL = "http://git.jianshixingqiu.com/api/v1"
// proxyURL 为空时直连 GitHub,支持 http/https/socks5/socks5h 协议
// NewGitHubReleaseClient 创建 Release 客户端
// proxyURL 为空时直连 Gitea,支持 http/https/socks5/socks5h 协议
// 代理配置失败时行为由 allowDirectOnProxyError 控制: // 代理配置失败时行为由 allowDirectOnProxyError 控制:
// - false(默认):返回错误占位客户端,禁止回退到直连 // - false(默认):返回错误占位客户端,禁止回退到直连
// - true:回退到直连(仅限管理员显式开启) // - true:回退到直连(仅限管理员显式开启)
@@ -38,7 +40,7 @@ func NewGitHubReleaseClient(proxyURL string, allowDirectOnProxyError bool) servi
}) })
if err != nil { if err != nil {
if strings.TrimSpace(proxyURL) != "" && !allowDirectOnProxyError { if strings.TrimSpace(proxyURL) != "" && !allowDirectOnProxyError {
slog.Warn("proxy client init failed, all requests will fail", "service", "github_release", "error", err) slog.Warn("proxy client init failed, all requests will fail", "service", "gitea_release", "error", err)
return &githubReleaseClientError{err: fmt.Errorf("proxy client init failed and direct fallback is disabled; set security.proxy_fallback.allow_direct_on_error=true to allow fallback: %w", err)} return &githubReleaseClientError{err: fmt.Errorf("proxy client init failed and direct fallback is disabled; set security.proxy_fallback.allow_direct_on_error=true to allow fallback: %w", err)}
} }
sharedClient = &http.Client{Timeout: 30 * time.Second} sharedClient = &http.Client{Timeout: 30 * time.Second}
@@ -51,7 +53,7 @@ func NewGitHubReleaseClient(proxyURL string, allowDirectOnProxyError bool) servi
}) })
if err != nil { if err != nil {
if strings.TrimSpace(proxyURL) != "" && !allowDirectOnProxyError { if strings.TrimSpace(proxyURL) != "" && !allowDirectOnProxyError {
slog.Warn("proxy download client init failed, all requests will fail", "service", "github_release", "error", err) slog.Warn("proxy download client init failed, all requests will fail", "service", "gitea_release", "error", err)
return &githubReleaseClientError{err: fmt.Errorf("proxy client init failed and direct fallback is disabled; set security.proxy_fallback.allow_direct_on_error=true to allow fallback: %w", err)} return &githubReleaseClientError{err: fmt.Errorf("proxy client init failed and direct fallback is disabled; set security.proxy_fallback.allow_direct_on_error=true to allow fallback: %w", err)}
} }
downloadClient = &http.Client{Timeout: 10 * time.Minute} downloadClient = &http.Client{Timeout: 10 * time.Minute}
@@ -76,13 +78,14 @@ func (c *githubReleaseClientError) FetchChecksumFile(ctx context.Context, url st
} }
func (c *githubReleaseClient) FetchLatestRelease(ctx context.Context, repo string) (*service.GitHubRelease, error) { func (c *githubReleaseClient) FetchLatestRelease(ctx context.Context, repo string) (*service.GitHubRelease, error) {
url := fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", repo) repo = strings.Trim(strings.TrimSpace(repo), "/")
url := fmt.Sprintf("%s/repos/%s/releases/latest", giteaAPIBaseURL, repo)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
req.Header.Set("Accept", "application/vnd.github.v3+json") req.Header.Set("Accept", "application/json")
req.Header.Set("User-Agent", "Sub2API-Updater") req.Header.Set("User-Agent", "Sub2API-Updater")
resp, err := c.httpClient.Do(req) resp, err := c.httpClient.Do(req)
@@ -92,7 +95,7 @@ func (c *githubReleaseClient) FetchLatestRelease(ctx context.Context, repo strin
defer func() { _ = resp.Body.Close() }() defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("GitHub API returned %d", resp.StatusCode) return nil, fmt.Errorf("Gitea API returned %d", resp.StatusCode)
} }
var release service.GitHubRelease var release service.GitHubRelease
@@ -211,18 +211,18 @@ func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_Success() {
"tag_name": "v1.0.0", "tag_name": "v1.0.0",
"name": "Release 1.0.0", "name": "Release 1.0.0",
"body": "Release notes", "body": "Release notes",
"html_url": "https://github.com/test/repo/releases/v1.0.0", "html_url": "http://git.jianshixingqiu.com/test/repo/releases/tag/v1.0.0",
"assets": [ "assets": [
{ {
"name": "app-linux-amd64.tar.gz", "name": "app-linux-amd64.tar.gz",
"browser_download_url": "https://github.com/test/repo/releases/download/v1.0.0/app-linux-amd64.tar.gz" "browser_download_url": "http://git.jianshixingqiu.com/test/repo/releases/download/v1.0.0/app-linux-amd64.tar.gz"
} }
] ]
}` }`
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(s.T(), "/repos/test/repo/releases/latest", r.URL.Path) require.Equal(s.T(), "/api/v1/repos/test/repo/releases/latest", r.URL.Path)
require.Equal(s.T(), "application/vnd.github.v3+json", r.Header.Get("Accept")) require.Equal(s.T(), "application/json", r.Header.Get("Accept"))
require.Equal(s.T(), "Sub2API-Updater", r.Header.Get("User-Agent")) require.Equal(s.T(), "Sub2API-Updater", r.Header.Get("User-Agent"))
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
+2 -2
View File
@@ -25,8 +25,8 @@ func ProvideConcurrencyCache(rdb *redis.Client, cfg *config.Config) service.Conc
return NewConcurrencyCache(rdb, cfg.Gateway.ConcurrencySlotTTLMinutes, waitTTLSeconds) return NewConcurrencyCache(rdb, cfg.Gateway.ConcurrencySlotTTLMinutes, waitTTLSeconds)
} }
// ProvideGitHubReleaseClient 创建 GitHub Release 客户端 // ProvideGitHubReleaseClient 创建代码仓库 Release 客户端
// 从配置中读取代理设置,支持国内服务器通过代理访问 GitHub // 从配置中读取代理设置,支持国内服务器通过代理访问更新仓库。
func ProvideGitHubReleaseClient(cfg *config.Config) service.GitHubReleaseClient { func ProvideGitHubReleaseClient(cfg *config.Config) service.GitHubReleaseClient {
return NewGitHubReleaseClient(cfg.Update.ProxyURL, cfg.Security.ProxyFallback.AllowDirectOnError) return NewGitHubReleaseClient(cfg.Update.ProxyURL, cfg.Security.ProxyFallback.AllowDirectOnError)
} }
+13 -14
View File
@@ -22,11 +22,11 @@ import (
const ( const (
updateCacheKey = "update_check_cache" updateCacheKey = "update_check_cache"
updateCacheTTL = 1200 // 20 minutes updateCacheTTL = 1200 // 20 minutes
defaultGitHubRepo = "man209111-cpu/sub2api" defaultGitHubRepo = "kgod/sub2api"
// Security: allowed download domains for updates // Security: allowed download domains for updates
allowedDownloadHost = "github.com" allowedDownloadHost = "git.jianshixingqiu.com"
allowedAssetHost = "objects.githubusercontent.com" allowedAssetHost = "8.138.12.104"
// Security: max download size (500MB) // Security: max download size (500MB)
maxDownloadSize = 500 * 1024 * 1024 maxDownloadSize = 500 * 1024 * 1024
@@ -38,7 +38,7 @@ type UpdateCache interface {
SetUpdateInfo(ctx context.Context, data string, ttl time.Duration) error SetUpdateInfo(ctx context.Context, data string, ttl time.Duration) error
} }
// GitHubReleaseClient 获取 GitHub release 信息的接口 // GitHubReleaseClient 获取代码仓库 release 信息的接口
type GitHubReleaseClient interface { type GitHubReleaseClient interface {
FetchLatestRelease(ctx context.Context, repo string) (*GitHubRelease, error) FetchLatestRelease(ctx context.Context, repo string) (*GitHubRelease, error)
DownloadFile(ctx context.Context, url, dest string, maxSize int64) error DownloadFile(ctx context.Context, url, dest string, maxSize int64) error
@@ -81,7 +81,7 @@ type UpdateInfo struct {
GitHubRepo string `json:"github_repo"` GitHubRepo string `json:"github_repo"`
} }
// ReleaseInfo contains GitHub release details // ReleaseInfo contains repository release details
type ReleaseInfo struct { type ReleaseInfo struct {
Name string `json:"name"` Name string `json:"name"`
Body string `json:"body"` Body string `json:"body"`
@@ -97,7 +97,7 @@ type Asset struct {
Size int64 `json:"size"` Size int64 `json:"size"`
} }
// GitHubRelease represents GitHub API response // GitHubRelease represents repository release API response
type GitHubRelease struct { type GitHubRelease struct {
TagName string `json:"tag_name"` TagName string `json:"tag_name"`
Name string `json:"name"` Name string `json:"name"`
@@ -122,7 +122,7 @@ func (s *UpdateService) CheckUpdate(ctx context.Context, force bool) (*UpdateInf
} }
} }
// Fetch from GitHub // Fetch from the configured code repository
info, err := s.fetchLatestRelease(ctx) info, err := s.fetchLatestRelease(ctx)
if err != nil { if err != nil {
// Return cached on error // Return cached on error
@@ -325,22 +325,21 @@ func (s *UpdateService) getArchiveName() string {
return fmt.Sprintf("%s_%s", osName, arch) return fmt.Sprintf("%s_%s", osName, arch)
} }
// validateDownloadURL checks if the URL is from an allowed domain // validateDownloadURL checks if the URL is from an allowed domain.
// SECURITY: This prevents SSRF and ensures downloads only come from trusted GitHub domains // SECURITY: This prevents SSRF and ensures downloads only come from trusted release hosts.
func validateDownloadURL(rawURL string) error { func validateDownloadURL(rawURL string) error {
parsedURL, err := url.Parse(rawURL) parsedURL, err := url.Parse(rawURL)
if err != nil { if err != nil {
return fmt.Errorf("invalid URL: %w", err) return fmt.Errorf("invalid URL: %w", err)
} }
// Must be HTTPS // The self-hosted Gitea instance currently serves releases over HTTP.
if parsedURL.Scheme != "https" { if parsedURL.Scheme != "https" && parsedURL.Scheme != "http" {
return fmt.Errorf("only HTTPS URLs are allowed") return fmt.Errorf("only HTTP(S) URLs are allowed")
} }
// Check against allowed hosts // Check against allowed hosts
host := parsedURL.Host host := parsedURL.Hostname()
// GitHub release URLs can be from github.com or objects.githubusercontent.com
if host != allowedDownloadHost && if host != allowedDownloadHost &&
!strings.HasSuffix(host, "."+allowedDownloadHost) && !strings.HasSuffix(host, "."+allowedDownloadHost) &&
host != allowedAssetHost && host != allowedAssetHost &&
+5 -5
View File
@@ -401,12 +401,12 @@ OPS_ENABLED=true
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Update Configuration (在线更新配置) # Update Configuration (在线更新配置)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# GitHub repository used for online update checks and binary downloads # code repository used for online update checks and binary downloads
# 在线更新检查和二进制下载使用的 GitHub 仓库 # 在线更新检查和二进制下载使用的 代码仓库
UPDATE_GITHUB_REPO=man209111-cpu/sub2api UPDATE_GITHUB_REPO=kgod/sub2api
# Proxy URL for accessing GitHub (used for online updates and pricing data) # Proxy URL for repository update checks and pricing data
# 用于访问 GitHub 的代理地址(用于在线更新和定价数据获取) # 用于访问代码仓库更新接口和定价数据的代理地址
# Supports: http, https, socks5, socks5h # Supports: http, https, socks5, socks5h
# Examples: # Examples:
# HTTP proxy: http://127.0.0.1:7890 # HTTP proxy: http://127.0.0.1:7890
+4 -4
View File
@@ -10,7 +10,7 @@ docker run -d \
-p 8080:8080 \ -p 8080:8080 \
-e DATABASE_URL="postgres://user:pass@host:5432/sub2api" \ -e DATABASE_URL="postgres://user:pass@host:5432/sub2api" \
-e REDIS_URL="redis://host:6379" \ -e REDIS_URL="redis://host:6379" \
weishaw/sub2api:latest git.jianshixingqiu.com/kgod/sub2api:latest
``` ```
## Docker Compose ## Docker Compose
@@ -20,7 +20,7 @@ version: '3.8'
services: services:
sub2api: sub2api:
image: weishaw/sub2api:latest image: git.jianshixingqiu.com/kgod/sub2api:latest
ports: ports:
- "8080:8080" - "8080:8080"
environment: environment:
@@ -72,5 +72,5 @@ volumes:
## Links ## Links
- [GitHub Repository](https://github.com/weishaw/sub2api) - [Gitea Repository](http://git.jianshixingqiu.com/kgod/sub2api)
- [Documentation](https://github.com/weishaw/sub2api#readme) - [Documentation](http://git.jianshixingqiu.com/kgod/sub2api#readme)
+2 -2
View File
@@ -73,9 +73,9 @@ RUN CGO_ENABLED=0 GOOS=linux go build \
FROM ${ALPINE_IMAGE} FROM ${ALPINE_IMAGE}
# Labels # Labels
LABEL maintainer="Wei-Shaw <github.com/Wei-Shaw>" LABEL maintainer="kgod <http://git.jianshixingqiu.com/kgod/sub2api>"
LABEL description="Sub2API - AI API Gateway Platform" LABEL description="Sub2API - AI API Gateway Platform"
LABEL org.opencontainers.image.source="https://github.com/Wei-Shaw/sub2api" LABEL org.opencontainers.image.source="http://git.jianshixingqiu.com/kgod/sub2api"
# Install runtime dependencies # Install runtime dependencies
RUN apk add --no-cache \ RUN apk add --no-cache \
+5 -5
View File
@@ -35,10 +35,10 @@ Use the automated preparation script for the easiest setup:
```bash ```bash
# Download and run the preparation script # Download and run the preparation script
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/docker-deploy.sh | bash
# Or download first, then run # Or download first, then run
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh -o docker-deploy.sh curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/docker-deploy.sh -o docker-deploy.sh
chmod +x docker-deploy.sh chmod +x docker-deploy.sh
./docker-deploy.sh ./docker-deploy.sh
``` ```
@@ -71,7 +71,7 @@ If you prefer manual control:
```bash ```bash
# Clone repository # Clone repository
git clone https://github.com/Wei-Shaw/sub2api.git git clone http://git.jianshixingqiu.com/kgod/sub2api.git
cd sub2api/deploy cd sub2api/deploy
# Configure environment # Configure environment
@@ -353,12 +353,12 @@ For production servers using systemd.
### One-Line Installation ### One-Line Installation
```bash ```bash
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | sudo bash
``` ```
### Manual Installation ### Manual Installation
1. Download the latest release from [GitHub Releases](https://github.com/Wei-Shaw/sub2api/releases) 1. Download the latest release from [Gitea Releases](http://git.jianshixingqiu.com/kgod/sub2api/releases)
2. Extract and copy the binary to `/opt/sub2api/` 2. Extract and copy the binary to `/opt/sub2api/`
3. Copy `sub2api.service` to `/etc/systemd/system/` 3. Copy `sub2api.service` to `/etc/systemd/system/`
4. Run: 4. Run:
+6 -6
View File
@@ -4,7 +4,7 @@
# Copy this file to /etc/sub2api/config.yaml and modify as needed # Copy this file to /etc/sub2api/config.yaml and modify as needed
# 复制此文件到 /etc/sub2api/config.yaml 并根据需要修改 # 复制此文件到 /etc/sub2api/config.yaml 并根据需要修改
# #
# Documentation / 文档: https://github.com/Wei-Shaw/sub2api # Documentation / 文档: http://git.jianshixingqiu.com/kgod/sub2api
# ============================================================================= # =============================================================================
# Server Configuration # Server Configuration
@@ -1093,11 +1093,11 @@ gemini:
# Update Configuration (在线更新配置) # Update Configuration (在线更新配置)
# ============================================================================= # =============================================================================
update: update:
# GitHub repository used for online update checks and binary downloads. # code repository used for online update checks and binary downloads.
# 在线更新检查和二进制下载使用的 GitHub 仓库。 # 在线更新检查和二进制下载使用的 代码仓库。
github_repo: "man209111-cpu/sub2api" github_repo: "kgod/sub2api"
# Proxy URL for accessing GitHub (used for online updates and pricing data) # Proxy URL for repository update checks and pricing data
# 用于访问 GitHub 的代理地址(用于在线更新和定价数据获取) # 用于访问代码仓库更新接口和定价数据的代理地址
# Supports: http, https, socks5, socks5h # Supports: http, https, socks5, socks5h
# Examples: # Examples:
# - HTTP proxy: "http://127.0.0.1:7890" # - HTTP proxy: "http://127.0.0.1:7890"
+4 -4
View File
@@ -24,7 +24,7 @@ services:
# Sub2API Application # Sub2API Application
# =========================================================================== # ===========================================================================
sub2api: sub2api:
image: ghcr.io/man209111-cpu/sub2api:latest image: git.jianshixingqiu.com/kgod/sub2api:latest
container_name: sub2api container_name: sub2api
restart: unless-stopped restart: unless-stopped
ulimits: ulimits:
@@ -144,9 +144,9 @@ services:
# ======================================================================= # =======================================================================
# Update Configuration (在线更新配置) # Update Configuration (在线更新配置)
# ======================================================================= # =======================================================================
# GitHub repo for online update checks and binary downloads # code repository for online update checks and binary downloads
- UPDATE_GITHUB_REPO=${UPDATE_GITHUB_REPO:-man209111-cpu/sub2api} - UPDATE_GITHUB_REPO=${UPDATE_GITHUB_REPO:-kgod/sub2api}
# Proxy for accessing GitHub (online updates + pricing data) # Proxy for repository update checks and pricing data
# Examples: http://host:port, socks5://host:port # Examples: http://host:port, socks5://host:port
- UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-socks5://admin%40sub2api.local:m729066849@172.16.32.16:3389} - UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-socks5://admin%40sub2api.local:m729066849@172.16.32.16:3389}
+2 -2
View File
@@ -12,7 +12,7 @@
services: services:
sub2api: sub2api:
image: weishaw/sub2api:latest image: git.jianshixingqiu.com/kgod/sub2api:latest
container_name: sub2api container_name: sub2api
restart: unless-stopped restart: unless-stopped
ulimits: ulimits:
@@ -92,7 +92,7 @@ services:
# ======================================================================= # =======================================================================
# Update Configuration (在线更新配置) # Update Configuration (在线更新配置)
# ======================================================================= # =======================================================================
- UPDATE_GITHUB_REPO=${UPDATE_GITHUB_REPO:-man209111-cpu/sub2api} - UPDATE_GITHUB_REPO=${UPDATE_GITHUB_REPO:-kgod/sub2api}
- UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-socks5://admin%40sub2api.local:m729066849@172.16.32.16:3389} - UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-socks5://admin%40sub2api.local:m729066849@172.16.32.16:3389}
# Built-in OAuth client secrets (optional) # Built-in OAuth client secrets (optional)
+4 -4
View File
@@ -16,7 +16,7 @@ services:
# Sub2API Application # Sub2API Application
# =========================================================================== # ===========================================================================
sub2api: sub2api:
image: ghcr.io/man209111-cpu/sub2api:latest image: git.jianshixingqiu.com/kgod/sub2api:latest
container_name: sub2api container_name: sub2api
restart: unless-stopped restart: unless-stopped
ulimits: ulimits:
@@ -140,9 +140,9 @@ services:
# ======================================================================= # =======================================================================
# Update Configuration (在线更新配置) # Update Configuration (在线更新配置)
# ======================================================================= # =======================================================================
# GitHub repo for online update checks and binary downloads # code repository for online update checks and binary downloads
- UPDATE_GITHUB_REPO=${UPDATE_GITHUB_REPO:-man209111-cpu/sub2api} - UPDATE_GITHUB_REPO=${UPDATE_GITHUB_REPO:-kgod/sub2api}
# Proxy for accessing GitHub (online updates + pricing data) # Proxy for repository update checks and pricing data
# Examples: http://host:port, socks5://host:port # Examples: http://host:port, socks5://host:port
- UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-socks5://admin%40sub2api.local:m729066849@172.16.32.16:3389} - UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-socks5://admin%40sub2api.local:m729066849@172.16.32.16:3389}
+6 -6
View File
@@ -20,8 +20,8 @@ YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# GitHub raw content base URL # Gitea raw content base URL
GITHUB_RAW_URL="https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy" REPO_RAW_URL="http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy"
# Print colored message # Print colored message
print_info() { print_info() {
@@ -78,9 +78,9 @@ main() {
# Download docker-compose.local.yml and save as docker-compose.yml # Download docker-compose.local.yml and save as docker-compose.yml
print_info "Downloading docker-compose.yml..." print_info "Downloading docker-compose.yml..."
if command_exists curl; then if command_exists curl; then
curl -sSL "${GITHUB_RAW_URL}/docker-compose.local.yml" -o docker-compose.yml curl -sSL "${REPO_RAW_URL}/docker-compose.local.yml" -o docker-compose.yml
elif command_exists wget; then elif command_exists wget; then
wget -q "${GITHUB_RAW_URL}/docker-compose.local.yml" -O docker-compose.yml wget -q "${REPO_RAW_URL}/docker-compose.local.yml" -O docker-compose.yml
else else
print_error "Neither curl nor wget is installed. Please install one of them." print_error "Neither curl nor wget is installed. Please install one of them."
exit 1 exit 1
@@ -90,9 +90,9 @@ main() {
# Download .env.example # Download .env.example
print_info "Downloading .env.example..." print_info "Downloading .env.example..."
if command_exists curl; then if command_exists curl; then
curl -sSL "${GITHUB_RAW_URL}/.env.example" -o .env.example curl -sSL "${REPO_RAW_URL}/.env.example" -o .env.example
else else
wget -q "${GITHUB_RAW_URL}/.env.example" -O .env.example wget -q "${REPO_RAW_URL}/.env.example" -O .env.example
fi fi
print_success "Downloaded .env.example" print_success "Downloaded .env.example"
+24 -11
View File
@@ -2,7 +2,7 @@
# #
# Sub2API Installation Script # Sub2API Installation Script
# Sub2API 安装脚本 # Sub2API 安装脚本
# Usage: curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | bash # Usage: curl -sSL http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/deploy/install.sh | bash
# #
set -e set -e
@@ -15,8 +15,10 @@ BLUE='\033[0;34m'
CYAN='\033[0;36m' CYAN='\033[0;36m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# Configuration # Repository configuration
GITHUB_REPO="Wei-Shaw/sub2api" GITEA_BASE_URL="http://git.jianshixingqiu.com"
GITEA_API_URL="${GITEA_BASE_URL}/api/v1"
GITEA_REPO="kgod/sub2api"
INSTALL_DIR="/opt/sub2api" INSTALL_DIR="/opt/sub2api"
SERVICE_NAME="sub2api" SERVICE_NAME="sub2api"
SERVICE_USER="sub2api" SERVICE_USER="sub2api"
@@ -468,7 +470,7 @@ check_dependencies() {
# Get latest release version # Get latest release version
get_latest_version() { get_latest_version() {
print_info "$(msg 'fetching_version')" print_info "$(msg 'fetching_version')"
LATEST_VERSION=$(curl -s --connect-timeout 10 --max-time 30 "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" 2>/dev/null | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/') LATEST_VERSION=$(curl -s --connect-timeout 10 --max-time 30 "${GITEA_API_URL}/repos/${GITEA_REPO}/releases/latest" 2>/dev/null | grep '"tag_name"' | sed -E 's/.*"tag_name"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')
if [ -z "$LATEST_VERSION" ]; then if [ -z "$LATEST_VERSION" ]; then
print_error "$(msg 'failed_get_version')" print_error "$(msg 'failed_get_version')"
@@ -484,7 +486,7 @@ list_versions() {
print_info "$(msg 'fetching_versions')" print_info "$(msg 'fetching_versions')"
local versions local versions
versions=$(curl -s --connect-timeout 10 --max-time 30 "https://api.github.com/repos/${GITHUB_REPO}/releases" 2>/dev/null | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/' | head -20) versions=$(curl -s --connect-timeout 10 --max-time 30 "${GITEA_API_URL}/repos/${GITEA_REPO}/releases" 2>/dev/null | grep '"tag_name"' | sed -E 's/.*"tag_name"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/' | head -20)
if [ -z "$versions" ]; then if [ -z "$versions" ]; then
print_error "$(msg 'failed_get_version')" print_error "$(msg 'failed_get_version')"
@@ -521,11 +523,11 @@ validate_version() {
# Check if the release exists # Check if the release exists
local http_code local http_code
http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 10 --max-time 30 "https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${version}" 2>/dev/null) http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 10 --max-time 30 "${GITEA_API_URL}/repos/${GITEA_REPO}/releases/tags/${version}" 2>/dev/null)
# Check for network errors (empty or non-numeric response) # Check for network errors (empty or non-numeric response)
if [ -z "$http_code" ] || ! [[ "$http_code" =~ ^[0-9]+$ ]]; then if [ -z "$http_code" ] || ! [[ "$http_code" =~ ^[0-9]+$ ]]; then
print_error "Network error: Failed to connect to GitHub API" >&2 print_error "Network error: Failed to connect to Gitea API" >&2
exit 1 exit 1
fi fi
@@ -554,8 +556,19 @@ get_current_version() {
download_and_extract() { download_and_extract() {
local version_num=${LATEST_VERSION#v} local version_num=${LATEST_VERSION#v}
local archive_name="sub2api_${version_num}_${OS}_${ARCH}.tar.gz" local archive_name="sub2api_${version_num}_${OS}_${ARCH}.tar.gz"
local download_url="https://github.com/${GITHUB_REPO}/releases/download/${LATEST_VERSION}/${archive_name}" local release_json
local checksum_url="https://github.com/${GITHUB_REPO}/releases/download/${LATEST_VERSION}/checksums.txt" local download_url
local checksum_url
release_json=$(curl -s --connect-timeout 10 --max-time 30 "${GITEA_API_URL}/repos/${GITEA_REPO}/releases/tags/${LATEST_VERSION}" 2>/dev/null || true)
download_url=$(printf '%s' "$release_json" | tr '{' '\n' | grep "\"name\"[[:space:]]*:[[:space:]]*\"${archive_name}\"" | sed -n -E 's/.*"browser_download_url"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' | head -1)
checksum_url=$(printf '%s' "$release_json" | tr '{' '\n' | grep '"name"[[:space:]]*:[[:space:]]*"checksums.txt"' | sed -n -E 's/.*"browser_download_url"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' | head -1)
if [ -z "$download_url" ]; then
print_error "$(msg 'download_failed'): ${archive_name}"
print_info "No matching release asset found at ${GITEA_BASE_URL}/${GITEA_REPO}/releases/tag/${LATEST_VERSION}"
exit 1
fi
print_info "$(msg 'downloading') ${archive_name}..." print_info "$(msg 'downloading') ${archive_name}..."
@@ -571,7 +584,7 @@ download_and_extract() {
# Download and verify checksum # Download and verify checksum
print_info "$(msg 'verifying_checksum')" print_info "$(msg 'verifying_checksum')"
if curl -sL "$checksum_url" -o "$TEMP_DIR/checksums.txt" 2>/dev/null; then if [ -n "$checksum_url" ] && curl -sL "$checksum_url" -o "$TEMP_DIR/checksums.txt" 2>/dev/null; then
local expected_checksum=$(grep "$archive_name" "$TEMP_DIR/checksums.txt" | awk '{print $1}') local expected_checksum=$(grep "$archive_name" "$TEMP_DIR/checksums.txt" | awk '{print $1}')
local actual_checksum=$(sha256sum "$TEMP_DIR/$archive_name" | awk '{print $1}') local actual_checksum=$(sha256sum "$TEMP_DIR/$archive_name" | awk '{print $1}')
@@ -655,7 +668,7 @@ install_service() {
cat > /etc/systemd/system/sub2api.service << EOF cat > /etc/systemd/system/sub2api.service << EOF
[Unit] [Unit]
Description=Sub2API - AI API Gateway Platform Description=Sub2API - AI API Gateway Platform
Documentation=https://github.com/Wei-Shaw/sub2api Documentation=http://git.jianshixingqiu.com/kgod/sub2api
After=network.target postgresql.service redis.service After=network.target postgresql.service redis.service
Wants=postgresql.service redis.service Wants=postgresql.service redis.service
+4 -4
View File
@@ -119,8 +119,8 @@ https://pay.example.com/pay?user_id=123&token=<jwt>&theme=light&lang=zh&ui_mode=
- 重试保持相同 `code`,并使用新的 `Idempotency-Key` - 重试保持相同 `code`,并使用新的 `Idempotency-Key`
### 6) `doc_url` 配置建议 ### 6) `doc_url` 配置建议
- 查看链接:`https://github.com/Wei-Shaw/sub2api/blob/main/ADMIN_PAYMENT_INTEGRATION_API.md` - 查看链接:`http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/ADMIN_PAYMENT_INTEGRATION_API.md`
- 下载链接:`https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/ADMIN_PAYMENT_INTEGRATION_API.md` - 下载链接:`http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/ADMIN_PAYMENT_INTEGRATION_API.md`
--- ---
@@ -239,5 +239,5 @@ https://pay.example.com/pay?user_id=123&token=<jwt>&theme=light&lang=zh&ui_mode=
- Keep the same `code` for retry, and use a new `Idempotency-Key` - Keep the same `code` for retry, and use a new `Idempotency-Key`
### 6) Recommended `doc_url` ### 6) Recommended `doc_url`
- View URL: `https://github.com/Wei-Shaw/sub2api/blob/main/ADMIN_PAYMENT_INTEGRATION_API.md` - View URL: `http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/ADMIN_PAYMENT_INTEGRATION_API.md`
- Download URL: `https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/ADMIN_PAYMENT_INTEGRATION_API.md` - Download URL: `http://git.jianshixingqiu.com/kgod/sub2api/raw/branch/main/ADMIN_PAYMENT_INTEGRATION_API.md`
+1 -1
View File
@@ -31,7 +31,7 @@ export async function getVersion(): Promise<{ version: string }> {
/** /**
* Check for updates * Check for updates
* @param force - Force refresh from GitHub API * @param force - Force refresh from Gitea API
*/ */
export async function checkUpdates(force = false): Promise<VersionInfo> { export async function checkUpdates(force = false): Promise<VersionInfo> {
const { data } = await apiClient.get<VersionInfo>('/admin/system/check-updates', { const { data } = await apiClient.get<VersionInfo>('/admin/system/check-updates', {
+1 -1
View File
@@ -128,7 +128,7 @@
<a <a
v-if="authStore.isAdmin" v-if="authStore.isAdmin"
href="https://github.com/Wei-Shaw/sub2api" href="http://git.jianshixingqiu.com/kgod/sub2api"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
@click="closeDropdown" @click="closeDropdown"
+1 -1
View File
@@ -467,7 +467,7 @@ const isHomeContentUrl = computed(() => {
const { isDarkTheme: isDark, toggleTheme } = useTheme() const { isDarkTheme: isDark, toggleTheme } = useTheme()
// GitHub URL // GitHub URL
const githubUrl = 'https://github.com/Wei-Shaw/sub2api' const githubUrl = 'http://git.jianshixingqiu.com/kgod/sub2api'
// Auth state // Auth state
const isAuthenticated = computed(() => authStore.isAuthenticated) const isAuthenticated = computed(() => authStore.isAuthenticated)
+1 -1
View File
@@ -376,7 +376,7 @@ const appStore = useAppStore()
const siteName = computed(() => appStore.cachedPublicSettings?.site_name || appStore.siteName || 'Sub2API') const siteName = computed(() => appStore.cachedPublicSettings?.site_name || appStore.siteName || 'Sub2API')
const siteLogo = computed(() => appStore.cachedPublicSettings?.site_logo || appStore.siteLogo || '') const siteLogo = computed(() => appStore.cachedPublicSettings?.site_logo || appStore.siteLogo || '')
const docUrl = computed(() => appStore.cachedPublicSettings?.doc_url || appStore.docUrl || '') const docUrl = computed(() => appStore.cachedPublicSettings?.doc_url || appStore.docUrl || '')
const githubUrl = 'https://github.com/Wei-Shaw/sub2api' const githubUrl = 'http://git.jianshixingqiu.com/kgod/sub2api'
// ==================== Theme (same as HomeView) ==================== // ==================== Theme (same as HomeView) ====================
+4 -4
View File
@@ -6571,14 +6571,14 @@ function applyCustomMenuIcon(item: { icon_svg: string }, optionID: string) {
const paymentGuideHref = computed(() => const paymentGuideHref = computed(() =>
locale.value.startsWith("zh") locale.value.startsWith("zh")
? "https://github.com/Wei-Shaw/sub2api/blob/main/docs/PAYMENT_CN.md" ? "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/docs/PAYMENT_CN.md"
: "https://github.com/Wei-Shaw/sub2api/blob/main/docs/PAYMENT.md", : "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/docs/PAYMENT.md",
); );
const paymentMethodsHref = computed(() => const paymentMethodsHref = computed(() =>
locale.value.startsWith("zh") locale.value.startsWith("zh")
? "https://github.com/Wei-Shaw/sub2api/blob/main/docs/PAYMENT_CN.md#支持的支付方式" ? "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/docs/PAYMENT_CN.md#支持的支付方式"
: "https://github.com/Wei-Shaw/sub2api/blob/main/docs/PAYMENT.md#supported-payment-methods", : "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/docs/PAYMENT.md#supported-payment-methods",
); );
type SettingsTab = type SettingsTab =
@@ -557,10 +557,10 @@ describe("admin SettingsView payment visible method controls", () => {
expect(paymentLinks).toHaveLength(2); expect(paymentLinks).toHaveLength(2);
expect(paymentLinks[0]?.attributes("href")).toBe( expect(paymentLinks[0]?.attributes("href")).toBe(
"https://github.com/Wei-Shaw/sub2api/blob/main/docs/PAYMENT_CN.md", "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/docs/PAYMENT_CN.md",
); );
expect(paymentLinks[1]?.attributes("href")).toBe( expect(paymentLinks[1]?.attributes("href")).toBe(
"https://github.com/Wei-Shaw/sub2api/blob/main/docs/PAYMENT_CN.md#支持的支付方式", "http://git.jianshixingqiu.com/kgod/sub2api/src/branch/main/docs/PAYMENT_CN.md#支持的支付方式",
); );
for (const link of paymentLinks) { for (const link of paymentLinks) {
expect(link.attributes("href")).toContain("docs/PAYMENT"); expect(link.attributes("href")).toContain("docs/PAYMENT");