Cleep 0.4.4 Docker Compose 部署指南

Ubuntu 24.04 + Docker Compose 从零部署 Cleep 0.4.4 实测指南:GHCR 镜像与 PostgreSQL 16 双服务编排、管理员账号引导、数据持久化布局、备份脚本初验、等价 docker run 与常见问题排障。

CleepCleep自托管NASDocker ComposePostgreSQL2026/10/25

Cleep 0.4.4 Docker Compose 部署指南

目标:在 Ubuntu 24.04 服务器上用 Docker Compose 从零部署 Cleep 0.4.4(官方 ghcr.io/blindpassasjer/cleep 镜像 + PostgreSQL 16),覆盖环境变量准备、首个管理员账号引导、启动验证、数据持久化布局、备份脚本初验与常用运维命令。文中全部命令与回显均在真实部署环境(Ubuntu 24.04、Docker Compose v2、Cleep 0.4.4 镜像 digest sha256:60da6a78…、PostgreSQL 16.15)实测通过。Cleep 的定位与选型对比见本专栏《Cleep 0.4.4 介绍与选型指南》。

一、环境信息

本篇部署目标与实测环境的关键信息如下,读者按本文操作时请将 IP 与密码换成自己服务器的取值:

  • 操作系统:Ubuntu 24.04 LTS,x86_64
  • 容器运行时:Docker(支持 Compose v2 插件,docker compose 子命令可用)
  • 应用镜像:ghcr.io/blindpassasjer/cleep:latest(2026-10-25 实查 digest sha256:60da6a78444ed38f2b4074c35a1a208b368c1b3aa75f3fe0c1f1971eefa98faf,镜像 OCI label org.opencontainers.image.version=0.4.4,大小约 365MB)
  • 数据库镜像:postgres:16-alpine(实测解析为 PostgreSQL 16.15)
  • 服务端口:Cleep 服务在 6169 端口监听,本文对外发布 8140 端口(可按需改)
  • 部署目录:/opt/cleep/(compose 文件与 .env 所在),数据目录 /opt/cleep/data/postgres/ 与 /opt/cleep/data/attachments/,备份目录 /opt/cleep/backups/
  • 演示管理员账号:admin@quzuo.net / q1w2e3r4(由 .env 的 ADMIN_EMAIL/ADMIN_PASSWORD 首次启动引导创建)

二、镜像选型说明

Cleep 只提供一种官方发行形态——GHCR 上的容器镜像 ghcr.io/blindpassasjer/cleep,配合仓库自带的 docker-compose.yml 一键起「应用 + PostgreSQL」双服务。没有 deb/rpm 等系统包,也不建议手工 npm 部署(那是开发形态)。

镜像标签策略(2026-10-25 实查 GHCR tags 接口):

标签形态示例说明用途建议
latestghcr.io/blindpassasjer/cleep:latest跟随 main 分支每次推送自动构建个人/NAS 快速上手(本文实测采用,当前即 0.4.4)
sha-<commit>ghcr.io/blindpassasjer/cleep:sha-cd81a01每个提交一个不可变标签需要精确回滚到某提交时使用
digest 锁定@sha256:60da6a78…内容寻址、绝对不可变生产环境推荐,升级由运维显式改 digest 触发

⚠️ 注意:GHCR 上没有 0.4.4 这类版本号标签(2026-10-25 实查仅有 latest 与 90 余个 sha-* 标签);latest 会随每次提交漂移,生产环境请改用 digest 锁定。

如何选:家庭 NAS / 个人使用直接跟 latest 即可(升级 = docker compose pull && docker compose up -d);对稳定性有要求的环境用 ghcr.io/blindpassasjer/cleep@sha256:60da6a78444ed38f2b4074c35a1a208b368c1b3aa75f3fe0c1f1971eefa98faf 形式锁定本文实测的 0.4.4 构建。

三、前置条件

  1. 已安装 Docker 与 Compose v2 插件,以下命令能正常输出版本号:
docker --version && docker compose version
  1. 服务器可访问 GHCR(ghcr.io)。国内网络拉取慢或超时时,为 Docker 守护进程配置代理后重试 docker compose pull;本文实测经代理拉取成功。

  2. 规划一个空闲的对外 Web 端口,本文用 8140,执行前先确认未占用:

ss -ltn | grep ':8140\b' || echo "8140 空闲"

实测回显(端口空闲时):

8140 空闲
  1. 创建部署目录与数据目录。Cleep 的 Postgres 服务以 uid/gid 999 运行(镜像内置 postgres 用户),数据目录必须先把属主改成 999,否则数据库首次初始化会因权限失败:
