别再用 Keep 存私密笔记了,一条命令把笔记全搬回自己的 NAS

最近没怎么把心思放在折腾上,因为迷上了两样东西,一个是 Vibe Coding,一个是某果的 AI 短视频,什么万妖、聚宝盆刷了个天昏地暗,虽然智商下降了,但是快乐确实增加了 😂

简介

什么是 Cleep?

Cleep 是一个开源的 Google Keep 自托管替代品。它提供了与 Google Keep 非常接近的彩色卡片式笔记体验,支持文本笔记、清单、图片/视频/音频附件、标签分类和全文搜索,所有数据都保存在你自己服务器上的 PostgreSQL 数据库里,不需要订阅、没有广告,也不会有第三方来读取你的笔记。

主要特点

  • 笔记与清单:支持置顶、配色、归档、回收站,并且可以随时把一条普通笔记转换成清单(或反过来),转换按行处理,不会丢失内容
  • 多媒体附件:照片、视频可以直接上传,音频还能在浏览器里直接录制
  • 链接预览卡片:笔记里的每个 URL 都会生成一张预览卡片。图片和 faviconCleep 抓取后中转输出,因此在严格的 img-src 'self' CSP 下也能正常显示,同时目标站点看不到你的真实 IP
  • 标签与搜索:用标签把笔记组织成集合,配合多选批量操作;搜索覆盖整个笔记库,还支持按一个或多个集合过滤(Any/All
  • 键盘快捷键/ 搜索、c 新建笔记、l 新建清单、g n/a/t 快速跳转、? 查看完整列表
  • 多用户账号:基于 Session 的登录认证,每个人只能看到自己的笔记,管理员可以重置被锁定用户的密码
  • 数据可迁移:支持从 Google Keep 导入(上传 Google Takeout 导出的 zip),也可以一键把所有数据导出成 zip,数据不会被锁死
  • PWA 支持:可以添加到手机主屏,并具备离线应用外壳(需要 HTTPS 环境)
  • 部署简单:一条 docker compose up 就会把 Postgres 和应用一起拉起来,基本没有其他需要配置的东西
  • 开源免费:基于 Apache-2.0 协议开源,可免费使用和修改

应用场景

  • 替代 Google Keep 做日常速记:购物清单、待办事项、随手灵感、临时图片,界面上手成本几乎为零,习惯了 Keep 的人不需要重新学习
  • 注重隐私的个人笔记库:工作记录、密码提示、家庭资料等不希望上传到第三方云端的笔记,全部留在自己的 NAS
  • 家庭多成员共享一台设备:多用户账号 + 各自独立的笔记空间,一台群晖就能满足全家人的需求,管理员还能帮忘密码的成员重置
  • 从 Google Keep 搬家:通过 Google Takeout 导出后直接导入,标题、清单、颜色、标签、置顶/归档状态和媒体文件都能带过来
  • 开发者测试:项目提供 npm run dev:demo 和纯前端 Demo 模式,不依赖后端即可调试界面

Cleep 笔记列表界面(浅色模式

总的来说,Cleep 是一个界面和操作习惯都对标 Google Keep、但把数据完全握在自己手里的轻量级自托管笔记工具。

安装

在群晖上以 Docker 方式安装。

本文写作时,latest 版本对应为 sha-8c50380 ,比 v0.3.2 更新

Cleep 包含 postgresapp 两个服务,属于多容器项目,镜像发布在 ghcr.io/blindpassasjer/cleep,因此推荐使用 docker-compose 部署。

准备环境变量

先在 docker 文件夹中创建 cleep 目录,然后进入该目录准备 env.txt 文件。

需要填写的变量有:

可变
PUID 999
PGID 999
POSTGRES_PASSWORD 自定义数据库密码
DATABASE_URL postgres://cleep:自定义数据库密码@postgres:5432/cleep
SESSION_SECRET openssl rand -hex 32 生成
PORT 6169
ADMIN_EMAIL 初始管理员的邮箱
ADMIN_PASSWORD 初始管理员的密码

完整内容参考项目根目录的 .env.example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Postgres 容器运行的用户,以及 ./data/postgres 在宿主机上的属主
PUID=999
PGID=999

# postgres 服务和下面的 DATABASE_URL 共用这个密码,两者必须一致
POSTGRES_PASSWORD=change-me

# 应用连接 Postgres 的连接串,必填;compose 部署时主机名就是服务名 postgres
DATABASE_URL=postgres://cleep:change-me@postgres:5432/cleep

# 用于签名 Session Cookie 的密钥,必填,用 openssl rand -hex 32 生成
SESSION_SECRET=9d88d45300940353361360f68cc0e48d72df0c7534eec6a4cfda9adf15494322

# 应用在容器内监听的端口
PORT=6169

# 是否给 Session Cookie 加 Secure 标记,直接用 http 访问时保持 false
COOKIE_SECURE=false

# 是否信任上游代理的 X-Forwarded-For 头,直接访问容器时保持 false
TRUST_PROXY=false

# 限流参数,默认值一般够用
AUTH_RATE_LIMIT_MAX=20
UPLOAD_RATE_LIMIT_MAX=60

# 可选:同时设置这两项可以在首次启动时自动创建管理员账号
ADMIN_EMAIL=wbsu2003@gmail.com
ADMIN_PASSWORD=laosu123

环境变量说明

  • DATABASE_URL 中的密码必须和 POSTGRES_PASSWORD 保持一致,否则应用启动时会连接失败;
  • SESSION_SECRET 没有默认值,不填应用会直接启动失败;
  • ADMIN_EMAIL / ADMIN_PASSWORD 只在数据库中还没有任何账号时生效,账号建好之后就可以留空。

docker-compose 安装

将下面的内容保存为 docker-compose.yml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
services:
postgres:
image: postgres:16-alpine
container_name: cleep-db
restart: unless-stopped
# user: "${PUID:-999}:${PGID:-999}"
volumes:
- ./data:/var/lib/postgresql/data # 数据库文件,宿主机上可直接浏览和备份
environment:
POSTGRES_USER: cleep
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in env.txt}
POSTGRES_DB: cleep
healthcheck:
test: ["CMD-SHELL", "pg_isready -U cleep -d cleep"]
interval: 5s
timeout: 5s
retries: 10

app:
image: ghcr.io/blindpassasjer/cleep:latest
container_name: cleep-app
restart: unless-stopped
ports:
- "${PORT:-6169}:${PORT:-6169}"
volumes:
- ./attachments:/data/attachments # 照片、视频、录音,按用户和笔记分子目录存放
environment:
DATABASE_URL: ${DATABASE_URL:?Set DATABASE_URL in env.txt}
SESSION_SECRET: ${SESSION_SECRET:?Set SESSION_SECRET in env.txt}
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:-}
depends_on:
postgres:
condition: service_healthy # 等数据库就绪后再启动应用

