Skip to content
twinkling.top服务Paperless-ngxEN
板型Pi 4B 4GB and up. The OCR worker saturates one core per document; a hundred-page scan takes about four minutes
内核6.6.51+rpt-rpi-v8
空闲温度48 °C
内核架构arm64
参考机:Pi 4B 8GB / Bookworm 64-bit

部署配方 · 文件与存储

Paperless-ngx:会回答问题的档案柜

被它取代的那套「扫描归档」流程,是一棵带着两个人各有意见的命名约定的目录树。Paperless-ngx 接手扫描件,做 OCR,猜出往来方和日期,并让整个库可以搜索——于是「锅炉保修卡在哪」从二十分钟的翻找变成十秒的检索。

ghcr.io/paperless-ngx/paperless-ngx:2.14.5 · 2026-10-09 ·

Paperless-ngx rack plate: board stack and host ports
服务参数
容器镜像ghcr.io/paperless-ngx/paperless-ngx:2.14.5
宿主端口:8010/tcp
数据目录/srv/homelab/paperless/media
内存预留900 MB
CPU 上限1.0 vCPU (cpus: "1.0") — OCR is the only expensive operation and it is bursty
更新节奏quarterly. The database migrations are well tested, but the OCR language packs and the classification model need re-downloading after a major bump
ARM 兼容arm64 native including the Tesseract OCR binaries; OCR on a Pi is slow but completely usable for household volumes
端口映射与暴露面
宿主容器proto暴露用途
:80108000tcp仅局域网web UI for search, tagging and the document viewer

部署步骤

  1. 按容器期望的 uid 建好三个目录

    USERMAP_UID 决定运行时用户,媒体和数据目录由它写入。投递目录在 NAS 上,那边也要做同样的处理。

    run
    sudo mkdir -p /srv/homelab/paperless/{data,media,export}
    sudo chown -R 1000:1000 /srv/homelab/paperless
    sudo chown -R 1000:1000 /mnt/nas/paperless-consume
  2. 首次启动时把 OCR 语言包装上

    镜像会在首次启动时按 PAPERLESS_OCR_LANGUAGES 下载语言包。没装就启动,之后每一份非英文文档都会是空的。

    run
    docker compose up -d paperless-db paperless-redis
    docker compose up -d paperless
    docker logs -f paperless | grep -i 'installing language'
    # 等它装完再上传任何东西
  3. 建好账号并关闭自助注册

    通过注册表单创建的第一个账号成为管理员。把家里人的账号加完,顺手把注册关掉。

    run
    # 管理 -> 用户 -> 新建用户,然后
    # 管理 -> 设置 -> 关闭「允许注册」
  4. 在导入任何东西之前,先定好 OCR 语言和工作进程数

    在一万份文档处理完之后再改 OCR 语言,意味着要全部重跑 OCR。先定下来。

    run
    docker exec paperless document_ocr --help
    docker exec paperless document_index reindex --help
    # 万一设置还是错了,这两个命令都在
  5. 先做一份测试文档,再做一次恢复演练

    在把全家的档案托付给它之前,先导出并导入到一个临时实例里。发现「导出里并没有你以为的东西」这件事,现在做比在旧档案柜已经清空之后做要好。

    run
    docker exec paperless document_exporter /usr/src/paperless/media/export --no-thumbnail
    du -sh /srv/homelab/paperless/media/export
    ls /srv/homelab/paperless/media/export | head

进件路径决定这套东西能不能用起来

Paperless 盯着一个投递目录。丢进去的任何东西都会被处理:OCR、分类、打标签,并按元数据改名。这个家里的做法是让扫描仪写到 NAS 上的一个文件夹,绝不直接写进 Paperless——这样扫描失败的表现是文件夹里躺着一个文件,而不是一个消失的任务。

第二个投递子目录用不同的命名约定,专门收那些应当算作来信而不是归档记录的文件。一开始就把投递结构定对,能省下以后给一千份文档重新打标签的工夫。

shell
# consume/           -> 常规进件
# consume/inbox/     -> 信件和账单,标为来信
# 丢一个 PDF 进去看它处理
docker logs -f paperless | grep -i consuming

树莓派上的 OCR:很慢,但是那种正确的慢

Tesseract 在 Pi 4 默认设置下大约每分钟二十五页。十页的水电账单二十秒;一百页的房贷文件四分钟,期间占满一个核。

工作进程数刻意设为一。四核板子上开两个 OCR 进程会让机架上其它一切都变迟钝,而且没有任何家庭文档量能证明第二个进程有必要。

文档页数Pi 4 上耗时CPU
水电账单3约 8 秒一个核,短暂
保单24约 60 秒一个核
房贷材料120约 5 分钟一个核,持续
无文字的扫描照片1约 2 秒一个核,短暂

文件命名模板与「家用级」元数据

文件名格式是一套基于元数据字段的模板,它在投递时应用,而不是在改名时应用。太晚才决定它,要么忍受不一致的文件名,要么触发整个档案重新处理。

日期是最容易出错的一个字段,因为 Paperless 是从正文里猜的。凡日期在法律上有意义的文档,都要打开把日期改正再让它进档案——因为错误的日期比缺失的日期更难在以后找出来。

shell
PAPERLESS_FILENAME_FORMAT: '{created}-{correspondent}-{title}'
# -> 2026-03-14-Northwind Energy-Annual statement.pdf
# 改完之后跑:document_renamer

