docs(env): expand and correct .env.example comments

依据代码核对修正多处不准确/缺失的注释,纯文档改动,无行为变化。

修正的不准确项:
- RATE_LIMIT_STRICT_* 实际覆盖登录/注册/评论预检/搜索,原注释只写登录注册
- STATEMENT_TIMEOUT_SECS 是 Postgres 服务端取消(非客户端断连),仅经连接池的连接生效
- COMPRESSION_ALGORITHMS 示例值(四项全开)等价于 all,消除注释默认 vs 示例值的歧义

补全的缺失细节:
- RUST_LOG 补细粒度语法示例(info,yggdrasil=debug)
- 限流项统一说明 token bucket 模型(PER_SEC 稳态 / BURST 突发容量)
- MAX_SESSIONS_PER_USER 超限按最旧优先删除(LRU)
- DB_POOL_SIZE 与 Postgres max_connections 的关系
- WEBP_QUALITY/METHOD 越界会 clamp 不报错
- TRUSTED_PROXY_COUNT 设错的双向安全后果
- IMAGE_DISK_CACHE_* 清理任务每小时跑一次
- MIGRATE_STARTUP_TIMEOUT_SECS 500ms 固定间隔轮询
- SSR_CACHE_SECS 文章更新后最长滞后 TTL 秒可见
- APP_BASE_URL 反向代理后 Host 头可被影响的 CSRF 风险

结构上用分隔线分组(Rate Limit / Security / WebP / SSR / Image Cache),
安全注意事项用 ⚠️ 标记。
This commit is contained in:
xfy 2026-06-22 13:32:49 +08:00
parent 2c7319c220
commit 694e198331

View File

