Cleep 0.4.4 配置参数详解

Cleep 0.4.4 全量配置参数详解:必填环境变量与启动时序、数据库连接、会话 Cookie、四组限流参数(附 429 实测)、反向代理与 HTTPS 联动、附件存储、注册开关与管理员引导、安全响应头与生产配置模板。

CleepCleep自托管NASDocker Compose2026/10/25

Cleep 0.4.4 配置参数详解

目标:Cleep 的全部运行时行为都由「启动期环境变量 + 一项运行期开关」控制,官方 .env.example 只写了用途、没写坑。本篇基于官方仓库源码(server/app.ts、server/middleware/*、server/db/bootstrapAdmin.ts,2026-10-25 实查 v0.4.4)与真实部署环境逐项实测,讲清每个配置参数的作用、默认值、生效时机与相互联动,重点还原三处最容易踩的坑:/api/auth 整路由限流计数、COOKIE_SECURE 与 HTTPS 的联动关系、TRUST_PROXY 开关对限流准确性的影响。部署过程见《Cleep 0.4.4 Docker Compose 部署指南》,定位与选型见《Cleep 0.4.4 介绍与选型指南》。

一、环境信息

本篇配置实测与取证环境如下,读者操作时请替换为自己的取值:

  • 操作系统:Ubuntu 24.04 LTS,x86_64
  • Cleep 版本:0.4.4(官方 GHCR latest 标签,digest sha256:60da6a78…,与源码 tag v0.4.4 一致)
  • 数据库:PostgreSQL 16.15(postgres:16-alpine)
  • 部署目录:/opt/cleep/(compose 编排文件与 .env 所在),数据目录 /opt/cleep/data/postgres/ 与 /opt/cleep/data/attachments/
  • 服务端口:应用服务在 6169 端口监听,对外发布 8140(8140:6169)
  • 演示管理员账号:admin@quzuo.net / q1w2e3r4(.env 的 ADMIN_EMAIL/ADMIN_PASSWORD 首次启动引导创建)

取证方式说明:配置项的「官方定义」逐条对照仓库内 .env.example 与服务端 TypeScript 源码(本地已克隆 blindpassasjer/cleep 仓库 v0.4.4);「实际行为」全部通过 curl 在 8140 端口实测取证,回显原文见文中代码块,证据文件留存于本地 tmp/cleep/ev_c1_*.txt。

二、配置体系总览

Cleep 没有配置文件,全部配置走两条通道,生效时机完全不同:

通道载体生效时机覆盖内容
启动期配置环境变量(compose 项目目录 .env)服务进程启动时读取一次,改完必须重新应用编排才生效数据库、会话、限流、代理、附件目录、管理员引导
运行期配置数据库 app_settings 表管理员在后台修改,立即生效、无需重启目前仅一项:registrationOpen(注册开关)

启动时序(源码 server/index.ts → server/app.ts)按固定顺序执行:

  1. fail-fast 校验必填变量(assertRequiredEnv()):DATABASE_URL、SESSION_SECRET、ATTACHMENTS_DIR 三项缺任何一个直接抛错退出,错误信息即变量名本身,例如 DATABASE_URL environment variable is required.;ADMIN_EMAIL 与 ADMIN_PASSWORD 校验成对出现(见第八章)。
  2. 数据库迁移:对 DATABASE_URL 指向的库自动执行 schema 迁移,无需手工建表。
  3. 管理员引导(bootstrapAdmin(),幂等,见第八章)。
  4. 监听端口:Number(process.env.PORT) || 6169,未设置 PORT 时默认 6169。

💡 「改了 .env 不生效」是最高频的误用:环境变量在进程启动时读取一次,修改后必须 docker compose up -d 重新应用编排让服务进程重建;而注册开关这类运行期配置改了立即生效,不要为它重启服务。

环境变量总表

以下为 v0.4.4 全部环境变量(来源:仓库 .env.example + 源码 process.env 引用点逐条核对,2026-10-25):

变量必填默认值作用详解章节
DATABASE_URL✅ 必填无(缺失启动即退出)应用服务连接 PostgreSQL 的连接串第三章
SESSION_SECRET✅ 必填无(缺失启动即退出)会话 Cookie 签名密钥第四章
ATTACHMENTS_DIR✅ 必填无(缺失启动即退出;Compose 模板已固定注入 /data/attachments)附件落盘根目录第七章
ADMIN_EMAIL / ADMIN_PASSWORD可选不设则跳过引导首次启动创建首个管理员账号,两者必须同时设或同时不设第八章
PORT可选6169应用服务监听端口第四章
NODE_ENV可选Compose 模板固定 production运行模式—
PUID / PGID可选999数据库服务进程运行 uid/gid,须与 ./data/postgres 属主一致第三章
POSTGRES_PASSWORDCompose 必填无(compose 用 :? 语法强制)数据库服务初始化密码,须与 DATABASE_URL 中密码一致第三章
COOKIE_SECURE可选false会话 Cookie 是否加 Secure 属性,同时控制是否下发 HSTS第六章
TRUST_PROXY可选false是否信任上一跳的 X-Forwarded-For(影响限流按 IP 计数)第五、六章
AUTH_RATE_LIMIT_MAX / AUTH_RATE_LIMIT_WINDOW_MS可选20 / 60000/api/auth/* 限流:窗口内最大请求数 / 窗口时长(毫秒)第五章
UPLOAD_RATE_LIMIT_MAX / UPLOAD_RATE_LIMIT_WINDOW_MS可选60 / 60000附件上传与数据导入导出限流第五章
NOTE_LOCK_RATE_LIMIT_MAX / NOTE_LOCK_RATE_LIMIT_WINDOW_MS可选20 / 60000笔记密码锁定/解锁限流(源码支持,.env.example 未列出)第五章
LINK_PREVIEW_RATE_LIMIT_MAX / LINK_PREVIEW_RATE_LIMIT_WINDOW_MS可选300 / 60000链接预览元数据/图片代理限流(源码支持,.env.example 未列出)第五章

⚠️ 注意两个「文档与源码不一致」的点:NOTE_LOCK_* 与 LINK_PREVIEW_* 两组限流变量在源码(server/middleware/rateLimit.ts)中真实生效,但官方 .env.example 没有列出——按默认值使用无需关心,需要调整时直接写进 .env 即可(Compose 模板未透传这两个变量时,需自行在编排文件 environment: 段补一行透传)。

三、数据库连接

Cleep 把「应用服务连什么库」与「数据库服务本身怎么初始化」拆成两组变量,两者必须人工保持一致:

# .env(Compose 部署的标准写法)
POSTGRES_PASSWORD=cleepdb2026
DATABASE_URL=postgres://cleep:cleepdb2026@postgres:5432/cleep
  • DATABASE_URL 标准连接串格式 postgres://用户:密码@主机:端口/库名。Compose 部署下主机名固定写服务名 postgres(编排内部 DNS 解析),库名与用户名由编排模板固定为 cleep。密码必须与 POSTGRES_PASSWORD 完全一致,否则应用服务连库失败、接口全部 500。
  • POSTGRES_PASSWORD 仅数据库服务使用(首次初始化时创建 cleep 用户与 cleep 库)。Compose 模板用 ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env} 语法强制要求设置,漏填时编排直接报错拒绝启动,不静默回退。
  • PUID / PGID(默认 999):数据库服务进程的运行身份,须与宿主机 ./data/postgres 数据目录属主一致。首次启动前 chown -R 999:999 data/postgres(999 是 PostgreSQL 官方运行用户的固定 uid);改了 PUID/PGID 就同步改目录属主,否则数据库首次初始化因无写权限失败。
  • 首次启动自动建表:应用服务启动即对目标库执行迁移,v0.4.4 库内共 8 张表(users、sessions、notes、labels、note_labels、attachments、link_previews、app_settings),全程无需手工执行任何 SQL。

💡 换密码的正确姿势:POSTGRES_PASSWORD 只在数据目录首次初始化时生效,对已初始化的库改 .env 里的它不会改变实际密码。正确做法是进数据库执行 ALTER USER cleep PASSWORD '...',再同步改 DATABASE_URL,最后重新应用编排。

SESSION_SECRET

会话签发采用「随机 token + 服务端存储 + Cookie 签名」三件套,SESSION_SECRET 是 Cookie 签名的 HMAC 密钥:

# 官方推荐的生成方式(64 位十六进制随机串)
openssl rand -hex 32

实测生成回显(每次不同,请使用自己生成的值):

784e82cbbf04d24479a87fb9263bd51b836e8db2f09ddde4701dd0eeebfdd001
  • 必填项,缺失时启动即退出(SESSION_SECRET environment variable is required.)。
  • 更换密钥的代价:所有已签发 Cookie 的签名校验失败,全体用户被登出(服务端 session 行仍在,但浏览器带的旧 Cookie 过不了签名验证),重新登录即可,无数据损失。
  • 泄露即等于「可伪造任意用户登录态」,按生产密钥管理,不要提交进版本库(官方 .env.example 明确写明 .env 已被 gitignore)。

登录成功后服务端下发的 Set-Cookie 原文(2026-10-25 实测抓取):

Set-Cookie: session=s%3Ad266250270c5473f9baa972788077a5fd09c83023b684fc3ad3aaf5e4a075477.GTwyzvT0UCWMdyMUnpa0NRl4P0eNLZWX46VjlqM7774; Path=/; Expires=Tue, 24 Nov 2026 05:31:57 GMT; HttpOnly; SameSite=Strict

逐属性解读:

属性实测值含义与联动
名称session固定,不可配置
值s%3A<64位hex>.<签名>URL 编码的 s:<token>.<HMAC签名>——token 为 64 位十六进制(服务端 sessions 表主键),s: 前缀与点后签名是 cookie-parser 的签名格式,密钥即 SESSION_SECRET
HttpOnly✅JavaScript 不可读,防 XSS 偷 Cookie
SameSiteStrict最严格档:跨站请求一律不带 Cookie,天然免疫 CSRF
Secure实测未出现(COOKIE_SECURE=false)设 COOKIE_SECURE=true 后追加,仅 HTTPS 连接发送——纯 HTTP 访问下开了它会导致浏览器静默丢弃 Cookie,「登录成功但刷新即 401」(第六章)
Expires登录时刻 + 30 天服务端会话 TTL 同为 30 天(源码 SESSION_TTL_MS = 30 天);30 天后无论 Cookie 是否还在,服务端 sessions 表记录过期,强制重新登录
  • 「保持登录」差异:登录时若勾选保持登录,Cookie 带 Expires(关浏览器后仍有效,上限 30 天);不勾则是会话 Cookie(无 Expires,关浏览器即失效,但服务端记录仍在)。
  • 服务端存储:token 存 sessions 表(token、userId、expiresAt),每个请求查库鉴权——所以管理员重置某用户密码时会删除该用户全部 session 行,强制其所有已登录设备下线重新认证(实测行为,源码 POST /api/admin/users/:id/password)。
  • 退出登录:POST /api/auth/logout 删除服务端 session 行并清 Cookie。

未登录态的行为

未登录访问身份接口不是 401 而是 200(2026-10-25 实测):

$ curl -s http://localhost:8140/api/auth/me
{"user":null}          # HTTP 200

前端据此区分「未登录/已登录」渲染界面;真正需要登录的接口(笔记、管理等)才返回 401 {"error":"Authentication required."}。做探活监控时不要拿 /api/auth/me 的 200 当「服务可用且已登录」。

五、限流参数:四组独立计数器

机制

源码 server/middleware/rateLimit.ts,实现是单进程内存里的固定窗口计数器:

  • 按 req.ip(客户端 IP)分桶计数,窗口内达到上限返回 429 {"error":"Too many requests. Please try again shortly."}(无 Retry-After 头,错误体固定这一句)。
  • 窗口到期由惰性清扫删除,不重启也能自然恢复。
  • 内存态,不落库:服务重启计数清零;未来若多实例部署,各实例独立计数(v0.4.4 未提供共享存储,官方注释明示单实例自托管定位)。
  • 数值可通过环境变量调整,窗口与上限是分开的两个变量;读取时校验「正整数」,非法值静默回退默认。

四组参数与覆盖范围

组默认(次/窗口)窗口覆盖的接口说明
AUTH_RATE_LIMIT_*20 次 / 60000ms1 分钟整个 /api/auth 前缀:注册开关查询、注册、登录、登出、身份查询(me)、改密码源码写法是 app.use('/api/auth', authRateLimit, …)——挂在路由前缀上,该前缀下所有请求都计数
UPLOAD_RATE_LIMIT_*60 次 / 60000ms1 分钟附件上传(POST)、数据导出(GET /api/export)、Keep zip 导入按接口逐个挂载
NOTE_LOCK_RATE_LIMIT_*20 次 / 60000ms1 分钟笔记加锁/解锁/解锁附件/移除锁四个接口密码试错面,与登录同级防护;.env.example 未列出
LINK_PREVIEW_RATE_LIMIT_*300 次 / 60000ms1 分钟链接预览元数据 + 图片代理上限最高:一条带多条链接的笔记展开即产生成倍的预览请求;.env.example 未列出

实测:20 次上限如何被打满

在默认配置(AUTH_RATE_LIMIT_MAX=20)下,同一来源 IP 先后触发了 4 次 /api/auth 请求(打开页面时的 registration-status、me,加上两次登录态查询),随后脚本连续 POST 错误密码登录(ev_c1_ratelimit.txt 原文摘录):

try1  HTTP 200 {"user":null,"error":"Invalid email or password."}
try2  HTTP 200 {"user":null,"error":"Invalid email or password."}
  …(try3 ~ try15 同样输出,略)
try16 HTTP 200 {"user":null,"error":"Invalid email or password."}
try17 HTTP 429 {"error":"Too many requests. Please try again shortly."}
try18 HTTP 429 {"error":"Too many requests. Please try again shortly."}
  …(try19 ~ try21 同样输出,略)

数字对得上:窗口内先有 4 次,try1~try16 又 16 次,合计 20 次封顶;第 21 次起全部 429,直到 60 秒窗口滚动过期。错误密码尝试在 20 次以内始终返回 HTTP 200 + {"user":null,"error":"Invalid email or password."}——Cleep 不用 401 区分「密码错」与「未认证」,接口语义上前端自行处理。

三个必须知道的坑

  1. /api/auth 整前缀计数:打开一次 Cleep 页面,前端就会发 registration-status + me 两次请求,全部计入 20 次的桶。多人共用出口 IP 的办公室/校园网环境,1 分钟内 20 次「打开页面 + 登录」的组合很容易触发。对策:调大 AUTH_RATE_LIMIT_MAX,或缩短前端轮询类调用(无配置项,只能调上限)。
  2. 反代场景下全站共享一个桶:TRUST_PROXY=false(默认)时 req.ip 恒为直连对端——若前面有反向代理,所有访客的请求在应用服务看来都来自代理地址,全站共用同一个 20 次的桶,表现为「没人暴力破解却频繁 429」。开了反代必须同时把 TRUST_PROXY 设为 true(第六章)。
  3. 429 无 Retry-After:客户端拿不到确切等待时长,按窗口时长(默认 60 秒)退避即可;服务重启计数立即清零,急用时可直接重建服务恢复(仅建议自托管测试环境这么干)。

六、反向代理与 HTTPS

两个开关 + 一个响应头,三者联动,官方 .env.example 对每个都写了警示注释,这里按场景给出组合结论:

场景COOKIE_SECURETRUST_PROXY结果
纯 HTTP 直连(如 http://<nas-ip>:8140)false(默认)false(默认)正常可用;无 HSTS;限流按真实来源 IP 计数
反向代理终止 HTTPS,内部仍 HTTPtruetrueCookie 加 Secure 仅经 HTTPS 传输;下发 HSTS;限流按 X-Forwarded-For 还原的真实客户端 IP 计数
反代但忘开 TRUST_PROXYtruefalse ❌能用,但全站共享一个限流桶(第五章坑 2),恶意方还可伪造 X-Forwarded-For 绕过登录限流
纯 HTTP 直连但误开 COOKIE_SECUREtrue ❌—浏览器静默丢弃 Cookie:登录接口返回成功,之后所有请求 401,表现为「无限登录循环」
  • TRUST_PROXY=true 的确切语义(源码 app.set('trust proxy', 1)):只信任直接上游一跳的 X-Forwarded-For。多层代理链要在代理层收敛该头,或按 Express 文档改为自实现解析——Cleep 未暴露更细的配置项。
  • COOKIE_SECURE=true 的附加效果——HSTS(源码 server/middleware/securityHeaders.ts):此时所有响应追加 Strict-Transport-Security: max-age=15552000; includeSubDomains(180 天,含子域)。官方注释解释了为什么默认不发:纯 HTTP 源站下发 HSTS 会把浏览器钉死在 https:// 上,而该源站根本没有证书,用户直接被锁在门外。所以 HSTS 与 Secure Cookie 绑定同一个开关,切 HTTPS 时一次到位。

七、附件存储

  • ATTACHMENTS_DIR:附件落盘根目录,必填项。Compose 模板已硬编码注入 ATTACHMENTS_DIR=/data/attachments 并挂载宿主机 ./data/attachments,Compose 用户无需也不应该在 .env 里再设它——该变量只对手工(非 Compose)部署有意义。
  • 落盘布局为普通目录树:<ATTACHMENTS_DIR>/<用户ID>/<笔记ID>/<文件名>,实测当前环境为空目录(16KB 起步),笔记删除、用户注销时服务端会同步清理对应文件(源码 deleteAttachmentFilesForNotes)。
  • 备份即目录备份:与数据库导出(pg_dump)分开,仓库自带 scripts/backup.sh 已把两者打包(部署篇已初验)。迁移服务器时「库 + 附件目录」成对搬运即可。
  • 上传受 UPLOAD_RATE_LIMIT_MAX 限流(默认 60 次/分钟),与下载无关——下载接口不在限流范围。

八、注册开关与管理员引导

ADMIN_EMAIL / ADMIN_PASSWORD:首启引导,成对出现

  • 成对校验:assertRequiredEnv() 强制两者同时设置或同时不设,只设一个启动即退出(ADMIN_EMAIL and ADMIN_PASSWORD must both be set, or both left unset.)。
  • 幂等且不提权(源码 bootstrapAdmin.ts 逻辑,2026-10-25 通读确认):
    • 目标邮箱账号不存在 → 创建,角色 admin,用户名取邮箱 @ 前缀,密码 bcrypt 12 轮哈希入库;
    • 目标邮箱已存在且是管理员 → 打日志 bootstrapAdmin: admin account already exists, nothing to do.,不重置密码——改 .env 里的 ADMIN_PASSWORD 再重启不会修改已有管理员密码;
    • 目标邮箱已存在但只是普通用户 → 打警告日志跳过,绝不静默把普通账号提升为管理员。
    • 两者都不设 → 整个引导跳过(库里有历史管理员时推荐留空)。
  • 引导在迁移之后、监听之前执行,失败则启动中止。

registrationOpen:唯一的运行期配置

注册开关存数据库 app_settings 表(默认 false,即安装后默认禁止自助注册),由管理员经后台接口在线切换,无需重启。2026-10-25 实测完整闭环(ev_c1_settings.txt):

$ curl -s -b /tmp/cleep_admin.jar http://localhost:8140/api/admin/settings
{"registrationOpen":false}

$ curl -s -b /tmp/cleep_admin.jar -X PATCH http://localhost:8140/api/admin/settings \
    -H 'Content-Type: application/json' -d '{"registrationOpen":true}'
{"registrationOpen":true,"error":null}

$ curl -s http://localhost:8140/api/auth/registration-status
{"open":true}

$ curl -s -b /tmp/cleep_admin.jar -X PATCH http://localhost:8140/api/admin/settings \
    -H 'Content-Type: application/json' -d '{"registrationOpen":false}'
{"registrationOpen":false,"error":null}
  • GET /api/admin/settings 需管理员登录态(未登录实测返回 {"error":"Authentication required."});
  • PATCH 只接受布尔值,传其他类型返回 {"error":"registrationOpen must be a boolean."};
  • 切到 true 后公开注册接口立即放行(registration-status 变 {"open":true}),注册出的都是普通用户,管理员仍需后台创建或提权。
  • 家庭/小团队部署建议保持 false,账号由管理员逐个创建(对应专栏 API 篇详述)。

九、安全响应头

Cleep 未引入第三方安全头中间件,而是在 server/middleware/securityHeaders.ts 手工设置了固定一组,全部响应无条件下发,无配置项可关。实测响应头原文(未登录访问注册开关接口,COOKIE_SECURE=false,2026-10-25 抓取):

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' https: http: blob: data:; media-src 'self' blob:; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(self), microphone=(self), geolocation=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
X-Permitted-Cross-Domain-Policies: none

逐项速读:

头值对使用者的实际影响
Content-Security-Policydefault-src 'self',脚本/样式仅同源,图片放宽到任意 https/http/blob/data,对象插件全禁,禁止被嵌入(frame-ancestors 'none')前端无法加载第三方 JS;笔记内的外部图片、链接预览图正常显示(img-src 放宽即为它服务);不能把 Cleep 页面 iframe 进别的系统
X-Frame-OptionsDENY同上,双层禁止嵌入
Strict-Transport-Securitymax-age=15552000; includeSubDomains仅 COOKIE_SECURE=true 时下发(实测未出现,符合预期),见第六章
Permissions-Policy摄像头/麦克风同源可用,地理定位/支付/USB 全禁录音附件功能(浏览器录音)要求页面同源且 HTTPS 安全上下文
COOP / CORP均 same-origin防跨窗口信息泄漏;跨站引用 Cleep 的图片资源会被拦(CORP)
Referrer-Policystrict-origin-when-cross-origin跳出站外只带源不带路径

另有两处由框架层设置的细节:x-powered-by 已显式关闭(不暴露技术栈指纹);JSON 请求体上限 1MB(express.json({ limit: '1mb' }),超限 413,配置不可调——附件走 multipart 不受此限)。前端静态资源中 index.html 与 Service Worker 脚本强制 Cache-Control: no-cache,保证 PWA 升级能被发现,代理层请勿覆写这两个文件的缓存策略。

十、生产环境配置模板

综合以上各章,家庭/小团队「反向代理 + HTTPS」形态的推荐 .env(在官方 .env.example 基础上补齐源码支持的两个限流组,并显式写全默认值以便审计):

# /opt/cleep/.env —— 生产模板(反代 TLS 形态)
PUID=999
PGID=999
POSTGRES_PASSWORD=<强密码A>
DATABASE_URL=postgres://cleep:<强密码A>@postgres:5432/cleep
SESSION_SECRET=<openssl rand -hex 32 生成>

# —— 网络 / 代理 ——
PORT=6169
COOKIE_SECURE=true          # 前置反代已终止 HTTPS
TRUST_PROXY=true            # 限流按真实客户端 IP 计数(与 COOKIE_SECURE 一起开)

# —— 限流(显式写全,含 .env.example 未列出的两组)——
AUTH_RATE_LIMIT_MAX=20
AUTH_RATE_LIMIT_WINDOW_MS=60000
UPLOAD_RATE_LIMIT_MAX=60
UPLOAD_RATE_LIMIT_WINDOW_MS=60000
NOTE_LOCK_RATE_LIMIT_MAX=20
NOTE_LOCK_RATE_LIMIT_WINDOW_MS=60000
LINK_PREVIEW_RATE_LIMIT_MAX=300
LINK_PREVIEW_RATE_LIMIT_WINDOW_MS=60000

# —— 首启管理员引导(账号建好后可整段删掉)——
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=<首启密码>

⚠️ NOTE_LOCK_*、LINK_PREVIEW_* 两组变量官方 Compose 模板未透传,使用时在编排文件 app.environment: 段按同样写法各补两行(与既有 AUTH_RATE_LIMIT_MAX 透传行同格式),否则 .env 里的值进不了服务进程。纯 HTTP 直连形态把 COOKIE_SECURE、TRUST_PROXY 都改回 false 即可,其余不变。

变更操作速查:

想改什么操作生效
限流阈值、代理开关、数据库密码改 .env → docker compose up -d重建服务进程后生效
注册开关管理员调 PATCH /api/admin/settings立即
会话有效期、Cookie 属性、CSP无配置项,需改源码重构建—

十一、FAQ

Q1:登录接口返回成功,但一刷新就回到登录页/接口全 401? COOKIE_SECURE=true 但你在用纯 HTTP 访问——浏览器把带 Secure 的 Cookie 静默丢弃了。纯 HTTP 形态把它改回 false 并重新应用编排;或尽快给服务配上 HTTPS(推荐,第六章组合表)。

Q2:没人暴力破解,却频繁 429 Too many requests? 两种可能:① 反代场景忘开 TRUST_PROXY,全站共享一个 20 次的桶(第五章坑 2);② 多人共用出口 IP,/api/auth 整前缀计数把正常打开页面也算进去(坑 1)。分别开 TRUST_PROXY、调大 AUTH_RATE_LIMIT_MAX。

Q3:改了 .env 里的 ADMIN_PASSWORD,管理员密码没变? 引导逻辑幂等:账号已存在时什么都不做(既不建号也不改密码)。改管理员密码走管理端重置接口(见 API 篇)或登录后自行改密;.env 里的 ADMIN_PASSWORD 只影响「该邮箱账号尚不存在」的首次引导。

Q4:唯一的管理员密码忘了怎么办? 三个途径,按代价从小到大:① 若还有另一个管理员账号,用它调 POST /api/admin/users/:id/password 重置(会强制目标账号全设备下线);② 直接改库:对 users 表该行 UPDATE password_hash 为新 bcrypt 哈希(12 轮);③ 删除该用户行后重启服务,让 ADMIN_EMAIL/ADMIN_PASSWORD 重新引导——注意 notes、sessions 对用户是级联删除,该账号全部笔记会一并消失,务必先导出。

Q5:限流是分布式的吗?多实例部署共享计数吗? 不是。计数在单进程内存里(源码注释明示单实例自托管定位),重启清零、多实例不共享。v0.4.4 官方不支持水平扩展形态。

Q6:能把 Cleep 嵌进公司门户的 iframe 里吗? 不能。X-Frame-Options: DENY + CSP frame-ancestors 'none' 双重禁止,属硬编码安全设计,无开关(第九章)。跳转或 SSO 改造需等官方支持。

Q7:PORT 改成 8080 后访问不通? PORT 只是应用服务内部监听端口;对外端口由编排 ports 映射决定。官方模板 ports 写作 "${PORT:-6169}:${PORT:-6169}" 时改 PORT 两端同步变;若你的编排把映射写死为 8140:6169(本文实测环境即如此),改 PORT 只会改变服务内部监听而映射左侧不变,需同步修改映射。改完记得数据库连接串不受影响(走内部服务名)。

十二、参考链接