# 环境变量与配置项 配置分三层:**默认值 → `FCB_*` 环境变量 → 数据库 settings KV(管理端运行时修改)**。 v2 起进程必需的环境变量为空集:数据库默认 **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() 逐键一致);v2 新增键统一 snake_case。 ### 站点信息与展示(需求 ①②③) | 键 | 类型/边界 | 默认 | 说明 | |---|---|---|---| | `site_name` / `name` | string | 文件快传 | 站点名称(`site_name` 优先) | | `site_domain` | string,≤256 | 空 | **v3.1**:站点对外域名(`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 字符 | 空 | **v2 需求 ①**:背景图 URL 或上传后地址(空=主题默认;取值时 legacy `background` 键兜底)。管理端保存时校验协议白名单:仅 `http(s)`、`data:image/*` 与站内相对路径(防 `javascript:` 注入,非法 400) | | `footer_text` | string,≤2000 字符 | 空 | **v2 需求 ②**:页脚自定义内容(纯文本或受控 HTML 片段) | | `footer_beian` | string,≤128 字符 | 空 | **v2 需求 ②**:备案号(如 `京ICP备2024xxxxxx号-1`),展示于页脚 | | `notify_enabled` | int(0/1) | 1 | **v2 需求 ③**:通知开关(1=前台右上角悬浮窗展示 / 0=关闭) | | `notify_title` | string,≤128 字符 | 系统通知 | 通知标题 | | `notify_content` | string,≤2000 字符 | 欢迎使用… | 通知正文(**服务端白名单净化**:仅保留纯文本与 `` 为 http(s)/站内相对/`#` 锚点的链接,其余标签与事件属性剥离,保存与读取双侧生效) | | `showAdminAddr` | int(0/1) | 0 | 是否展示后台入口 | | `robotsText` | string | `User-agent: *\nDisallow: /` | robots.txt 内容(由公开端点 `GET /robots.txt` 输出) | ### 保存策略(需求 ④,上传页动态读取并在范围内选择) | 键 | 类型/边界 | 默认 | 说明 | |---|---|---|---| | `max_save_seconds` | int64,0~31536000 | 0 | 最长保存秒数上限(0=仅默认 7 天兜底;>0 时按时间过期超限 403「限制最长时间为 X,可换用其他方式」)。**v3**:管理界面以「小时/天」下拉单位编辑(≥1 天自动显示天),提交时前端换算为秒——canonical 单位保持秒,接口语义不变 | | `max_save_count` | int,0~100000 | 0 | **v2 新增**:单次分享最大可取(保存)次数上限(0=不限制;`expire_style=count` 且 `expire_value` 超上限时 403「限制次数最多为 N 次」) | | `expireStyle` | []string | `["day","hour","minute","forever","count"]` | 允许的过期方式白名单(上传时不在白名单 400「过期时间类型错误」) | ### 存储策略(需求 ④⑩) | 键 | 类型/边界 | 默认 | 说明 | |---|---|---|---| | `uploadSize` | int64,1024~10GiB | 10485760(10MB) | 单文件大小上限(字节),参考实现语义;`max_file_size=0` 时作为生效上限 | | `max_file_size` | int64,0~10GiB | 0 | **v2 新增**:存储策略-单文件上限(字节),0=回落 `uploadSize`;超出 403(文案 humanSize 自适应 B/KB/MB/GB)。**v3**:管理界面以「MB/GB」下拉单位编辑(≥1 GiB 自动显示 GB),提交时前端换算为字节 | | `allowed_file_types` | []string | `["*"]` | 允许类型白名单(扩展名/MIME 通配,`*` 不限制;非白名单 403「不允许上传该类型文件」) | | `storageLimit` | int64,≥0 | 0 | 站点总容量(字节),0=不限制(超限 507) | | `openUpload` | int(0/1) | 1 | 游客上传开关(0 时上传接口要求管理员令牌 403) | | `enableChunk` | int(0/1) | 0 | 启用分片上传 | ### 上传频率限制(需求 ④,既有键对齐参考 ip_limit["upload"]) | 键 | 类型/边界 | 默认 | 说明 | |---|---|---|---| | `uploadCount` / `uploadMinute` | int(1~10000 / 1~1440) | 10 / 1 | 窗口内允许上传次数 / 窗口分钟(上传成功才计数,超限 423;管理端修改后运行时同步限流规则,立即生效) | | `upload_rate` / `download_rate` | int64(0~1 GiB/s) | 0 / 0 | **v3.2**:上下行带宽字节/秒,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 整天) | ### 存储引擎(v3 运行时可配 + 热切换) **`storage_engine`**(v3 新增键):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`(v3 加入 `settings.SensitiveKeys`): > 管理端 GET 返回掩码 `******`;PATCH 时空串或 `******` 表示不修改。直接写库 settings KV 后重启同样生效。 ## 策略动态生效机制(v2 需求 ④⑩) 上传页通过 `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` 获取站点公开配置(无需认证;v2 扩展需求 ①②③④⑩): ```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" } } ```