@ -1,74 +1,112 @@
DATABASE_URL=postgres://postgres:postgres@localhost:5432/yggdrasil
# tracing 日志过滤器。支持逗号分隔的细粒度语法,例如:
# RUST_LOG=info 全局 info 级
# RUST_LOG=info,yggdrasil=debug 本项目 debug其余 info
# RUST_LOG=warn,hyper=warn,sqlx=warn 降噪第三方库
# 不设时默认 info见 main.rs
RUST_LOG=info
# Rate Limit — 严格限流(登录、注册)
# ─────────────────────────────────────────────────────────────
# Rate Limit 限流配置
#
# 采用 token bucket令牌桶模型
# PER_SEC = 稳态补充速率(每秒补充的令牌数)
# BURST = 桶容量(允许瞬间累积的最大请求数)
# 例如 PER_SEC=1、BURST=5每秒补 1 个令牌,最多攒 5 个,可短时 1 秒内打 5 个请求。
# ─────────────────────────────────────────────────────────────
# 严格限流:覆盖登录、注册、评论预检、搜索等敏感/查询接口。
RATE_LIMIT_STRICT_PER_SEC=1
RATE_LIMIT_STRICT_BURST=5
# Rate Limit — 上传限流(图片上传)
# 上传限流:仅 /api/upload(图片上传)
RATE_LIMIT_UPLOAD_PER_SEC=2
RATE_LIMIT_UPLOAD_BURST=15
# Rate Limit — 图片访问限流(/uploads/*
# 图片访问限流:仅 GET /uploads/*(图片读取与处理)。
RATE_LIMIT_IMAGE_PER_SEC=10
RATE_LIMIT_IMAGE_BURST=50
# Rate Limit — 评论限流POST 评论)
# 评论限流:仅 POST 创建评论(与上面的“评论预检”不是同一个桶)。
RATE_LIMIT_COMMENT_PER_SEC=1
RATE_LIMIT_COMMENT_BURST=5
# Rate Limit — 宽松桶:无法识别真实客户端 IP"unknown")时使用
# 当未配置可信代理TRUSTED_PROXY_COUNT=0Dioxus server function 拿不到 TCP
# 对端地址,请求会落到这个桶,因此阈值更高以免误杀正常用户。
# 宽松桶:当真实客户端 IP 无法识别(值为 "unknown")时,由 check_strict_limit 自动改用此桶
# 触发条件通常是 TRUSTED_PROXY_COUNT=0 且调用方为 Dioxus server function拿不到 TCP 对端地址)。
# 此时所有匿名请求共享同一个桶,因此阈值必须更高,否则会误杀正常用户。
RATE_LIMIT_UNKNOWN_PER_SEC=30
RATE_LIMIT_UNKNOWN_BURST=100
# ─────────────────────────────────────────────────────────────
# Security 安全相关
# ─────────────────────────────────────────────────────────────
# 写请求POST/PUT/PATCH/DELETECSRF 校验的可信来源。
# 生产环境设为你的源站,例如 https://your-domain.example。
# 不设:回退到请求的 Host 头 + X-Forwarded-Proto在反向代理后生效
# 不设:回退到请求的 Host 头 + X-Forwarded-Proto。
# ⚠️ 安全提示:反向代理后若 Host 头可被客户端影响,回退路径可能被 CSRF 绕过。
# 生产环境强烈建议显式设置此变量。
APP_BASE_URL=
# 设为 true/1/yes 给会话 cookie 加上 Secure 标志HTTPS 生产环境启用)。
# 是否给会话 cookie 加 Secure 标志。识别 true/1/yes其余均视为 false
# 启用后浏览器仅在 HTTPS 下发送 cookieHTTP 生产环境必开。
COOKIE_SECURE=false
# 应用前方的反向代理层数;用于从 X-Forwarded-For 中提取真实客户端 IP。
# 应用前方的反向代理层数,用于从 X-Forwarded-For 提取真实客户端 IP。
# 直接对外服务时为 0经过一层代理如 nginx/Caddy时为 1。
# ⚠️ 设错的安全后果:
# 设得比实际大 → 信任客户端伪造的 IP限流可被绕过
# 设得比实际小 → 取到代理 IP 而非客户端 IP限流对错对象。
TRUSTED_PROXY_COUNT=0
# 单条查询的超时秒数;慢查询会被取消以保护连接池。
# 单条 SQL 查询的服务端超时秒数。超时由 PostgreSQL 服务端取消该查询(不是客户端断连)。
# 仅对经连接池DB_POOL建立的连接生效作用是防止单条慢查询长时间占用连接拖垮池。
# 需注意PostgreSQL 的总连接数受 max_connections 限制,本超时不影响已占连接的计费。
STATEMENT_TIMEOUT_SECS=30
# WebP 编码配置
# 质量0.0(最小体积)到 100.0(最佳质量),默认 85.0
# ─────────────────────────────────────────────────────────────
# WebP 编码配置(仅上传转码 / 图片格式转换时生效)
# ─────────────────────────────────────────────────────────────
# 质量0.0(最小体积)到 100.0(最佳质量),默认 85.0。
# 越界值会被 clamp截断到合法范围并打 WARN 日志,不会报错。
WEBP_QUALITY=85.0
# 方法0最快到 6最佳质量默认 2
# 编码方法0最快到 6最佳质量/压缩率),默认 2。
# 越界值同样 clamp 到 06。
WEBP_METHOD=2
# 每用户最大并发会话数(默认 5最小 1
# 每用户最大并发会话数(默认 5最小 1
# 超过上限时按最旧优先删除LRU 式淘汰)——新设备登录会让最老的会话自动失效。
MAX_SESSIONS_PER_USER=5
# 数据库连接池大小(默认 20
# 数据库连接池大小(默认 20
# 不应超过 PostgreSQL 的 max_connections多实例部署时按 (max_connections / 实例数) 估上限。
DB_POOL_SIZE=20
# 启动时数据库连接重试窗口,单位秒(默认 30
# 服务器在启动期间等待 PostgreSQL 可达的最长时间,超时则放弃。
# 服务器在启动期间等待 PostgreSQL 可达的最长时间,超时则友好退出(不 panic
# 内部以 500ms 固定间隔轮询,因此 30s 约重试 60 次。
# 适用于 DB 启动比 app 慢的场景docker-compose 无 healthcheck、本机冷启动 Postgres 等)。
# 仅影响启动;运行时连接重试走独立的快速失败策略,以避免级联故障。
# 仅影响启动;运行时连接失败走独立的快速失败策略1.6s、指数退避),以避免级联故障。
MIGRATE_STARTUP_TIMEOUT_SECS=30
# SSR 页面缓存时长,单位秒(默认 3600
# SSR 页面缓存时长,单位秒(默认 3600,即 1 小时)。
# src/ssr_cache.rs 维护了一个全局 generation 计数器,每次文章写入时自增,
# 但 Dioxus 0.7 暴露的 API 无法把它接入增量 SSR 缓存的 key。在该 API 可用前,
# 此 TTL 是唯一有效的 SSR 缓存失效手段。
# 此 TTL 是唯一有效的 SSR 缓存失效手段——意味着文章更新后最长可能滞后 TTL 秒才可见
SSR_CACHE_SECS=3600
# HTTP 响应压缩算法。
# 逗号分隔大小写不敏感。支持gzip、brotli或 br、deflate、zstd。
# 用 "all" 启用全部(不设时的默认);用 "none" 或 "off" 关闭。
# HTTP 响应压缩算法。逗号分隔,大小写不敏感。
# 支持gzip、brotli可简写为 br、deflate、zstd。
# 示例值(四项全开)等价于 "all",也是不设环境变量时的默认。
# 用 "none" 或 "off" 关闭压缩。
COMPRESSION_ALGORITHMS=gzip,brotli,deflate,zstd
# 图片响应的缓存头(硬编码默认值)
# 上传的原始图片资源以 Cache-Control: public, max-age=31536000, immutable 提供。
# 处理变体(?w=、?format= 等)缓存 24 小时。
# 要使已缓存的原始上传失效,请更改其文件路径。
# 要刷新某个处理变体,请更改其处理参数。
# ─────────────────────────────────────────────────────────────
# 图片响应缓存头(硬编码默认值,非环境变量)
# ─────────────────────────────────────────────────────────────
# 上传的原始图片资源Cache-Control: public, max-age=31536000, immutable。
# 处理变体(?w=、?format= 等查询参数生成的衍生图):缓存 24 小时。
# 失效方式:
# - 原始上传:更改其文件路径;
# - 处理变体:更改处理参数(查询串不同即视为新资源)。
# 图片磁盘缓存上限
# 最大总容量,单位 MB默认 1024
# ─────────────────────────────────────────────────────────────
# 图片磁盘缓存上限uploads/.cache/,后台清理任务每小时扫描一次)
# ─────────────────────────────────────────────────────────────
# 最大总容量,单位 MB默认 1024。超限时按修改时间删除最旧的文件。
IMAGE_DISK_CACHE_MAX_MB=1024
# 文件被强制删除前的最大存在时长,单位小时(默认 168即 7 天)
# 文件最大保留时长,单位小时(默认 168即 7 天)。超期的文件优先删除。
# ⚠️ 清理任务每小时运行一次,改了不会立即生效,最长需等 1 小时。
IMAGE_DISK_CACHE_MAX_AGE_HOURS=168