diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c9e9de9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,49 @@ +# Git +.git +.gitignore +.gitattributes + +# Dependencies (rebuilt in Docker) +backend/vendor +frontend/node_modules + +# Runtime artifacts +backend/data +backend/.env.local +backend/.server.pid +frontend/.vite.pid +frontend/.node_platform +logs +*.log +*.db +*.db-shm +*.db-wal + +# Build artifacts +*.tar.gz +*.zip + +# IDE +.vscode +.claude +.idea + +# Docker files +Dockerfile +docker-compose.yml +.env.example +.env +.dockerignore +docker-init.sh + +# Deployment scripts (not needed in image) +一键初始化.bat +一键初始化.sh +一键运行.bat +一键运行.sh +scripts +deploy + +# README +README.md +LICENSE \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3b06dfd --- /dev/null +++ b/.env.example @@ -0,0 +1,37 @@ +# ======================================== +# BitAPI Docker 环境变量 +# 复制为 .env 并修改后使用 +# cp .env.example .env +# ======================================== + +# 站点名称(会显示在页面标题、导航栏等位置) +BITAPI_APP_NAME=BitAPI + +# 环境:production / development +BITAPI_ENV=production + +# 对外端口(docker-compose 端口映射使用) +BITAPI_HTTP_PORT=8091 + +# JWT 签名密钥(必须修改!建议 48 字节随机串) +# 生成方式:openssl rand -base64 48 +BITAPI_JWT_SECRET=change-me-in-production + +# 数据加密密钥(必须修改!建议 32 字节随机串) +# 生成方式:openssl rand -base64 32 +BITAPI_ENCRYPTION_KEY=change-me-encryption-key-32-bytes + +# Token 有效期 +BITAPI_ACCESS_TOKEN_TTL=30m +BITAPI_REFRESH_TOKEN_TTL=336h + +# CORS 允许的域名(逗号分隔,支持 https://*.domain.com 通配) +BITAPI_CORS_ORIGINS=http://localhost:8091,http://127.0.0.1:8091 + +# 初始管理员账号(首次启动时自动创建) +BITAPI_BOOTSTRAP_EMAIL=admin@bitapi.local +BITAPI_BOOTSTRAP_PASSWORD=bitapi-admin +BITAPI_BOOTSTRAP_NAME=BitAPI 管理员 + +# 新用户默认余额(单位:微单位,0 表示 0) +BITAPI_DEFAULT_USER_BALANCE_MICROS=0 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8273cb --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +# --- OS junk --- +.DS_Store +Thumbs.db + +# --- IDE / Editor --- +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# --- Environment & Secrets --- +.env +*.env +!.env.example +!backend/config.example.env + +# --- Go (backend) --- +backend/cmd/*/main +backend/cmd/*/*.exe +*.test +*.out +*.prof +vendor/ + +# --- Node (frontend) --- +frontend/node_modules/ +frontend/dist/ +*.tsbuildinfo + +# --- Logs --- +*.log +logs/ + +# --- Docker --- +docker-compose.override.yml + +# --- OS / Misc --- +__pycache__/ +*.pyc +tmp/ +temp/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..83e417d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +# BitAPI - Multi-stage Docker build +# Stage 1: Build Vue 3 frontend +FROM node:20-alpine AS frontend-build +WORKDIR /app/frontend +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci +COPY frontend/ ./ +RUN npm run build + +# Stage 2: Build Go backend (CGO_ENABLED=0, glebarez/sqlite is pure Go) +FROM golang:1.23-alpine AS backend-build +ENV GOTOOLCHAIN=auto +ENV GOPROXY=https://goproxy.cn,direct +WORKDIR /app +COPY backend/go.mod backend/go.sum ./ +RUN go mod download +COPY backend/ ./ +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o server ./cmd/server + +# Stage 3: Minimal runtime +FROM alpine:3.21 +RUN apk add --no-cache ca-certificates curl +WORKDIR /app +COPY --from=frontend-build /app/frontend/dist /app/frontend/dist +COPY --from=backend-build /app/server /app/server + +RUN mkdir -p /app/data/uploads/avatars + +EXPOSE 8091 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -fsS http://localhost:8091/health || exit 1 + +ENV BITAPI_DATABASE_DSN="file:/app/data/bitapi.db?_foreign_keys=on&_busy_timeout=5000" + +ENTRYPOINT ["/app/server"] \ No newline at end of file diff --git a/README.md b/README.md index 0c85383..c86a314 100644 --- a/README.md +++ b/README.md @@ -1,508 +1,142 @@ -# BitAPI Release 使用教程 +# BitAPI -BitAPI 是一个中文 AI API Gateway,后端使用 Go、Gin、GORM、SQLite,前端使用 Vue 3、TypeScript、Arco Design Vue。 +中文 AI API Gateway — 统一管理和分发 AI 模型接口,支持多上游账号、用户配额、计费支付、品牌定制。 -本发布版采用手动初始化模式:发布目录不内置数据库,也不内置默认管理员密码。首次部署必须运行初始化脚本,由部署者自己填写站点名称、管理员账号、名称和密码。 +后端 Go · Gin · GORM · SQLite | 前端 Vue 3 · TypeScript · Arco Design -初始化后也可以在后台 `系统设置 -> 产品品牌配置` 里继续修改站点名称、Logo 和版权信息。 +## 功能 -## 一、目录说明 +- **OpenAI 兼容接口** — `/v1/chat/completions`、`/v1/responses`、`/v1/models`,任何 OpenAI SDK 直接接入 +- **多上游管理** — 配置多个 API 账号,按分组分配模型,负载均衡、故障切换 +- **用户体系** — 注册/登录、API Key 管理、用量统计、充值兑换 +- **计费 & 支付** — 用量计费、余额扣除、多支付通道 +- **管理后台** — 用户管理、分组配置、订单审核、兑换码、数据统计 +- **品牌定制** — 站点名称、Logo(浅色/深色/侧边栏)、版权信息全部可换 +- **安全** — 无默认密码,首次部署强制手动初始化;JWT 鉴权、API Key 认证 -```text -BitAPI_Release -├─ backend/ 后端源码、配置和 SQLite 数据目录 -├─ frontend/ 前端源码和 dist 构建产物 -├─ deploy/ 宝塔/Nginx 示例配置 -├─ docs/ 架构文档 -├─ logs/ 运行日志目录 -├─ scripts/ 初始化和启动脚本 -├─ 一键初始化.bat Windows 初始化 -├─ 一键初始化.sh Linux 初始化 -├─ 一键运行.bat Windows 启动 -├─ 一键运行.sh Linux 启动 -└─ README.md -``` - -## 二、运行要求 - -服务器需要安装: - -- Go 1.22 或更高版本 -- Node.js 20 或更高版本 -- npm -- Nginx,宝塔面板自带即可 +## 快速开始 -查看版本: +### 方式一:Docker(推荐) ```bash -go version -node -v -npm -v -nginx -v -``` - -## 三、端口说明 - -BitAPI 默认使用: - -```text -8091 -``` - -本地访问: - -```text -http://127.0.0.1:8091 -``` +# 1. 初始化(生成密钥和配置) +bash docker-init.sh -线上推荐方式: +# 2. 启动 +docker compose up -d --build -```text -Nginx 直接返回 frontend/dist 静态文件 -Nginx 只把 /api、/v1、/responses、/uploads、/health 转发给 127.0.0.1:8091 +# 3. 访问 +# http://localhost:8091/auth/login ``` -不要再使用 `5181`,不要再启动 `vite preview`。 +数据库和上传文件通过 Docker volume 持久化,删除容器不会丢数据。配置文件在 `.env`,按需修改端口、管理员信息等。 -## 四、Linux 首次初始化 +### 方式二:手动部署 -进入发布目录: +**要求:** Go ≥1.22、Node.js ≥20、npm、Nginx ```bash -cd /www/wwwroot/demo -``` - -给脚本执行权限: +# 1. 上传整个项目目录到服务器 +# 2. 进入目录 +cd /path/to/BitAPI -```bash +# 3. 赋权 chmod +x 一键初始化.sh 一键运行.sh scripts/init.sh scripts/run.sh -``` -运行初始化: - -```bash +# 4. 初始化(会提示填写站点名、管理员账号/密码等) bash 一键初始化.sh -``` - -脚本会用中文提示: - -```text -请输入站点/产品名称 -请输入管理员账号邮箱 -请输入管理员名称 -请输入管理员密码,输入过程会直接显示,请认真核对 -请输入服务监听地址 -``` - -密码会直接显示,这是为了避免输错一位还看不见。请在安全的终端环境里输入。 - -初始化会清空并重建: - -```text -backend/data/bitapi.db -backend/data/bitapi.db-shm -backend/data/bitapi.db-wal -``` - -初始化完成后会生成: - -```text -backend/.env.local -``` - -## 五、Windows 首次初始化 - -双击: -```text -一键初始化.bat -``` - -或者在 PowerShell 执行: - -```powershell -.\一键初始化.bat -``` - -同样会要求填写站点名称、管理员账号、名称、密码和监听地址。 - -## 六、修改产品品牌 - -管理员登录后台后,进入 `系统设置 -> 产品品牌配置`,可以修改: - -- 站点名称,例如 FitAI、AaaAI 或自己的产品名 -- 浅色 Logo,显示在首页导航、登录页、控制台和后台侧边栏 -- 深色 Logo,显示在首页底边栏等深色区域 -- 侧边栏收缩 Logo,建议使用方形图标 -- 版权信息 - -Logo 支持直接上传,文件会保存到 `/uploads/branding/`。Nginx 配置里需要保留 `/uploads/` 转发规则,否则上传后的 Logo 无法访问。 - -## 七、启动服务 - -Linux: - -```bash +# 5. 启动 bash 一键运行.sh ``` -Windows: - -```powershell -.\一键运行.bat -``` - -启动脚本会自动: - -- 停止旧的 `8080`、`5173`、`5181`、`8091` 端口进程 -- 安装或刷新前端依赖 -- 构建 `frontend/dist` -- 启动 Go 后端 -- 等 `/health` 正常后再提示启动完成 - -日志位置: +启动后服务监听 `:8091`,前端静态文件 + API 都在同端口。日志在 `logs/` 目录。 -```text -logs/backend.log -logs/backend.err.log -``` - -## 八、手动停止旧进程 +## 访问地址 -如果需要手动杀掉旧服务: +| 地址 | 说明 | +|---|---| +| `/` | 前台首页 | +| `/auth/login` | 管理后台登录 | +| `/health` | 健康检查 | +| `/v1/chat/completions` | OpenAI 兼容接口 | +| `/v1/models` | 模型列表 | -```bash -lsof -ti tcp:8091 | xargs -r kill -9 -``` +网关 base URL 直接填域名或 IP + 端口即可。 -如果服务器没有 `lsof`: - -```bash -fuser -k 8091/tcp -``` - -确认端口是否还在: - -```bash -ss -lntp | grep 8091 -``` +## 品牌定制 -没有输出就表示旧进程已停止。 +登录后台 → `系统设置 → 产品品牌配置`: -## 九、宝塔面板推荐配置 - -推荐使用“静态文件直出 + API 反代”的方式,不要整站反代。这样前端 JS/CSS/图片由 Nginx 直接返回,速度更快。 - -宝塔网站根目录设置为: - -```text -/www/wwwroot/demo/frontend/dist -``` - -Go 后端仍然监听: - -```text -127.0.0.1:8091 -``` - -宝塔配置注意事项: - -- 不要启用宝塔的整站反向代理 -- 如果之前创建过反向代理,请删除或注释 `proxy/demo.bitit.cn/*.conf` -- 防盗链如果开启,需要放行 `/bitapi-assets/` -- WAF 如果拦截 JS/CSS,先临时关闭测试 -- 修改 Nginx 配置后必须重载 Nginx - -完整 `server` 配置示例: - -```nginx -server -{ - listen 80; - listen 443 ssl; - listen 443 quic; - listen [::]:443 ssl; - listen [::]:443 quic; - listen [::]:80; - http2 on; - http3 on; - - server_name demo.bitit.cn; - index index.html index.htm default.html; - root /www/wwwroot/demo/frontend/dist; - - include /www/server/panel/vhost/nginx/well-known/demo.bitit.cn.conf; - include /www/server/panel/vhost/nginx/extension/demo.bitit.cn/*.conf; - - ssl_certificate /www/server/panel/vhost/cert/demo.bitit.cn/fullchain.pem; - ssl_certificate_key /www/server/panel/vhost/cert/demo.bitit.cn/privkey.pem; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:!MD5; - ssl_prefer_server_ciphers on; - ssl_session_tickets on; - ssl_session_cache shared:SSL:10m; - ssl_session_timeout 10m; - - add_header Strict-Transport-Security "max-age=31536000" always; - add_header Alt-Svc 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443"' always; - - quic_retry on; - quic_gso on; - ssl_early_data on; - error_page 497 https://$host$request_uri; - - set $isRedcert 1; - if ($server_port != 443) { - set $isRedcert 2; - } - if ($uri ~ /\.well-known/) { - set $isRedcert 1; - } - if ($isRedcert != 1) { - rewrite ^(/.*)$ https://$host$1 permanent; - } - - # 重要:不要再引用宝塔自动生成的整站反向代理规则。 - # include /www/server/panel/vhost/nginx/proxy/demo.bitit.cn/*.conf; - - location ^~ /bitapi-assets/ { - try_files $uri =404; - expires 30d; - add_header Cache-Control "public, max-age=2592000, immutable" always; - } - - location = /favicon.png { - try_files /favicon.png =404; - expires 7d; - add_header Cache-Control "public, max-age=604800" always; - } - - location ^~ /api/ { - proxy_pass http://127.0.0.1:8091; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_connect_timeout 60s; - proxy_send_timeout 300s; - proxy_read_timeout 300s; - } - - location ^~ /v1/ { - proxy_pass http://127.0.0.1:8091; - proxy_http_version 1.1; - proxy_buffering off; - proxy_cache off; - proxy_read_timeout 600s; - proxy_send_timeout 600s; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } - - location = /responses { - proxy_pass http://127.0.0.1:8091; - proxy_http_version 1.1; - proxy_buffering off; - proxy_cache off; - proxy_read_timeout 600s; - proxy_send_timeout 600s; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } - - location ^~ /uploads/ { - proxy_pass http://127.0.0.1:8091; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } - - location = /health { - proxy_pass http://127.0.0.1:8091; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - } - - location / { - try_files $uri $uri/ /index.html; - add_header Cache-Control "no-cache" always; - } - - location ~* (\.user.ini|\.htaccess|\.htpasswd|\.env.*|\.project|\.bashrc|\.bash_profile|\.bash_logout|\.DS_Store|\.gitignore|\.gitattributes|LICENSE|README\.md|CLAUDE\.md|CHANGELOG\.md|CHANGELOG|CONTRIBUTING\.md|TODO\.md|FAQ\.md|composer\.json|composer\.lock|package(-lock)?\.json|yarn\.lock|pnpm-lock\.yaml|\.\w+~|\.swp|\.swo|\.bak(up)?|\.old|\.tmp|\.temp|\.log|\.sql(\.gz)?|docker-compose\.yml|docker\.env|Dockerfile|\.csproj|\.sln|Cargo\.toml|Cargo\.lock|go\.mod|go\.sum|phpunit\.xml|pom\.xml|build\.gradl|pyproject\.toml|requirements\.txt|application(-\w+)?\.(ya?ml|properties))$ - { - return 404; - } - - location ~* /(\.git|\.svn|\.bzr|\.vscode|\.claude|\.idea|\.ssh|\.github|\.npm|\.yarn|\.pnpm|\.cache|\.husky|\.turbo|\.next|\.nuxt|node_modules|runtime)/ { - return 404; - } - - location ~ \.well-known { - allow all; - } - - if ($uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$") { - return 403; - } - - access_log /www/wwwlogs/demo.bitit.cn.log; - error_log /www/wwwlogs/demo.bitit.cn.error.log; -} -``` - -改完检查 Nginx: - -```bash -nginx -t -/etc/init.d/nginx reload -``` - -## 十、访问地址 - -前台首页: - -```text -https://你的域名/ -``` - -管理后台登录: - -```text -https://你的域名/auth/login -``` - -健康检查: - -```text -https://你的域名/health -``` - -网关地址: - -```text -https://你的域名 -``` - -Codex 或 OpenAI 风格客户端推荐: - -```text -base_url = https://你的域名 -``` - -支持接口: - -```text -GET /v1/models -POST /v1/chat/completions -POST /v1/responses -POST /responses -``` - -## 十一、常见问题 - -### 1. 页面空白,控制台提示 JS/CSS 403 - -通常是宝塔防盗链、WAF、整站反代或 CORS 配置导致。 - -处理方式: - -- 确认 `/bitapi-assets/` 是 Nginx 静态文件直出 -- 注释或删除宝塔整站反代 include -- 防盗链放行 `/bitapi-assets/` -- WAF 临时关闭测试 -- 检查 `backend/.env.local` 里的 `BITAPI_CORS_ORIGINS` - -推荐包含: - -```text -https://你的域名,https://*.你的主域名 -``` +- 站点名称 +- 浅色 Logo(导航栏、登录页、控制台) +- 深色 Logo(底部栏等深色区域) +- 侧边栏收缩 Logo(建议方形图标) +- 版权信息 -示例: +Logo 上传后保存到 `/uploads/branding/`,Nginx 需保留 `/uploads/` 转发。 -```text -https://demo.bitit.cn,https://*.bitit.cn -``` +## 常见问题 -### 2. 初始化后登录不了 +**页面空白 / JS / CSS 403** +- 检查宝塔是否开了整站反代(删除或注释 `proxy/*.conf`) +- 防盗链放行 `/bitapi-assets/`,WAF 临时关闭测试 +- CORS 配置:`BITAPI_CORS_ORIGINS` 需包含你的域名 -检查: - -- 管理员邮箱是不是初始化时输入的邮箱 -- 密码是不是初始化时输入的密码 +**初始化后登录失败** +- 确认管理员邮箱和密码是否与初始化时一致 - 查看 `logs/init-backend.err.log` - 确认 `backend/data/bitapi.db` 已生成 -### 3. 反向代理很慢 - -不要整站反代。推荐: - -```text -Nginx 直出 frontend/dist -Go 只处理 API -``` - -确认没有代理到: - -```text -127.0.0.1:5181 -``` - -### 4. 如何重新初始化 - -重新初始化会清空数据库。 - -Linux: +**反向代理慢** +- 不要整站反代。Nginx 直出 `frontend/dist`,Go 只处理 API +- 确认代理目标是 `127.0.0.1:8091`,不是 `:5181` +**重新初始化** ```bash -bash 一键初始化.sh +bash 一键初始化.sh # 会清空数据库 ``` -Windows: +## 技术架构 -```powershell -.\一键初始化.bat ``` - -### 5. 如何只重启服务 - -Linux: - -```bash -bash 一键运行.sh +请求 → Nginx (HTTPS + 静态文件) → Go Backend (:8091) + 静态文件由 frontend/dist 直出 ├─ /api/* 管理 API + API 请求反代到 Go 后端 ├─ /v1/* OpenAI 兼容接口 + ├─ /uploads 文件服务 + └─ SQLite 数据存储 ``` -Windows: +后端目录: -```powershell -.\一键运行.bat +``` +backend/ +├── cmd/server/main.go 入口 +└── internal/ + ├── config/ 环境变量 + ├── db/ SQLite 初始化与迁移 + ├── http/ 路由、Handler、中间件、响应封装 + ├── models/ GORM 数据模型 + ├── pkg/crypto/ 密码哈希 + └── services/ + ├── adapters/ AI 厂商适配器 (OpenAI) + ├── auth/ 认证与 JWT + ├── billing/ 计费 + ├── gateway/ 核心转发 + ├── keys/ API Key 管理 + ├── monitor/ 统计监控 + ├── payments/ 支付通道 + └── ratelimit/ 限流 ``` -## 十二、发布注意事项 +## Nginx 配置参考 -正式发布前,发布目录不应包含: +**Docker 部署无需 Nginx**,后端已内置静态文件服务。以下仅供手动部署 + 宝塔面板参考。 -```text -backend/data/*.db -backend/data/*.db-shm -backend/data/*.db-wal -logs/*.log -backend/.server.pid -frontend/.vite.pid -*.zip -``` +完整示例见 [`deploy/nginx-bitapi.conf`](deploy/nginx-bitapi.conf)。 -本发布目录已经按这个规则清理。部署时请直接上传整个 `BitAPI_Release` 文件夹,不需要压缩包。 +核心规则: +- 网站根目录设为 `frontend/dist` +- 只反代以下路径到 `127.0.0.1:8091`:`/api/`、`/v1/`、`/responses`、`/uploads/`、`/health` +- 不要开整站反代 +- 防盗链放行 `/bitapi-assets/` \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7a4fa74 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +# BitAPI - Single-container deployment +# Backend serves API + static frontend, no separate Nginx needed. +# +# First-time setup: +# 1. cp .env.example .env +# 2. Edit .env (set JWT secret, admin email/password, etc.) +# 3. docker compose up -d +# 4. Admin login at http://localhost:8091/auth/login + +services: + bitapi: + build: . + container_name: bitapi + restart: unless-stopped + ports: + - "${BITAPI_HTTP_PORT:-8091}:8091" + environment: + - BITAPI_APP_NAME=${BITAPI_APP_NAME:-BitAPI} + - BITAPI_ENV=${BITAPI_ENV:-production} + - BITAPI_HTTP_ADDR=:8091 + - BITAPI_DATABASE_DSN=file:/app/data/bitapi.db?_foreign_keys=on&_busy_timeout=5000 + - BITAPI_JWT_SECRET=${BITAPI_JWT_SECRET:-change-me-in-production} + - BITAPI_ACCESS_TOKEN_TTL=${BITAPI_ACCESS_TOKEN_TTL:-30m} + - BITAPI_REFRESH_TOKEN_TTL=${BITAPI_REFRESH_TOKEN_TTL:-336h} + - BITAPI_CORS_ORIGINS=${BITAPI_CORS_ORIGINS:-http://localhost:8091,http://127.0.0.1:8091} + - BITAPI_BOOTSTRAP_EMAIL=${BITAPI_BOOTSTRAP_EMAIL:-admin@bitapi.local} + - BITAPI_BOOTSTRAP_PASSWORD=${BITAPI_BOOTSTRAP_PASSWORD:-bitapi-admin} + - BITAPI_BOOTSTRAP_NAME=${BITAPI_BOOTSTRAP_NAME:-BitAPI 管理员} + - BITAPI_ENCRYPTION_KEY=${BITAPI_ENCRYPTION_KEY:-dev-bitapi-encryption-key-32bytes} + - BITAPI_DEFAULT_USER_BALANCE_MICROS=${BITAPI_DEFAULT_USER_BALANCE_MICROS:-0} + volumes: + - bitapi_data:/app/data + - bitapi_uploads:/app/data/uploads + +volumes: + bitapi_data: + bitapi_uploads: \ No newline at end of file diff --git a/docker-init.sh b/docker-init.sh new file mode 100644 index 0000000..8ae8fc9 --- /dev/null +++ b/docker-init.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# BitAPI Docker 快速初始化脚本 +# 生成安全的随机密钥,创建 .env 文件 +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")" && pwd)" +ENV_FILE="$ROOT/.env" + +if [[ -f "$ENV_FILE" ]]; then + echo "⚠️ .env 已存在,将被覆盖。" + read -r -p "输入 YES 继续: " confirm + if [[ "$confirm" != "YES" ]]; then + echo "已取消。" + exit 0 + fi +fi + +echo "" +echo "════════════════════════════════════" +echo " BitAPI Docker 初始化" +echo "════════════════════════════════════" +echo "" + +read -r -p "站点名称 [BitAPI]: " APP_NAME +APP_NAME="${APP_NAME:-BitAPI}" + +read -r -p "管理员邮箱 [admin@bitapi.local]: " ADMIN_EMAIL +ADMIN_EMAIL="${ADMIN_EMAIL:-admin@bitapi.local}" + +read -r -p "管理员昵称 [${APP_NAME} 管理员]: " ADMIN_NAME +ADMIN_NAME="${ADMIN_NAME:-${APP_NAME} 管理员}" + +read -r -p "管理员密码 (明文显示,请注意安全) [bitapi-admin]: " ADMIN_PASSWORD +ADMIN_PASSWORD="${ADMIN_PASSWORD:-bitapi-admin}" + +read -r -p "对外端口 [8091]: " HTTP_PORT +HTTP_PORT="${HTTP_PORT:-8091}" + +JWT_SECRET=$(openssl rand -base64 48 2>/dev/null || python3 -c "import base64,os; print(base64.b64encode(os.urandom(48)).decode())") +ENCRYPTION_KEY=$(openssl rand -base64 32 2>/dev/null || python3 -c "import base64,os; print(base64.b64encode(os.urandom(32)).decode())") + +cat > "$ENV_FILE" <