浏览器收藏夹里的一条链接,过几个月再点开,可能只剩登录页、改版后的首页,或者一段“内容已删除”。为了找一句当时觉得有用的话,又得重新搜关键词。Readeck 适合处理这类问题:把网页中可阅读的正文保存下来,配上标签、标注和集合,给以后查找留一个入口。
它也适合把手机上来不及读的文章交给电脑继续读。这里用 Docker 在 VPS 上部署一个私人实例,先打通保存、阅读、导出这条流程,再安排备份。网页解析有成功率,登录后才能看到的内容、复杂脚本生成的页面,以及已经失效的图片,都需要单独检查,不能以“加入成功”作为完整保存的证据。
收藏的是哪些内容
Readeck 会提取文章正文,并处理关联的阅读资源。阅读界面提供高亮、标签和集合,文章或集合可以导出 EPUB,支持 OPDS 的阅读器还可以访问它的目录。这几个功能分别处理不同的阅读需要:标签负责找,集合负责安排一组要读的文章,高亮负责留下真正需要回看的段落。
先选十篇能公开访问的网页试用,比一次导入几千条书签更容易判断是否合适。样本里放一篇长文、一篇含代码的教程、一篇图片较多的文章和一篇中文新闻,逐一对照源页面检查正文、标题与图片。某种网站总是提取不全,就保留原始链接并换一种保存方式,不要把有缺漏的结果当档案。
一个个人实例可以先用默认的 SQLite,省去单独维护数据库。容量主要随保存的内容增长,尤其是图片。没有必要为一个阅读工具先选很高的 CPU 配置,但需要有稳定的出站访问、够用的磁盘,以及能够放到另一台机器上的备份空间。服务器到内容网站的网络同样影响抓取,浏览器能打开网页并不代表 VPS 也能访问。
把实例放在一个固定目录
本文假定服务器已经装好 Docker Engine 和 Compose 插件,且当前账号有执行 Docker 的权限;没有权限时通过管理员配置或给命令加 sudo。域名示例 read.example.com 需要改成自己的,并把 DNS 指向服务器。Caddy 安装在宿主机,入口使用 80、443,应用端口只监听回环地址。
mkdir -p /opt/readeck/data
cd /opt/readeck
docker version
docker compose version
保存下面的内容为 compose.yaml。镜像、挂载目录及健康检查采用项目提供的部署方式,把宿主机端口限制在 127.0.0.1。使用相对路径时,后续所有 Compose 操作都在这个目录进行。
services:
readeck:
image: codeberg.org/readeck/readeck:latest
restart: unless-stopped
ports:
- "127.0.0.1:8000:8000"
environment:
READECK_SERVER_HOST: "0.0.0.0"
READECK_SERVER_PORT: "8000"
READECK_LOG_LEVEL: info
READECK_LOG_FORMAT: text
volumes:
- ./data:/readeck
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD", "/bin/readeck", "healthcheck", "-config", "config.toml"]
interval: 30s
timeout: 2s
retries: 3
latest 用于第一次选择当前镜像,日常使用应把拉取成功的镜像摘要记下来,并固定到 镜像名@sha256:摘要,不要让定时更新器替你跨版本升级。固定摘要后也要主动检查新版本,不能把“固定”理解成以后不用维护。
docker compose config --quiet
docker compose pull
docker image inspect codeberg.org/readeck/readeck:latest --format '{{json .RepoDigests}}'
docker compose up -d
docker compose ps
docker compose logs --tail=80 readeck
curl -I http://127.0.0.1:8000/
日志里如果出现写入配置或数据库失败,先检查 data 的所有者、磁盘剩余容量以及挂载是否正确,不要直接把整个目录改成任何人可写。修改目录权限需要对照所用镜像的运行用户。容器不断重启时,反复执行 up -d 并不能修复写入失败。
第一个账号先在私人入口里创建
初始化阶段先使用 SSH 转发,在自己的电脑执行下面的命令,替换 SSH 用户和服务器地址,再用浏览器打开本机 18000 端口。
ssh -N -L 18000:127.0.0.1:8000 [email protected]
创建管理员账号,设置独立密码,登录后存入一篇测试文章。确认初始化完成后,再配置域名入口。Caddyfile 中添加以下站点段,先验证配置,然后通过服务管理工具重载 Caddy。
read.example.com {
reverse_proxy 127.0.0.1:8000
}
这个上游地址只适用于 Caddy 在宿主机运行的情况。如果反向代理也在容器里,它的 127.0.0.1 指向自己,要改为共享 Docker 网络里的服务地址,不能照抄。域名入口启用以后,检查地址栏确实是 HTTPS,再设置浏览器扩展的实例地址。不要把扩展连到临时 IP、旧域名或另一个同名服务上。
首次账号创建后,确认管理员设置中的用户范围,避免把私人阅读库误做成开放注册服务。也可以把入口限制在 VPN 网络,只给自己的设备访问。多一个家庭成员时应单独建账号,保存入口和访问凭据分别设置,便于以后撤销某一台设备的权限。
让保存下来的文章还能找得到
刚开始只设少量能长期沿用的标签,例如“数据库”“网络”“待核实”。把标签取成一句完整的文章标题,通常没有检索收益,反而增加维护负担。同一领域的不同阅读目的可以放进集合:迁移前要查的文档组成一个集合,周末准备读的长文组成另一个。
高亮也需要节制。一篇文章标满整页,回看的效果和没有标注差不多。可以只标配置限制、重要结论和容易忘记的数字,再在自己的笔记里写清楚为什么留下这句话。文章保存的日期与原文的更新日期不同,涉及软件参数时,仍应以目前使用版本的官方文档为准。
浏览器扩展接好后,分别从电脑和手机保存同一类型的页面,检查它们进入的是同一个账号。移动端分享入口的具体方式取决于客户端,选用客户端前确认它连接自建实例所需的地址和认证方式。给第三方客户端生成的访问凭据应独立管理,不要把管理员密码散落在各种脚本里。
导出一次 EPUB,真正用阅读器打开,比只看到导出按钮更有用。检查目录、图片和代码是否可读,尤其是长代码行在小屏幕上是否截断。准备离线阅读前先下载成品文件;服务器里的书目目录可见,不代表设备在断网后还有完整正文。
抓不到正文时按链路排查
先在服务器上检查目标网站是否能访问,再看 Readeck 日志中的抓取错误。如果网络超时,要处理服务器出站路径或目标站点的访问限制;如果请求成功但正文只剩导航,问题更可能在页面结构与提取环节。换一篇同站点的公开文章对比,可以缩小范围。
访问自建页面出现 502 时,先用宿主机 curl 访问 8000 端口。这里也失败,检查容器;这里正常而域名失败,检查代理上游、Caddy 日志和端口绑定。页面能登录但保存任务一直不完成,则应看应用的抓取日志,不要把所有错误都归到 HTTPS。
私人实例不应开放给陌生人随意提交抓取地址。服务端会代用户访问 URL,权限和网络范围都要认真管理。如果一份收藏需要用于正式的项目归档,还应记录标题、保存时间和关键附件,单独验证附件可恢复;阅读工具里的页面快照不适合承诺完整复现原站的所有行为。
备份整个数据目录,再练习恢复
本例没有外接 PostgreSQL,数据库、配置和保存的内容都在 data 挂载目录里。最容易理解的一致性备份是短暂停止应用,再打包整个目录。提前确认目标位置空间够用,备份成功后重启;打包失败也要记得恢复服务。
cd /opt/readeck
mkdir -p /opt/backups
docker compose stop readeck
tar -czf "/opt/backups/readeck-$(date +%F-%H%M).tgz" compose.yaml data
docker compose start readeck
这份压缩包还在原 VPS 上,只能应对误操作,不能应对整台机器丢失。再复制到另一处有访问限制的存储,保留几份不同日期的备份。阅读库中可能有私人文章、访问令牌和账号信息,压缩不是加密。
恢复时,在另一个目录解压,用备份时的镜像版本启动,临时入口仍限制在回环地址,并换一个宿主机端口,避免和现有实例冲突。登录后随机打开几篇较早保存的文章、下载 EPUB、检查高亮与标签。升级前重复这个过程,遇到数据库格式迁移失败,回退应使用旧镜像和升级前的完整数据一起恢复。
日常使用时,每周花几分钟整理未读集合,删除明显保存失败或已经不需要的内容。Readeck 的价值会体现在下次查资料时:输入几个关键词,就能找到当初留下的正文和标注,而不必回头猜那条链接原来写过什么。