mkdir -p /opt/cleep/data/postgres /opt/cleep/data/attachments /opt/cleep/backups
chown -R 999:999 /opt/cleep/data/postgres

命令无回显即为成功;ls /opt/cleep/data/ 应看到 attachments postgres 两个目录。

四、部署步骤

本节按「准备环境变量 → 编写编排文件 → 拉取镜像 → 启动 → 验证」的顺序完成从零到可用。Cleep 官方推荐即为此形态,无需其他任何依赖。

4.1 准备环境变量文件

Cleep 的全部运行时配置通过环境变量注入,compose 项目目录下的 .env 文件负责承载。先生成会话签名密钥(64 位十六进制随机串):

openssl rand -hex 32

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

784e82cbbf04d24479a87fb9263bd51b836e8db2f09ddde4701dd0eeebfdd001

创建 /opt/cleep/.env,内容如下(密码等敏感值按自己环境替换;本文演示值可直接用于测试):

# /opt/cleep/.env
PUID=999
PGID=999
POSTGRES_PASSWORD=cleepdb2026
DATABASE_URL=postgres://cleep:cleepdb2026@postgres:5432/cleep
SESSION_SECRET=784e82cbbf04d24479a87fb9263bd51b836e8db2f09ddde4701dd0eeebfdd001
PORT=6169
COOKIE_SECURE=false
TRUST_PROXY=false
AUTH_RATE_LIMIT_MAX=20
UPLOAD_RATE_LIMIT_MAX=60
ADMIN_EMAIL=admin@quzuo.net
ADMIN_PASSWORD=q1w2e3r4

逐项说明:

变量作用本文取值说明
PUID / PGIDPostgres 进程运行的 uid/gid,须与 ./data/postgres 目录属主一致默认 999(镜像内置 postgres 用户)
POSTGRES_PASSWORD数据库 cleep 用户的密码与 DATABASE_URL 中的密码段必须一致
DATABASE_URL应用连接数据库的完整串;compose 网络内主机名固定为服务名 postgrespostgres://cleep:<密码>@postgres:5432/cleep
SESSION_SECRET会话 Cookie 签名密钥,必填无默认值,缺失时应用启动即失败openssl rand -hex 32 生成
PORT应用监听端口默认 6169
COOKIE_SECURE是否给会话 Cookie 加 Secure 标志仅当反向代理已终止 HTTPS 时设 true,否则登录后每个请求都会 401
TRUST_PROXY是否信任上游代理的 X-Forwarded-For(影响登录限流的客户端 IP 判定)仅在反向代理之后设 true,否则所有访客共享同一限流额度
AUTH_RATE_LIMIT_MAX每窗口登录/注册类请求上限默认 20
UPLOAD_RATE_LIMIT_MAX每窗口上传/导入导出请求上限默认 60
ADMIN_EMAIL / ADMIN_PASSWORD首次启动时引导创建的管理员账号;留空则不创建两个变量必须同时设置才生效

⚠️ 注意:.env 含数据库密码与会话密钥,属敏感文件。 compose 官方模板已在 git 中忽略它;生产服务器上建议 chmod 600 /opt/cleep/.env。

4.2 编写编排文件

创建 /opt/cleep/docker-compose.yml(与官方仓库自带模板一致,仅对外端口按本文规划发布为 8140):

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    user: "${PUID:-999}:${PGID:-999}"
    environment:
      POSTGRES_USER: cleep
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
      POSTGRES_DB: cleep
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U cleep -d cleep"]
      interval: 5s
      timeout: 5s
      retries: 10

  app:
    image: ghcr.io/blindpassasjer/cleep:latest
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DATABASE_URL: ${DATABASE_URL:?Set DATABASE_URL in .env}
      SESSION_SECRET: ${SESSION_SECRET:?Set SESSION_SECRET in .env}
      ATTACHMENTS_DIR: /data/attachments
      PORT: ${PORT:-6169}
      NODE_ENV: production
      COOKIE_SECURE: ${COOKIE_SECURE:-false}
      TRUST_PROXY: ${TRUST_PROXY:-false}
      AUTH_RATE_LIMIT_MAX: ${AUTH_RATE_LIMIT_MAX:-}
      AUTH_RATE_LIMIT_WINDOW_MS: ${AUTH_RATE_LIMIT_WINDOW_MS:-}
      UPLOAD_RATE_LIMIT_MAX: ${UPLOAD_RATE_LIMIT_MAX:-}
      UPLOAD_RATE_LIMIT_WINDOW_MS: ${UPLOAD_RATE_LIMIT_WINDOW_MS:-}
      ADMIN_EMAIL: ${ADMIN_EMAIL:-}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD:-}
    volumes:
      - ./data/attachments:/data/attachments
    ports:
      - "8140:6169"

