Initial commit: MyBlog full stack blog

This commit is contained in:
2026-08-22 22:28:41 +08:00
commit c61193f2af
64 changed files with 7290 additions and 0 deletions
+193
View File
@@ -0,0 +1,193 @@
# ============================================================
# 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.dbSQLite 文件)
# 保持默认即可;如需换路径:
# 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_PORT465=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.shGitHub 下载约 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