# ============================================================ # MyBlog 环境变量模板 # 用法:复制本文件为 .env,填入真实值(.env 已被 git 忽略,勿提交) # 说明:所有变量均可选填;不填时后端使用各变量下方的“默认值” # ============================================================ # ---------------- 基础配置 ---------------- # JWT 签名密钥(强烈建议必填) # 作用:给登录令牌签名,密钥泄露 = 可以伪造任意用户身份 # 生成方式:python -c "import secrets; print(secrets.token_urlsafe(48))" # 注意:后端启动时会校验,缺失则直接报错拒绝启动 JWT_SECRET= # JWT 令牌有效期(单位:分钟),默认 10080(7 天) # 调小(如 1440 = 1 天):登录态更快过期,更安全但需更频繁登录 # 调大(如 43200 = 30 天):体验更好但令牌泄露风险时间更长 JWT_EXPIRE_MINUTES=10080 # 数据库地址(可选),默认:backend 目录下的 blog.db(SQLite 文件) # 保持默认即可;如需换路径: # Windows 示例:sqlite:///D:/MyBlog/backend/blog.db # Linux 示例: sqlite:////var/www/blog/backend/blog.db DATABASE_URL= # 上传文件根目录(可选),默认:项目根目录的 uploads/ # 部署时务必与 Nginx 的 /uploads/ 静态映射指向同一目录 # 相对路径按项目根目录解析 UPLOADS_DIR= # ---------------- 头像设置(可选)---------------- # 头像文件大小上限(MB),默认 4 # 作用:头像上传接口拒绝超过该大小的文件(仅支持 jpg/png/webp) # 调大(如 8):允许更高清头像;调小(如 1):更省存储 AVATAR_MAX_SIZE_MB=4 # 头像更换冷却时间(小时),默认 24 # 作用:同一账号两次更换头像之间至少间隔该时长,防止反复更换头像 # 调大(如 168 = 1 周):更严格;调小(如 1):更宽松 AVATAR_CHANGE_INTERVAL_HOURS=24 # ---------------- 博主账号(仅初始化用)---------------- # 作用:执行 python -m backend.seed 时创建唯一博主账号(bcrypt 存储) # 账号已存在时重复执行会跳过,不会覆盖已有账号 BLOGGER_USERNAME=孤竹居士 BLOGGER_EMAIL=guzhujushi2008@163.com BLOGGER_PASSWORD=你的登录密码 # ---------------- SMTP 邮箱验证码 ---------------- # 作用:注册/忘记密码时向用户邮箱发送验证码(163 邮箱示例) # SMTP_PORT:465=SSL 加密(推荐);587/25=普通 STARTTLS # SMTP_AUTH_CODE:邮箱的“授权码”,不是登录密码(163 在设置里开启 SMTP 后获取) SMTP_HOST=smtp.163.com SMTP_PORT=465 SMTP_USER=发件邮箱地址 SMTP_AUTH_CODE=授权码 EMAIL_FROM=发件邮箱地址(默认与 SMTP_USER 相同) # ---------------- 文章图片上传(可选)---------------- # 文章图片(封面 / 正文插图)大小上限(MB),默认 6 # 作用:发文时上传封面与正文图片的接口拒绝超过该大小的文件(仅支持 jpg/png/webp) # 调大(如 10):允许更高清大图;调小(如 3):更省存储 ARTICLE_IMAGE_MAX_SIZE_MB=6 # ---------------- 文章文档上传(可选)---------------- # 文章 Word 文档(doc/docx)大小上限(MB),默认 20 # 作用:发文编辑器“插入文档”上传接口拒绝超过该大小的文件 # 注意:文档只能用于“我的生活 / 我的学习”分区的文章(后端强制校验分区) # 调大(如 50):允许更大的文档;调小(如 10):更省存储 DOC_MAX_SIZE_MB=20 # ---------------- 安全限流(可选,调整防护强度)---------------- # 登录失败次数上限,默认 5 # 作用:同一邮箱在窗口内失败达到该次数后,即使密码正确也会被临时拒绝 # 调小(如 3):更安全,但误输密码几次就被锁 # 调大(如 10):更宽松,防爆破能力下降 LOGIN_MAX_FAILURES=5 # 登录锁定窗口(秒),默认 900 = 15 分钟 LOGIN_WINDOW_SECONDS=900 # 同一 IP 在登录窗口内最多尝试次数,默认 30 # 作用:配合邮箱维度限流,防止攻击者换着邮箱对博主账号做分布式爆破 # 调小(如 10):更严格,但同一 NAT 出口下的多人可能互相影响 LOGIN_MAX_PER_IP=30 # 同一 IP 每小时最多注册次数,默认 3 # 作用:注册已强制要求邮箱验证码,此处再加 IP 限流,防批量注册垃圾账号 REGISTER_MAX_PER_IP=3 REGISTER_WINDOW_SECONDS=3600 # 评论 / 点赞每分钟最多次数(按 IP),默认 30 # 作用:防止好友账号刷评论 / 刷点赞 ACTION_MAX_PER_MINUTE=30 # 同一邮箱每小时最多发送验证码次数,默认 5 # 调小可防止被恶意刷邮件,调大可让正常用户更频繁重发 SEND_CODE_MAX_PER_EMAIL=5 # 同一 IP 每小时最多发送验证码次数,默认 10 SEND_CODE_MAX_PER_IP=10 # 验证码发送限流窗口(秒),默认 3600 = 1 小时 SEND_CODE_WINDOW_SECONDS=3600 # 验证码最多尝试次数,默认 5 # 作用:同一邮箱在验证码有效期内错误尝试达到该次数后,验证码自动作废,需重新发送 # 防止 6 位验证码被暴力枚举 VERIFY_CODE_MAX_ATTEMPTS=5 # 验证码尝试限流窗口(秒),默认 600 = 10 分钟 VERIFY_CODE_WINDOW_SECONDS=600 # 验证码有效期(分钟),默认 10 EMAIL_CODE_TTL_MINUTES=10 # 同一邮箱重发验证码的最小间隔(秒),默认 60 EMAIL_RESEND_INTERVAL_SECONDS=60 # 评论最大长度(字),默认 2000 # 同时是接口层强制上限(超出返回错误),改小可减轻存储与展示压力 COMMENT_MAX_LENGTH=2000 # 注册/重置密码的最小长度(位),默认 6 PASSWORD_MIN_LENGTH=6 # ---------------- SSH 白名单自动更新(可选,强烈建议)---------------- # 背景:家庭宽带的公网 IP 经常变化,安全组 22 端口若只放行固定 IP, # 换 IP 后就会把自己挡在门外。启用后,家庭电脑定时上报当前公网 IP, # 服务器自动调用阿里云 API 更新安全组 22 端口白名单(只放行最新 IP)。 # 原理:家庭端 -> https://域名/myip 获取公网 IP -> 变化时调用 # POST /api/ipwatch/report -> 服务器更新安全组(先加新规则、后删旧规则)。 # 说明:AccessKey 只放在服务器 .env,家庭端只配置下方 IPWATCH_SECRET 即可。 # 完整配置步骤见 deploy/DEPLOY.md「日常运维」章节。 # 上报密钥(必填):家庭端 ipwatch.conf 里的 SECRET 必须与此相同 # 作用:防止任意人调用上报接口刷白名单;建议用随机字符串并定期更换 # 生成:python3 -c "import secrets; print(secrets.token_urlsafe(24))" IPWATCH_SECRET= # 阿里云 AccessKey(RAM 子账号,仅授予该安全组的增删查权限即可) # 作用:服务器调用阿里云 ECS API 更新安全组规则 # 注意:不要用主账号密钥;建议定期在 RAM 控制台轮换 ALIYUN_AK_ID= ALIYUN_AK_SECRET= # 安全组 ID(必填):阿里云控制台「ECS -> 安全组 -> 基础信息」查看 IPWATCH_SECURITY_GROUP_ID= # 阿里云地域 ID(必填):乌兰察布是 cn-wulanchabu,其它地域见控制台 IPWATCH_REGION=cn-wulanchabu # 受保护的端口(默认 22 = SSH),一般无需修改 IPWATCH_PORT=22 # 上报限流(秒):同一来源 IP 两次上报的最小间隔,默认 60 # 作用:即使密钥泄露,攻击者每分钟也只能刷一条白名单 # 调大(如 600):更安全;调小(如 10):换 IP 后恢复 SSH 更快 IPWATCH_REPORT_INTERVAL_SECONDS=60 # ---------------- JS→WASM 预编译(可选)---------------- # 总开关(默认 true):是否允许把上传项目的 .js 预编译为 .wasm # 作用:仅在服务器生成编译产物与报告,不会执行任何上传代码; # 浏览器演示页仍然运行原始 JS(Javy 产物面向服务端沙箱执行等场景) # 注意:需先在服务器执行 bash deploy/install_javy.sh 安装编译工具 WASM_COMPILE_ENABLED=true # Javy 编译工具路径(默认 /usr/local/bin/javy) # 安装脚本:deploy/install_javy.sh(GitHub 下载约 14MB 单文件) JAVY_PATH=/usr/local/bin/javy # 单个 JS 文件大小上限(MB),默认 3 # 作用:超过该大小的 JS 跳过不编译,防止超大文件撑爆内存/磁盘 # 调大(如 10):允许编译更大的文件;调小(如 1):更保守 WASM_MAX_JS_SIZE_MB=3 # 单文件编译超时(秒),默认 60 # 作用:防止 javy 编译卡死拖慢接口;超时自动终止并记录失败 WASM_TIMEOUT_SECONDS=60 # 压缩包打包成单个 wasm 时,全部 JS 的总量上限(MB),默认 10 # 作用:防止超大项目把内存/磁盘撑爆;超过则跳过打包并在报告中注明 # 调大(如 30):允许打包更大的项目;调小(如 3):更保守 WASM_BUNDLE_MAX_SIZE_MB=10