编排要点解读:

  • 两个服务:postgres(数据)与 app(应用);depends_on: service_healthy 保证数据库通过健康检查后才启动应用。
  • 数据全部落宿主机普通目录:不用匿名卷,./data/postgres 与 ./data/attachments 直接可浏览、可备份。
  • 端口映射 8140:6169:左侧是对外发布端口(改成你规划的端口),右侧 6169 是应用监听端口(与 PORT 对应)。
  • 健康检查:pg_isready -U cleep -d cleep 每 5 秒一次、最多重试 10 次。

4.3 拉取镜像

cd /opt/cleep
docker compose pull

实测回显(尾部节选,分层下载过程略):

 6288ca1fda9c Extracting 1B
 6288ca1fda9c Pull complete 0B
 493c6ada4d66 Pull complete 0B
 f1a36da7b02d Pull complete 0B
 6bbd9b7ca1a1 Pull complete 0B
 171591073c1f Pull complete 0B
 1f145c2e42b2 Pull complete 0B
 Image ghcr.io/blindpassasjer/cleep:latest Pulled

⚠️ 网络说明:ghcr.io 在国内网络下可能拉取缓慢或超时。本文实测环境为 Docker 守护进程配置代理(192.168.1.62:7897)后一次拉取成功;如遇超时,配置代理或镜像加速后重试本命令即可,无需改动其他步骤。

4.4 启动服务

docker compose up -d

实测回显:

 Container cleep-020-stack-postgres-1 Starting
 Container cleep-020-stack-postgres-1 Started
 Container cleep-020-stack-postgres-1 Waiting
 Container cleep-020-stack-postgres-1 Healthy
 Container cleep-020-stack-app-1 Starting
 Container cleep-020-stack-app-1 Started

(回显中的项目名称前缀因各服务器 compose 项目目录名不同而不同,属正常现象。)

4.5 验证启动结果

第一步确认两个服务都在运行、数据库为 healthy:

docker compose ps

实测回显:

NAME                         IMAGE                                 COMMAND                  SERVICE    CREATED          STATUS                    PORTS
cleep-020-stack-app-1        ghcr.io/blindpassasjer/cleep:latest   "./docker-entrypoint…"   app        14 seconds ago   Up 8 seconds              0.0.0.0:8140->6169/tcp, [::]:8140->6169/tcp
cleep-020-stack-postgres-1   postgres:16-alpine                    "docker-entrypoint.s…"   postgres   14 seconds ago   Up 13 seconds (healthy)   5432/tcp

第二步看应用日志,应出现「迁移 → 引导管理员 → 监听端口」三段完整过程:

docker compose logs app

实测回显:

app-1  | Running database migrations...
app-1  | Migrations applied.
app-1  | Bootstrapping admin account...
app-1  | bootstrapAdmin: created admin account for admin@quzuo.net.
app-1  | Starting server...
app-1  | Cleep self-host server listening on port 6169

六行日志的含义:Running database migrations... / Migrations applied. 表示数据库表结构自动迁移完成(无需手工建表);Bootstrapping admin account... / created admin account for admin@quzuo.net 表示按 .env 的 ADMIN_EMAIL/ADMIN_PASSWORD 创建了首个管理员;最后两行表示 HTTP 服务已在 6169 端口监听。

第三步验证 HTTP 可达与安全响应头:

curl -sI http://127.0.0.1:8140/ | head -8

实测回显:

HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
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'
Permissions-Policy: camera=(self), microphone=(self), geolocation=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin

返回 200 且默认带全安全响应头(CSP、X-Frame-Options 等),说明服务正常。

第四步用管理员账号实际登录一次(API 方式,等价于浏览器登录动作):

curl -s -c /tmp/cleep-cookie.txt -X POST http://127.0.0.1:8140/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@quzuo.net","password":"q1w2e3r4"}'

实测回显:

{"user":{"id":"aba48719-7d4b-44b6-82c7-963a2b0fa777","email":"admin@quzuo.net","username":"admin","role":"admin"},"error":null}

返回 role:"admin" 的管理员用户对象即登录成功。此后浏览器访问 http://<服务器IP>:8140,用同一账号登录即可进入便签网格界面。

💡 说明:Cleep 注册默认关闭(管理员建号制)。管理员登录后在设置页的 Users 管理面板里逐个创建其他用户;直接调注册接口会得到 {"user":null,"error":"Registration is currently closed."}(HTTP 403),这是设计行为而非故障(详见「九、常见问题」)。

五、数据持久化说明