导出才是真正的备份

只有媒体目录不够:没有数据库,标签、往来方、文档类型全都消失,只剩一堆命名正确的 PDF。反过来只有数据库,那就是一份列着不存在的文档的清单。

document_exporter 把两者加上元数据写成一棵可移植的目录树,未来的 Paperless 版本能重新导入。这里每月跑一次,叠在每晚的文件级复制之上,因为它是唯一能在整套栈彻底重建之后依然存活的东西。

shell
docker exec paperless document_exporter /usr/src/paperless/media/export \
  --no-thumbnail --use-filename-format
# 导出的树是自描述的,可以重新导入

compose 文件

整份文件放在 /srv/homelab/paperless-ngx/compose.yaml。标签固定版本号,不用 latest——树莓派上回滚比升级麻烦得多。

compose.yaml
services:
  paperless:
    image: ghcr.io/paperless-ngx/paperless-ngx:2.14.5
    container_name: paperless
    restart: unless-stopped
    ports:
      - "8010:8000/tcp"
    environment:
      TZ: Asia/Shanghai
      PAPERLESS_REDIS: redis://paperless-redis:6379
      PAPERLESS_DBHOST: paperless-db
      PAPERLESS_DBNAME: paperless
      PAPERLESS_DBUSER: paperless
      PAPERLESS_DBPASS: ${PAPERLESS_DB_PASSWORD}
      PAPERLESS_OCR_LANGUAGES: eng chi_sim
      PAPERLESS_OCR_LANGUAGE: eng+chi_sim
      PAPERLESS_TIME_ZONE: Asia/Shanghai
      PAPERLESS_URL: https://docs.lan
      PAPERLESS_OCR_MODE: skip_noarchive
      PAPERLESS_FILENAME_FORMAT: '{created}-{correspondent}-{title}'
      PAPERLESS_TASK_WORKERS: "1"
      PAPERLESS_THREADS_PER_WORKER: "1"
      USERMAP_UID: "1000"
      USERMAP_GID: "1000"
    volumes:
      - /srv/homelab/paperless/data:/usr/src/paperless/data
      - /srv/homelab/paperless/media:/usr/src/paperless/media
      - /mnt/nas/paperless-consume:/usr/src/paperless/consume
    depends_on:
      paperless-db:
        condition: service_healthy
    networks: [rack]

  paperless-redis:
    image: redis:7.4-alpine
    container_name: paperless-redis
    restart: unless-stopped
    networks: [rack]

  paperless-db:
    image: postgres:16-alpine
    container_name: paperless-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: paperless
      POSTGRES_USER: paperless
      POSTGRES_PASSWORD: ${PAPERLESS_DB_PASSWORD}
    volumes:
      - /srv/homelab/paperless/db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U paperless"]
      interval: 10s
      timeout: 5s
      retries: 6
    networks: [rack]

networks:
  rack:
    external: true

加固清单

  • 实例放在认证门户后面——一个可搜索的全家文档索引,能不用单因素就别用
  • 账号按人分配,管理员账号只用于配置,普通会话改不了处理规则
  • 投递目录是 NAS 上一个只有某个家庭账号可写的文件夹,也是扫描仪的进件通道
  • OCR 语言集裁剪到实际使用的语言,既为速度,也因为没用的语言包就是多出来的、未经验证的解析代码

备份方案

有三样东西必须一起复制,分开就没意义了:存原始文件和 OCR 文本的媒体目录、数据库、以及投递目录。export 命令会写出一个包含全部内容的可移植归档,每月跑一次,作为双保险。

上线后验证

  • 丢进去的 PDF 在一分钟内出现在档案里,且文本可搜索
  • 搜索一个只存在于某页扫描图像里的短语能返回该文档,说明 OCR 跑了
  • document_exporter 的输出能导入到临时实例,且标签结构一致
  • 一批处理完之后投递目录是空的,失败项被挪进失败目录而不是无限循环

踩过的坑

  • 一份没有 OCR 文字层、而 OCR 模式设置又不可读的 PDF,会产出一份没有文本、也没有报错的文档。在批量导入十年扫描件之前,先确认 OCR 模式。
  • Postgres 和媒体目录必须一起备份。把媒体目录恢复到一份更旧的数据库上,会产生「作为文件存在、但作为记录不存在」的文档。
  • 导入之后改文件名模板不会立刻改名,要跑 document_renamer;而跑它会改变路径,任何指向这些文件的外部链接就断了。
  • 投递目录绝不能就是扫描仪直接写入的那个文件夹。一个只写了一半的文件被处理,会在档案里留下一份损坏的文档。

硬件与选型问答

树莓派做真实档案的 OCR 够快吗?
对家庭文档量来说够。一千份平均四页的文档,按每页两秒半算,大约两个半小时的后台 OCR。放夜里跑就结束了。派吃力的是批量导入五万页这种活——那应该用笔记本做,然后把数据目录搬过来。
扫得很糟的文档会怎样?
它们会带着很差的文本、但完整的原始图像进档案,所以你手工修正元数据之后依然能找到它们。重扫是可行的,但很少需要——更好的扫描仪和 300 dpi 的设置是预防问题,而不是事后修问题。
我可能要交给官方机构看的东西能放这儿吗?
能,导出目录树就是为此设计的:原件、启用对应模式时的 PDF/A 版本、以及 OCR 文本并排放着。法律事务上算数的是原件,这也是为什么进件流程从不修改源文件。