文件
wangchuanli 3751dffef9 feat: 新增备份恢复与公网加固
- 新增备份管理页与 API:在线快照、自动周期备份、按份数清理、下载、一键恢复(恢复前自动兜底)
- 新增 /profile/export,普通用户可导出本人全部数据(不含 Cookie 明文)
- 修复 X-Forwarded-For 可伪造导致三道 IP 防线失效,统一走 client_ip() 取客户端地址
- 取消 admin123 硬编码默认口令,留空则生成随机初始口令并仅打印一次
- .dockerignore 排除 backups/ 并加构建期断言,防止密钥随镜像分发
- 新增会话版本号,改密/停用/删除及恢复备份后其他会话立即失效
- 新增容器资源上限、采集跨度硬顶 31 天、重操作最小间隔与并发 409
- 新增访问日志、HSTS 条件下发、口令黑名单、验证码抗模板匹配、instance.json 0600
- 版本号升至 1.4.0,同步更新 README、SECURITY、.env.example 与 compose 配置
2026-09-18 08:46:34 +08:00

86 行
4.6 KiB
Bash

# =============================================================================
# docker-compose 环境变量样例:复制成 .env 后按需修改(.env 已被 .gitignore 排除)
# cp .env.example .env
# =============================================================================
# ---------- 监听 ----------
# 宿主机绑定地址:0.0.0.0 = 局域网可访问;127.0.0.1 = 只允许本机
WB_BIND=0.0.0.0
WB_PORT=8848
TZ=Asia/Shanghai
# ---------- 首个管理员(只在数据库为空时生效)----------
# 强烈建议:首次启动前就设好。
# 留空时程序会生成**随机**口令,并且只在启动日志里打印一次:
# docker compose logs portal | grep -A1 口令
# 抄下来登录后立刻改掉。(1.4.0 起不再有 admin123 这类硬编码兜底。)
WB_ADMIN_USER=admin
WB_ADMIN_PASSWORD=
# ---------- 容器资源上限 ----------
# 应用层已经有「采集频率 / 并发 / 采集跨度」三重业务刹车,这里是**进程**层面的
# 兜底:一次异常(内存泄漏、超大导出、正则回溯)不能把整台机器带下去。
# 单写者架构下不要靠加副本扛负载,限制单实例资源才是正解。
#
# CPUS : CPU 上限,允许小数。SQLite 是单写者,1.0 已经够用;
# 压测后再调大,别一上来就给满宿主机的核。
# MEM_LIMIT : 内存上限。500 条/页采集时的常驻内存在 100~200 MB 量级,
# 512m 留了充裕余量;内存与 swap 同时设成这个值 = 禁用 swap,
# 这样超限会「被 OOM 杀掉」而不是「越来越慢」——后者更难查。
# PIDS_LIMIT : 进程/线程数上限,挡 fork 炸弹。tini + python + waitress
# 线程模型下 256 很宽松。
WB_CPUS=1.0
WB_MEM_LIMIT=512m
WB_PIDS_LIMIT=256
# ---------- waitress 线程数 ----------
# 这是「单实例能同时吃进几个慢请求」的上限(采集 / 导出 / 备份恢复都算慢请求)。
# 与 CPU 上限配套:1 核配 8 线程容易出现「都在等 CPU」的假并发,默认 4。
WB_THREADS=4
# ---------- 反向代理与传输安全(三个必须一起决定)----------
# WB_TRUST_PROXY:是否信任 X-Forwarded-For。**默认 0 = 不信任**。
# 直接暴露给公网时必须留 0。置 1 的后果很严重:攻击者每次换一个伪造的
# XFF,验证码限速、注册配额、登录锁定这三道 IP 防线会**同时失效**。
# 置 1 的前提只有一个:**你自己的**反向代理会写这个头。
# 开启后程序取 XFF 里**最右侧**的合法 IP,而最右侧是离你最近的那一跳
# (由你的代理写入),客户端伪造不了。因此 nginx 侧两种写法都安全:
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 保留链路,便于排查
# proxy_set_header X-Forwarded-For $remote_addr; # 覆盖,最保守
# 真正不能做的是:去信 XFF 里**最左边**那一段(那是客户端自己填的)。
WB_TRUST_PROXY=0
# 前面挂了 HTTPS 反代时置 1(读到 X-Forwarded-Proto: https 就不跳转)
WB_FORCE_HTTPS=0
# 是否记录访问日志(写进 logs/app.log,静态资源与验证码图片除外)
WB_ACCESS_LOG=1
# ---------- 调度 ----------
# 一个容器一份调度。只有跑多副本时才把除第一份之外的都设成 1。
WB_DISABLE_SCHEDULER=0
# ---------- 会话安全 ----------
# 会话 Cookie 是否只允许走 HTTPS。
# 0 = 关闭(默认,纯 HTTP / 局域网部署的正确值)
# 1 = 只在 HTTPS 下发送。**如果你用 http:// 访问却设成 1,会出现
# 「登录成功又立刻跳回登录页」**,因为浏览器根本不会回传会话 Cookie。
# 只有在前面挂了 HTTPS 反向代理、并且用域名访问时才设为 1。
WB_COOKIE_SECURE=0
# ---------- 可选:启动时自动导入 ----------
# 1 = 尝试从挂载进来的编辑器 settings.json 读取 codebuddyUsage.* 写入数据库
WB_IMPORT_CREDS=0
# 指向容器内路径;配合 docker-compose.yml 里注释掉的挂载项使用
WB_IMPORT_XLSX=
# ---------- 镜像名(推送 Gitea 注册表时用)----------
# WB_IMAGE=git.iwali.top/wangchuanli/workbuddy-portal:latest
# WB_IMAGE=git.iwali.top/wangchuanli/workbuddy-portal:1.4.0
# ---------- 仅叠加 docker-compose.hostdir.yml 时有效 ----------
# 把数据/日志/备份放到宿主机目录而不是命名卷。**只建议 Linux 宿主机使用**:
# Windows + Docker Desktop 的 9p 挂载下,宿主进程访问过 WAL 库之后,
# 容器侧会打不开数据库且不自愈(详见 docs/DEPLOYMENT.md)。
# WB_HOST_DATA_DIR=./data
# WB_HOST_LOG_DIR=./logs
# WB_HOST_BACKUP_DIR=./backups