Cleep 的数据分两类、全部落在宿主机普通目录(非匿名卷),可直接用文件工具管理:

数据宿主机路径内容
数据库/opt/cleep/data/postgres/笔记正文、用户、会话、标签、链接预览缓存等(PostgreSQL 数据文件)
附件/opt/cleep/data/attachments/照片/视频/录音文件,按 <用户ID>/<笔记ID>/<文件名> 分层存放

实测:上传一张图片附件后,目录树真实落盘如下——

find /opt/cleep/data/attachments -type f

实测回显:

/opt/cleep/data/attachments/aba48719-7d4b-44b6-82c7-963a2b0fa777/cb983725-d38e-4ad5-b24f-e6332021dcdc/494c14fd-7e75-48a1-9b2b-56db9c302f29-t.png

数据库侧实测共 8 张表(psql -U cleep -d cleep -c '\dt' 回显节选):users、sessions、notes、labels、note_labels、attachments、link_previews、app_settings。

💡 说明:备份的最小单位就是「/opt/cleep/data/postgres 的一致性导出 + attachments 目录打包」。官方仓库自带 scripts/backup.sh(pg_dump + tar)与 scripts/restore.sh,本文第九章给出一次真实备份回显,完整备份/恢复/巡检流程见本专栏《Cleep 0.4.4 日常运维手册》。

六、环境变量表

下表汇总 compose 模板引用的全部环境变量(默认值与语义以官方 .env.example,2026-10-25 查询为准);逐项深解与调参建议见本专栏《Cleep 0.4.4 配置参数详解》:

变量必填默认值作用
SESSION_SECRET是无(缺失即启动失败)会话 Cookie 签名密钥
DATABASE_URL是无应用连接 PostgreSQL 的连接串
POSTGRES_PASSWORD是无数据库密码,须与 DATABASE_URL 同步
PUID / PGID否999 / 999Postgres 进程运行身份,须等于数据目录属主
PORT否6169应用监听端口
ADMIN_EMAIL / ADMIN_PASSWORD否空首启引导管理员账号(须成对设置)
COOKIE_SECURE否falseCookie Secure 标志,仅 HTTPS 反代后设 true
TRUST_PROXY否false信任 X-Forwarded-For,仅反代后设 true
AUTH_RATE_LIMIT_MAX / AUTH_RATE_LIMIT_WINDOW_MS否20 / 60000登录注册限流(次/毫秒窗口)
UPLOAD_RATE_LIMIT_MAX / UPLOAD_RATE_LIMIT_WINDOW_MS否60 / 60000上传与导入导出限流
LINK_PREVIEW_RATE_LIMIT_MAX / LINK_PREVIEW_RATE_LIMIT_WINDOW_MS否300 / 60000链接预览限流
ATTACHMENTS_DIR否/data/attachments(compose 内置)附件存储目录,仅裸机部署时需显式设置

七、配置参数说明

本节说明部署期最常调整的三组参数,完整参数体系(含限流窗口、会话与 Cookie 细节、反向代理配合)见本专栏《Cleep 0.4.4 配置参数详解》。

  1. 改对外端口:只改 compose 文件 ports 左侧(如 "8080:6169"),应用监听端口 PORT=6169 保持不变;改完 docker compose up -d 生效。
  2. 反向代理 + HTTPS:代理终止 TLS 后必须把 .env 中两项改为 COOKIE_SECURE=true、TRUST_PROXY=true 再重启应用,否则会出现「登录看似成功但每个接口 401」或「正常登录即触发 Too many requests」两个典型故障;启用 COOKIE_SECURE=true 后 Cleep 会同时发送 6 个月 max-age 的 HSTS 头,请确认该域名确实长期走 HTTPS。
  3. 更换数据库密码:POSTGRES_PASSWORD 只在数据库首次初始化时生效;已有数据的库改密码需同时改 DATABASE_URL 并在数据库内 ALTER USER cleep PASSWORD,仅改 .env 会导致应用连不上库(见「九、常见问题」Q3)。

八、等价 docker run

不使用 Compose 时,以下两条命令与上文编排完全等价(网络、卷、健康检查依赖需手工保证顺序,先起数据库并等待其可连接):

# 1. 启动数据库(数据目录属主须为 999)
docker run -d --name cleep-postgres --restart unless-stopped \
  --user 999:999 \
  -e POSTGRES_USER=cleep -e POSTGRES_PASSWORD=cleepdb2026 -e POSTGRES_DB=cleep \
  -v /opt/cleep/data/postgres:/var/lib/postgresql/data \
  postgres:16-alpine

