Files
FileShare/docs/api/10-config.md
T
SKYMirror 84df9996cb
CI 测试 / go vet + go test (push) Successful in 49s
26.9:版本号统一 + CI 精简 + 前端产物重建
- 全项目版本号统一:v3.x 迭代号(26.9/26.9/26.9/26.9 及裸 v2/v3)→ 26.9,
  覆盖 Go 注释 / 文档 / openapi.yaml / README×4 / 前端源码(80+ 处)
- v31_test.go 更名 custom_code_test.go;TestV2AccessorDefaults → TestKVAccessorDefaults
- docs/api/00-overview.md 更新日志合并为单条 26.9 条目(修复错位拼接)
- .goreleaser.yaml 头部注释与实际一致(Pro 2.18.1 / GITEA_TOKEN / semver tag 要求)
- CI:release-image.yml → ci.yml,仅保留 vet+test 门禁;
  镜像发布移交 GoReleaser Pro(原 build-push 的 tag 校验与 26.9 版本方案冲突,历史 9 次失败)
- 前端重建:server/web/dist 与 web-embed 同步(docs 文案嵌入更新)
2026-09-08 03:16:51 +08:00

192 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 环境变量与配置项
配置分三层:**默认值 → `FCB_*` 环境变量 → 数据库 settings KV(管理端运行时修改)**。
26.9 起进程必需的环境变量为空集:数据库默认 **SQLite**modernc.org/sqlite 纯 Go 驱动,零外部依赖,
DSN 缺省落 `./data/fileshare.db`);`FCB_DB_DRIVER=postgres``FCB_DB_DSN` 必需(需求 ⑧)。
## 环境变量(进程级)
| 变量 | 必需 | 默认 | 说明 |
|---|---|---|---|
| `FCB_DB_DRIVER` | ❌ | `sqlite` | 数据库驱动:`sqlite` / `postgres`(需求 ⑧) |
| `FCB_DB_DSN` | 视驱动 | `./data/fileshare.db` | postgres:连接串(**必需**,如 `postgres://user:pass@host:5432/filecodebox?sslmode=disable`);sqlite:数据库文件路径(可空,父目录自动创建) |
| `FCB_REDIS_ADDR` | ❌ | 空 | Redis 地址(如 `redis:6379`),也支持 `redis://[:password@]host:port[/db]` / `rediss://`(TLS)URL 形式;**空则缓存降级为进程内存实现**(缓存故障时自动降级为进程内限流计数) |
| `FCB_REDIS_DB` | ❌ | `0` | Redis 逻辑库号 0-15;URL 形式地址显式携带 `/N` 时以 URL 为准 |
| `FCB_ADMIN_PASSWORD` | ❌ | 空 | 设置后服务首次启动即自动初始化管理员(≥8 位,不足告警跳过),消除 `/setup` 被抢占窗口;初始化完成后建议移除 |
| `FCB_LISTEN` | ❌ | `:8466` | HTTP 监听地址 |
| `FCB_STORAGE_ENGINE` | ❌ | `local` | 存储引擎:`local` / `s3` / `webdav` |
| `FCB_TRUSTED_PROXIES` | ❌ | 空 | 可信代理 CIDR(逗号分隔),命中时从 `X-Forwarded-For` 解析真实客户端 IP |
- SQLite 连接参数(驱动自动注入):`busy_timeout=10s` + `WAL` 日志模式 + `foreign_keys=1`;连接池 8/4。
- Postgres 连接池沿用 v1 参数(32/8,1h 轮换);`FCB_DB_DRIVER=postgres` 且未设 `FCB_DB_DSN` 时**启动直接报错**。
引擎相关环境变量(种子注入 settings KV,见《存储引擎配置》):`FCB_LOCAL_STORAGE_PATH`
`FCB_STORAGE_PATH``FCB_S3_ACCESS_KEY_ID``FCB_S3_SECRET_ACCESS_KEY``FCB_AWS_SESSION_TOKEN`
`FCB_S3_BUCKET_NAME``FCB_S3_ENDPOINT_URL``FCB_S3_REGION_NAME``FCB_S3_ADDRESSING_STYLE`
`FCB_WEBDAV_URL``FCB_WEBDAV_USERNAME``FCB_WEBDAV_PASSWORD``FCB_WEBDAV_ROOT_PATH`
部署用编排变量(`deploy/.env.example`):`WEB_PORT`(默认 8466)、
`POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB`(默认 fileshare,仅 `--profile postgres` 时使用)。
## 配置项(settings KV,默认值对齐参考实现)
> 键名/类型/默认值/边界以 `server/internal/config/schema.go` 的 `KVSchema()` 为单一事实来源
> schema 同步测试保证与 defaults() 逐键一致);26.9 新增键统一 snake_case。
### 站点信息与展示(需求 ①②③)
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
| `site_name` / `name` | string | 文件快传 | 站点名称(`site_name` 优先) |
| `site_domain` | string,≤256 | 空 | **26.9**:站点对外域名(`http(s)://host[:port]`,不带路径;裸主机自动补 `http://`)。配置后分享链接(结果卡/管理端复制)用该域名生成——内网部署也能把公网链接发出去;留空=用当前访问地址 |
| `description` | string | 开箱即用的文件快传系统 | 站点描述 |
| `page_explain` | string | (合规声明) | 页面说明文案 |
| `keywords` | string | 文件快传, 文件分享… | SEO 关键词 |
| `logo_url` | string | 空(前端回落本地打包 `/assets/logo-*.svg`,需求 ⑤) | 页面导航 Logo,管理端可设任意 URL |
| `favicon_url` | string | 空(前端回落本地打包 `/assets/favicon-*.png`,需求 ⑤) | favicon / 备用 Logo |
| `opacity` | float | 0.9 | 界面不透明度 |
| `background` | string | 空 | 背景图 URL(参考实现既有键,v1 兼容保留) |
| `background_url` | string,≤2048 字符 | 空 | **26.9 需求 ①**:背景图 URL 或上传后地址(空=主题默认;取值时 legacy `background` 键兜底)。管理端保存时校验协议白名单:仅 `http(s)``data:image/*` 与站内相对路径(防 `javascript:` 注入,非法 400 |
| `footer_text` | string,≤2000 字符 | 空 | **26.9 需求 ②**:页脚自定义内容(纯文本或受控 HTML 片段) |
| `footer_beian` | string,≤128 字符 | 空 | **26.9 需求 ②**:备案号(如 `京ICP备2024xxxxxx号-1`),展示于页脚 |
| `notify_enabled` | int0/1 | 1 | **26.9 需求 ③**:通知开关(1=前台右上角悬浮窗展示 / 0=关闭) |
| `notify_title` | string,≤128 字符 | 系统通知 | 通知标题 |
| `notify_content` | string,≤2000 字符 | 欢迎使用… | 通知正文(**服务端白名单净化**:仅保留纯文本与 `<a href>` 为 http(s)/站内相对/`#` 锚点的链接,其余标签与事件属性剥离,保存与读取双侧生效) |
| `showAdminAddr` | int(0/1 | 0 | 是否展示后台入口 |
| `robotsText` | string | `User-agent: *\nDisallow: /` | robots.txt 内容(由公开端点 `GET /robots.txt` 输出) |
### 保存策略(需求 ④,上传页动态读取并在范围内选择)
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
| `max_save_seconds` | int640~31536000 | 0 | 最长保存秒数上限(0=仅默认 7 天兜底;>0 时按时间过期超限 403「限制最长时间为 X,可换用其他方式」)。**26.9**:管理界面以「小时/天」下拉单位编辑(≥1 天自动显示天),提交时前端换算为秒——canonical 单位保持秒,接口语义不变 |
| `max_save_count` | int0~100000 | 0 | **26.9 新增**:单次分享最大可取(保存)次数上限(0=不限制;`expire_style=count``expire_value` 超上限时 403「限制次数最多为 N 次」) |
| `expireStyle` | []string | `["day","hour","minute","forever","count"]` | 允许的过期方式白名单(上传时不在白名单 400「过期时间类型错误」) |
### 存储策略(需求 ④⑩)
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
| `uploadSize` | int641024~10GiB | 1048576010MB) | 单文件大小上限(字节),参考实现语义;`max_file_size=0` 时作为生效上限 |
| `max_file_size` | int640~10GiB | 0 | **26.9 新增**:存储策略-单文件上限(字节),0=回落 `uploadSize`;超出 403(文案 humanSize 自适应 B/KB/MB/GB)。**26.9**:管理界面以「MB/GB」下拉单位编辑(≥1 GiB 自动显示 GB),提交时前端换算为字节 |
| `allowed_file_types` | []string | `["*"]` | 允许类型白名单(扩展名/MIME 通配,`*` 不限制;非白名单 403「不允许上传该类型文件」) |
| `storageLimit` | int64,≥0 | 0 | 站点总容量(字节),0=不限制(超限 507) |
| `openUpload` | int0/1) | 1 | 游客上传开关(0 时上传接口要求管理员令牌 403) |
| `enableChunk` | int0/1 | 0 | 启用分片上传 |
### 上传频率限制(需求 ④,既有键对齐参考 ip_limit["upload"]
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
| `uploadCount` / `uploadMinute` | int1~10000 / 1~1440 | 10 / 1 | 窗口内允许上传次数 / 窗口分钟(上传成功才计数,超限 423;管理端修改后运行时同步限流规则,立即生效) |
| `upload_rate` / `download_rate` | int640~1 GiB/s | 0 / 0 | **26.9**:上下行带宽字节/秒,0=不限速;管理端改后立即生效(每请求动态读 KV)。详见《[带宽限速](13-bandwidth.md)》 |
| `errorCount` / `errorMinute` | int | 10 / 1 | 取件错误(失败计数)+ metadata 每次计数 |
| `loginCount` / `loginMinute` | int | 5 / 15 | 登录失败计数 |
### 安全与会话
| 键 | 默认 | 说明 |
|---|---|---|
| `admin_token` | 空(未初始化) | 管理员密码哈希(`sha256$salt$hash`);GET 配置时屏蔽为空串 |
| `jwt_secret` | 空 | JWT 签名密钥(初始化/改密时自动生成轮换;不下发;`settings.SensitiveKeys` 双模式下一致屏蔽) |
| `adminSessionExpire` | 604800(7 天) | 管理员会话秒数(须 1~365 整天) |
### 存储引擎(26.9 运行时可配 + 热切换)
**`storage_engine`**26.9 新增键):string`local|s3|webdav`,默认空=回落启动值 `FCB_STORAGE_ENGINE`
运行时切换走 **`POST /admin/storage/switch`**(JWT 保护):构建新引擎 → 健康检查通过才生效;
失败返回 503「存储引擎切换失败,已保持原引擎: …」且不改 KV。成功后持久化 `storage_engine`,重启沿用。
`GET /api/v1/config` 公开下发 `storage_engine` 当前名(仅名称,任何引擎参数/凭据不下发)。
引擎参数键(管理端可改;保存后对应引擎实例缓存失效,下次切换/构建生效):
| 键 | 默认 |
|---|---|
| `file_storage` | `local` |
| `storage_path` | 空 |
| `local_storage_path` | 空(容器内由 `FCB_LOCAL_STORAGE_PATH=/app/data` 注入) |
| `s3_access_key_id` / `s3_secret_access_key` / `aws_session_token` | 空 |
| `s3_bucket_name` / `s3_endpoint_url` / `s3_hostname` | 空 |
| `s3_region_name` | `auto` |
| `s3_signature_version` | `s3v4` |
| `s3_addressing_style` | `auto` |
| `s3_proxy` | 0 |
| `webdav_url` / `webdav_username` / `webdav_password` | 空 |
| `webdav_root_path` | `filebox_storage` |
| `webdav_proxy` | 0 |
> 敏感键 `webdav_password` / `s3_secret_access_key` / `aws_session_token`26.9 加入 `settings.SensitiveKeys`):
> 管理端 GET 返回掩码 `******`PATCH 时空串或 `******` 表示不修改。直接写库 settings KV 后重启同样生效。
## 策略动态生效机制(26.9 需求 ④⑩)
上传页通过 `GET /api/v1/config``config` 字段读取**当前策略快照**并在范围内渲染选项;
上传链路(`/share/file``/chunk/*``/presign/*`**每次请求实时读取** settings KV 同一组值校验:
- 管理端改策略(`PATCH /admin/config/update`)→ 公开 config 即时反映 → 后续上传立即按新策略执行(含 403/400 拒绝与恢复放行)。
- 生效上限:`max_file_size > 0` 时为 `max_file_size`,否则回落 `uploadSize`
- 校验点覆盖:单文件(`/share/file`)、分片 init 按分片数上限、分片上传累计、分片 complete 累计、预签名 init 声明大小,五处口径一致(`api.UploadPolicy.CheckSize`)。
## 公共配置接口
前端启动时经 `GET /api/v1/config` 获取站点公开配置(无需认证;26.9 扩展需求 ①②③④⑩):
```json
{
"code": 200, "msg": "ok",
"data": {
"config": {
"name": "文件快传",
"description": "开箱即用的文件快传系统",
"explain": "请勿上传或分享违法内容…",
"logo_url": "",
"favicon_url": "",
"background_url": "",
"footer_text": "自定义页脚内容",
"footer_beian": "京ICP备2024xxxxxx号-1",
"notify_enabled": 1,
"notify_title": "系统通知",
"notify_content": "欢迎使用文件快传…",
"uploadSize": 10485760,
"max_file_size": 10485760,
"maxFileSize": 10485760,
"allowedFileTypes": ["*"],
"expireStyle": ["day", "hour", "minute", "forever", "count"],
"max_save_seconds": 0,
"maxSaveSeconds": 0,
"max_save_count": 0,
"maxSaveCount": 0,
"uploadCount": 10,
"uploadMinute": 1,
"enableChunk": false,
"openUpload": true
},
"meta": {
"version": "26.9",
"features": { "chunkUpload": false, "guestUpload": true }
}
}
}
```
> 策略字段 snake_case 与 camelCase 双份下发(前端宽松解析);响应为白名单显式构造,
> 任何敏感键(`admin_token`/`jwt_secret`)均不会出现。
## 健康检查
```bash
curl -s http://localhost:8466/api/v1/health
```
```json
{
"code": 200, "msg": "ok",
"data": {
"status": "ok",
"version": "26.9",
"storage": "local",
"time": "2025-06-01T12:00:00+08:00"
}
}
```