然后通过 SSH 登录到您的群晖,执行下面的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 新建文件夹 cleep 和 子目录
mkdir -p /volume1/docker/cleep/{attachments,data}

# 进入 cleep 目录
cd /volume1/docker/cleep

# 修改目录权限
chmod a+rw data

# 将 docker-compose.yml 放入当前目录

# 一键启动
docker-compose --env-file env.txt up -d

提示:该项目包含多个服务,建议使用 docker-compose 进行部署,可以自动处理服务间的依赖关系。容器启动时会先自动执行数据库迁移,再根据 ADMIN_EMAIL / ADMIN_PASSWORD 创建初始管理员。

运行

在浏览器中访问 http://<群晖IP>:6169 即可进入登录界面

env.txt 中配置的 ADMIN_EMAILADMIN_PASSWORD 登录

如果需要给家人或同事使用,在应用内注册新的普通账号,各账号的笔记互相隔离

支持新建 New List

也可以添加图片和音频

随便建了几个

现在你可以在「Settings(设置)Your data(你的数据)」里可以执行 Export all data 导出全部数据

如果你之前使用 Google Keep,可以用 Import from Google Keep 导入从 Google Takeout 导出的 Keep 压缩包(选择 Keep 一项,标题、清单、颜色、标签、置顶/归档状态和媒体都会带过来,回收站里的笔记会被跳过)

注意事项

  1. 数据目录在宿主机上是可见的:笔记、用户、标签存在 ./data/postgres,附件存在 ./data/attachments/<user-id>/<note-id>/<file>。它们是普通的绑定挂载目录而不是 Docker 卷,可以直接浏览、打包和迁移
  2. HTTPS 与 PWA:若需启用 PWA 安装、离线访问、麦克风录音,必须配置反向代理并终止 HTTPS,同时设置 COOKIE_SECURE=trueTRUST_PROXY=true
  3. 端口冲突:默认端口 6169,如有冲突可在 .env 中修改 PORT 并同步更新 docker-compose.yml 的端口映射
  4. 从 ghcr.io 拉取镜像:如果首次 docker compose pull 提示未授权,是因为 GHCR 上的包第一次发布时默认是私有可见性,需要在 GitHub 该包的设置里手动改成 public。国内网络下拉取 ghcr.io 可能较慢,可以考虑配置镜像加速或代理
  5. 安全建议SESSION_SECRET 请使用 openssl rand -hex 32 生成的随机值,不要复用示例值;如果通过公网访问,务必放在带 TLS 的反向代理之后,并避免使用弱口令

参考文档

blindpassasjer/cleep: Yet another Google Keep clone
地址:https://github.com/blindpassasjer/cleep

Cleep 在线 Demo(静态构建,数据仅保存在浏览器本地)
地址:https://blindpassasjer.github.io/cleep/

blindpassasjer/cleep 容器镜像包
地址:https://github.com/blindpassasjer/cleep/pkgs/container/cleep