diff --git a/.env.example b/.env.example index d876f70..1c79ffe 100644 --- a/.env.example +++ b/.env.example @@ -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=0)时,Dioxus 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/DELETE)CSRF 校验的可信来源。 # 生产环境设为你的源站,例如 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 下发送 cookie,HTTP 生产环境必开。 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 到 0–6。 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