# 2. 启动应用(--link 仅示意,生产建议用自定义网络按服务名互访)
docker run -d --name cleep-app --restart unless-stopped \
  -e DATABASE_URL=postgres://cleep:cleepdb2026@postgres:5432/cleep \
  -e SESSION_SECRET=784e82cbbf04d24479a87fb9263bd51b836e8db2f09ddde4701dd0eeebfdd001 \
  -e ATTACHMENTS_DIR=/data/attachments -e PORT=6169 -e NODE_ENV=production \
  -e COOKIE_SECURE=false -e TRUST_PROXY=false \
  -e ADMIN_EMAIL=admin@quzuo.net -e ADMIN_PASSWORD=q1w2e3r4 \
  -v /opt/cleep/data/attachments:/data/attachments \
  -p 8140:6169 \
  ghcr.io/blindpassasjer/cleep:latest

💡 说明:两条 docker run 需让两个实例处于同一自定义网络并能按主机名 postgres 解析(Compose 默认已处理好这一点);因此官方与本文都推荐 Compose 形态,等价命令仅作理解参数映射之用。

九、常用运维命令

以下命令均在 /opt/cleep/(compose 项目目录)下执行,全部实测通过:

# 查看服务状态
docker compose ps
# 跟踪应用日志
docker compose logs -f app
# 重启应用(改 .env 后)
docker compose restart app
# 升级到最新镜像(数据库迁移随启动自动执行)
docker compose pull && docker compose up -d
# 停止整套服务(数据目录保留)
docker compose down

重启后数据保持实测:docker compose restart app 后重新查询笔记列表,重启前创建的 2 条笔记均在(notes after restart: 2)。

备份实测:官方 scripts/backup.sh 在 compose 项目目录执行——

./backup.sh --keep 7

实测回显:

Dumping Postgres -> ./backups/20261025T042623Z/postgres.sql
Archiving attachments -> ./backups/20261025T042623Z/attachments.tgz
Done: ./backups/20261025T042623Z
Pruning old backups, keeping newest 7

产物为带时间戳的目录(postgres.sql 全量导出 + attachments.tgz 附件包 + README.txt 说明),--keep 7 表示只保留最新 7 份。恢复用 ./restore.sh ./backups/<时间戳>,本文实测删除一条笔记后从该备份完整恢复。完整操作与定时备份配置见本专栏《Cleep 0.4.4 日常运维手册》。

资源占用参考(实测,空闲状态):应用进程内存约 40MiB,PostgreSQL 约 80MiB——总计百兆级,适合低功耗 NAS。

十、常见问题

Q1:拉取 ghcr.io 镜像超时怎么办? 为 Docker 守护进程配置 HTTP 代理(/etc/docker/daemon.json 的 proxies 或 systemd drop-in)后 systemctl restart docker,重试 docker compose pull;也可先 docker login ghcr.io 排除匿名配额问题。本文实测经代理一次成功。

Q2:浏览器登录后立刻被踢回登录页 / 接口全 401? 绝大多数是 COOKIE_SECURE=true 但你仍在用 http:// 访问——带 Secure 的 Cookie 在 HTTP 下被浏览器静默丢弃。纯 HTTP 直连场景保持 COOKIE_SECURE=false;只有反向代理终止 HTTPS 后才设 true。

Q3:改了 .env 里的 POSTGRES_PASSWORD 后应用起不来? POSTGRES_PASSWORD 仅在数据库首次初始化时写入;对已初始化的数据目录改密码需要三步同步:改 .env 两处(POSTGRES_PASSWORD 与 DATABASE_URL)→ 进数据库执行 ALTER USER cleep WITH PASSWORD '新密码'; → docker compose up -d。

Q4:注册接口返回 403 "Registration is currently closed."? 设计行为:Cleep 默认关闭公开注册(实测 GET /api/auth/registration-status 返回 {"open":false})。由管理员登录 Web 界面,在 Users 管理面板创建账号;管理员也可以在后台为重置密码的用户生成临时密码。

Q5:首次启动日志卡在 migrations 或报数据库连接失败? 按顺序排查:① data/postgres 目录属主是否为 999:999(PUID/PGID 默认值);② .env 中 DATABASE_URL 的密码段是否与 POSTGRES_PASSWORD 一致;③ docker compose logs postgres 是否已正常完成初始化。

Q6:手机浏览器为什么不能「添加到主屏幕」/离线使用? PWA 安装与录音都要求安全上下文(HTTPS 或 localhost)。纯 http://<nas-ip>:8140 下这两项不可用(笔记本体不受影响);为站点套上任意反向代理的 TLS 证书后即解锁,同时记得设置 TRUST_PROXY=true。

十一、参考链接