用 paperless-ngx 搭建私有合同与报销管理系统

纸质合同、发票、报销单和付款凭证最麻烦的地方,不是“存不下”,而是“找不到、分不清、说不清”。paperless-ngx 是一个开源的文档管理系统,适合把扫描件、PDF、图片、邮件附件统一归档,通过 OCR 自动识别文字,再用标签、通讯方、文档类型、日期和全文搜索快速定位资料。

如果你希望用一套低成本、可私有化部署、可长期维护的系统管理合同和报销资料,paperless-ngx 是非常值得推荐的选择。

一、项目简介

paperless-ngx 是 paperless 项目的社区延续版本,核心目标是把纸质文件数字化,并让归档、检索、分类和备份变得自动化。它支持:

  • 上传 PDF、图片、Office 转换后的 PDF 等常见文档
  • OCR 识别扫描件内容,支持中文识别配置
  • 全文搜索、标签、通讯方、文档类型、存储路径规则
  • 自动消费目录,把文件放进指定文件夹即可入库
  • 邮件导入,自动归档邮箱里的附件
  • 多用户、权限、组、分享链接和审计需求
  • 自定义字段、工作流、自动匹配规则
  • Docker Compose 部署,适合家庭服务器、NAS、VPS 和公司内网服务器

对合同和报销场景来说,它的价值不是替代财务软件或电子签系统,而是提供一个“可信的原始凭证库”:所有合同、发票、审批单、付款凭证、邮件附件都能被集中保存、快速搜索、按规则归档。

二、主要适用人群

1. 小微企业和初创团队

适合没有完整 OA、ERP 或档案系统,但合同、发票、报销凭证已经开始变多的团队。paperless-ngx 可以先解决“资料集中存放、可查、可备份”的问题。

2. 财务、行政和法务协作团队

适合需要按供应商、客户、项目、年份、合同类型、报销人等维度检索文件的团队。相比网盘目录,paperless-ngx 的全文搜索和元数据管理更适合凭证型资料。

3. 自由职业者和个人工作室

适合管理客户合同、发票、收据、银行回单、税务资料和项目文件。一个人也能用出价值,尤其适合年度报税、客户对账和历史资料复查。

4. 注重数据主权的个人或组织

如果你不希望把合同、身份证件、发票、银行流水等敏感资料上传到第三方 SaaS,paperless-ngx 的自托管模式更合适。

5. 有 NAS 或家庭服务器的用户

群晖、威联通、TrueNAS、Unraid、Linux 小主机、VPS 都可以部署。只要能跑 Docker,就可以低成本搭建。

不太适合的人群:

  • 完全不想维护服务器、备份和升级的人
  • 需要复杂审批流、预算控制、电子发票验真、银企直连的企业
  • 必须满足严格等保、审计、合规认证且没有技术团队支持的组织
  • 希望系统自动完成财务记账和报销审批的人

三、为什么适合合同与报销管理

合同和报销资料有几个共同特点:

  • 文件类型多:PDF、扫描件、照片、邮件附件、付款截图
  • 检索维度多:公司名、金额、日期、项目、经办人、合同编号、发票号码
  • 隐私要求高:包含税号、银行账号、地址、签章、身份证件
  • 保存周期长:合同、发票和报销凭证往往需要保存多年
  • 查找频率不高,但一旦要找就必须马上找到

paperless-ngx 正好匹配这些需求。它不是只按文件夹保存文件,而是把每份文档变成一条可搜索、可分类、可授权、可备份的记录。

推荐的管理思路是:

  • 用“文档类型”区分合同、发票、报销单、付款凭证、审批记录、收据、对账单
  • 用“通讯方”记录客户、供应商、员工、银行、税务机关
  • 用“标签”记录项目、部门、年份、状态和用途
  • 用“自定义字段”记录金额、合同编号、发票号码、报销人、付款日期
  • 用“存储路径规则”自动生成规范目录

这样,即使文件名很乱,也可以通过关键词、日期、供应商、项目或金额快速找回。

四、隐私保护与安全建议

paperless-ngx 最大的隐私优势是自托管。文件、数据库和索引可以保存在你自己的服务器、NAS 或内网环境中,不需要默认交给第三方平台处理。

但自托管不等于天然安全。合同和报销资料通常包含大量敏感信息,部署时应至少做到以下几点。

1. 不要直接裸奔公网

不要把 paperless-ngx 的 Web 端口直接暴露到公网。更稳妥的方式是:

  • 仅内网访问
  • 使用 VPN、Tailscale、WireGuard 或 Zero Trust 隧道访问
  • 如必须公网访问,放在反向代理后面,并启用 HTTPS

2. 设置强密码和双因素认证

管理员账号必须使用强密码。多人使用时不要共享账号,应为每个人创建独立账户,并按角色分配权限。建议启用双因素认证,尤其是可以访问合同和财务凭证的账号。

3. 按角色分权

不要让所有人都拥有管理员权限。可以按以下方式设计:

  • 管理员:系统维护、用户管理、备份恢复
  • 财务:查看和编辑发票、报销单、付款凭证
  • 法务或负责人:查看合同、审批记录
  • 普通员工:只上传自己的报销资料或查看授权文件

4. 加密备份

备份文件往往比生产系统更容易泄露。建议:

  • 数据库、media 目录、consume 目录和 export 目录统一备份
  • 备份文件使用加密压缩或专用备份工具加密
  • 至少保留一份离线备份
  • 定期做恢复演练,而不是只生成备份

5. 谨慎使用邮件导入

邮件导入很方便,但也可能把不该入库的附件自动保存。建议为归档创建专用邮箱,并用邮件规则只转发需要归档的合同、发票和报销资料。

6. 注意 OCR 与全文索引的敏感性

OCR 会把扫描件里的文字提取出来并写入索引。也就是说,即使原文件是图片,身份证号、银行账号、税号、金额等内容也可能被全文搜索到。权限配置必须覆盖文档和索引层面的访问风险。

五、项目优点

1. 私有化能力强

系统可以部署在自己的机器上,文件和数据库由自己掌控,适合管理敏感资料。

2. 搜索体验明显优于网盘目录

OCR 后可以搜索扫描件内容。查合同编号、供应商名称、发票抬头、金额、项目名称时,比手动翻文件夹高效得多。

3. 自动化程度高

消费目录、邮件导入、自动标签、自动匹配通讯方、工作流和存储路径规则,可以减少人工整理成本。

4. 元数据适合档案管理

通讯方、文档类型、标签、归档序列号、自定义字段等能力,比普通文件管理器更适合长期归档。

5. 开源生态成熟

项目活跃,文档完善,Docker 部署路径清晰,社区使用案例多,适合长期使用。

6. 迁移和备份相对友好

可以通过导出工具和数据库备份保存资料,不会完全被某个商业平台锁死。

六、项目缺点

1. 需要基础运维能力

部署、升级、备份、HTTPS、权限和磁盘规划都需要自己负责。对完全没有服务器经验的人,初期有学习成本。

2. 不是完整的报销审批系统

paperless-ngx 适合保存和检索报销凭证,但不负责预算控制、审批流、打款、会计分录和电子发票验真。

3. OCR 准确率受文件质量影响

拍照歪斜、模糊、反光、印章遮挡、低分辨率图片都会影响识别效果。中文 OCR 还需要正确安装和配置语言包。

4. 权限模型需要认真设计

如果团队多人使用,前期必须设计好角色和文档权限,否则容易出现敏感资料被过度共享的问题。

5. 大规模使用要关注性能

大量扫描件、高清图片、复杂 OCR 和全文索引会消耗 CPU、内存和磁盘。几万份以上文档建议使用 PostgreSQL,并给服务器留足资源。

七、部署前准备

下面以 Linux 服务器或 NAS 的 Docker 环境为例。推荐配置:

  • CPU:2 核以上,OCR 多时建议 4 核以上
  • 内存:至少 2 GB,建议 4 GB 以上
  • 磁盘:按原始文件体积规划,建议单独数据盘
  • 系统:Ubuntu、Debian、NAS Docker 环境均可
  • 软件:Docker、Docker Compose
  • 数据库:新部署建议 PostgreSQL
  • 缓存:Redis

目录规划示例:

1
2
3
4
5
6
7
8
9
/opt/paperless
├── docker-compose.yml
├── .env
├── consume
├── data
├── media
├── export
├── db
└── redis

各目录含义:

  • consume:自动导入目录,把文件放进去后系统会自动消费
  • data:paperless-ngx 应用数据
  • media:原始文件、归档文件、缩略图等核心资料
  • export:导出和备份中转目录
  • db:PostgreSQL 数据库数据
  • redis:Redis 数据

八、Docker Compose 实操部署教程

以下命令以 Ubuntu/Debian 为例,其他 Linux 发行版可按实际包管理器调整。

第 1 步:安装 Docker

1
2
3
4
5
6
7
8
9
10
11
12
13
sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker --version
docker compose version

如果你使用 NAS,通常可以直接在套件中心或应用商店安装 Docker/Container Manager。

第 2 步:创建部署目录

1
2
3
sudo mkdir -p /opt/paperless/{consume,data,media,export,db,redis}
sudo chown -R $USER:$USER /opt/paperless
cd /opt/paperless

第 3 步:创建 .env

1
nano .env

写入以下内容,并把密码、密钥、域名改成自己的:

1
2
3
4
5
6
7
8
9
USERMAP_UID=1000
USERMAP_GID=1000
PAPERLESS_TIME_ZONE=Asia/Shanghai
PAPERLESS_OCR_LANGUAGE=chi_sim+eng
PAPERLESS_SECRET_KEY=please-change-this-to-a-long-random-string
PAPERLESS_URL=https://paperless.example.com
POSTGRES_DB=paperless
POSTGRES_USER=paperless
POSTGRES_PASSWORD=please-change-db-password

生成随机密钥可以使用:

1
openssl rand -base64 48

说明:

  • USERMAP_UIDUSERMAP_GID 建议设为运行 Docker 的本机用户 ID
  • PAPERLESS_TIME_ZONE 建议设为 Asia/Shanghai
  • PAPERLESS_OCR_LANGUAGE=chi_sim+eng 表示简体中文加英文 OCR
  • PAPERLESS_SECRET_KEY 必须改成随机长字符串
  • PAPERLESS_URL 如果只在内网使用,可以先写 http://服务器IP:8000

查看当前用户 UID/GID:

1
id

第 4 步:创建 docker-compose.yml

1
nano 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
services:
broker:
image: docker.io/library/redis:7
restart: unless-stopped
volumes:
- ./redis:/data

db:
image: docker.io/library/postgres:16
restart: unless-stopped
volumes:
- ./db:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped
depends_on:
- db
- broker
ports:
- "8000:8000"
volumes:
- ./data:/usr/src/paperless/data
- ./media:/usr/src/paperless/media
- ./export:/usr/src/paperless/export
- ./consume:/usr/src/paperless/consume
env_file: .env
environment:
PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db

生产环境如果追求可控升级,建议把 latest 改成明确版本号,例如 2.x.x。测试确认后再升级,不要无计划自动拉最新镜像。

第 5 步:启动服务

1
2
3
docker compose pull
docker compose up -d
docker compose logs -f webserver

看到服务正常启动后,浏览器访问:

1
http://服务器IP:8000

第 6 步:创建管理员账号

执行:

1
docker compose exec webserver python manage.py createsuperuser

按提示输入用户名、邮箱和密码。

第 7 步:验证 OCR 与导入

把一份合同 PDF 或发票图片放到消费目录:

1
cp /path/to/test.pdf /opt/paperless/consume/

然后查看日志:

1
docker compose logs -f webserver

等待处理完成后,在 Web 页面搜索合同里的公司名、发票抬头或金额。如果能搜到,说明 OCR 和索引正常。

九、HTTPS 与内网访问建议

如果只在公司内网或家庭局域网使用,可以先用 http://服务器IP:8000。如果需要远程访问,推荐三种方式:

方式一:VPN 访问

最推荐。使用 Tailscale、WireGuard 或公司 VPN,把 paperless-ngx 留在内网,不直接暴露公网端口。

方式二:反向代理加 HTTPS

可以使用 Nginx Proxy Manager、Caddy、Traefik 或 Nginx。反向代理负责证书和域名,paperless-ngx 继续监听内网端口。

Caddy 示例:

1
2
3
paperless.example.com {
reverse_proxy 127.0.0.1:8000
}

同时在 .env 中设置:

1
2
PAPERLESS_URL=https://paperless.example.com
PAPERLESS_CSRF_TRUSTED_ORIGINS=https://paperless.example.com

修改后重启:

1
docker compose up -d

方式三:Zero Trust 隧道

适合没有公网 IP 的环境,但要理解访问链路和账号安全策略。合同和财务资料敏感,不建议为了方便牺牲访问控制。

十、初始化配置建议

登录后,不要急着大量上传文件。先把分类体系设计好。

1. 文档类型

建议创建:

  • 合同
  • 发票
  • 报销单
  • 付款凭证
  • 审批记录
  • 收据
  • 对账单
  • 银行回单
  • 税务资料

2. 通讯方

建议按实际往来对象创建:

  • 客户公司
  • 供应商
  • 员工
  • 银行
  • 税务机关
  • 平台服务商

通讯方不建议写得过细。例如“阿里云计算有限公司”比“阿里云 2026 年发票”更适合作为通讯方。

3. 标签

推荐标签结构:

  • 年份:2026
  • 部门:财务行政研发销售
  • 项目:项目A项目B
  • 状态:待付款已付款待报销已报销
  • 敏感级别:敏感仅管理层

标签不要无限增加。优先使用文档类型、通讯方和自定义字段承载结构化信息。

4. 自定义字段

合同和报销场景建议创建:

  • 合同编号
  • 发票号码
  • 金额
  • 币种
  • 报销人
  • 付款日期
  • 所属项目
  • 付款状态
  • 备注

金额字段建议统一格式,例如 1280.00,不要混用 1280¥1280一千二百八十元

5. 存储路径规则

可以设置类似规则:

1
{document_type}/{created_year}/{correspondent}/{title}

合同示例:

1
合同/2026/某某科技有限公司/软件服务合同-2026-001.pdf

报销示例:

1
报销单/2026/张三/差旅报销-上海客户拜访.pdf

这样即使以后离开系统,底层文件也相对清晰。

十一、日常使用教程

1. 上传合同

推荐流程:

  1. 扫描合同为 PDF,分辨率建议 300 DPI
  2. 文件名先简单写清楚,例如 2026-某某公司-采购合同.pdf
  3. 上传到 Web 页面,或放入 consume 目录
  4. 等待 OCR 完成
  5. 设置文档类型为“合同”
  6. 设置通讯方为客户或供应商
  7. 添加项目、年份、状态标签
  8. 填写合同编号、金额、付款状态等自定义字段

2. 上传报销资料

推荐把一笔报销相关资料合并为一个 PDF,或使用同一组标签关联:

  • 报销单
  • 发票
  • 行程单
  • 酒店水单
  • 支付截图
  • 审批截图

命名建议:

1
2026-06-张三-上海差旅报销.pdf

标签建议:

1
2026、张三、差旅、已报销、项目A

自定义字段建议:

1
2
3
4
5
报销人:张三
金额:2860.50
付款日期:2026-06-25
所属项目:项目A
付款状态:已付款

3. 使用消费目录自动导入

如果扫描仪、手机同步工具或 NAS 能把文件保存到指定目录,可以直接保存到:

1
/opt/paperless/consume

paperless-ngx 会自动处理该目录中的文件。适合:

  • 扫描仪自动输出
  • 手机扫描 App 同步
  • 邮件附件下载
  • 批量历史文件导入

注意:不要把正在编辑或尚未传输完成的大文件直接放入消费目录。可以先放到临时目录,确认完整后再移动进去。

4. 使用搜索

常用搜索方式:

  • 搜公司名:查某个客户或供应商的所有文件
  • 搜合同编号:定位具体合同
  • 搜发票号码:定位发票
  • 搜金额:查付款或报销记录
  • 按日期筛选:查某个月或某一年的资料
  • 按标签筛选:查项目、部门或状态

建议把“高频查询”保存为视图,例如:

  • 待付款合同
  • 本月报销
  • 2026 年发票
  • 某项目全部资料
  • 敏感文件

5. 邮件导入

适合处理供应商发票、平台账单和合同邮件附件。

建议流程:

  1. 创建专用邮箱,例如 archive@example.com
  2. 在供应商平台或财务邮箱中设置转发规则
  3. 在 paperless-ngx 中配置邮件账号
  4. 设置只导入带附件邮件
  5. 使用规则自动打标签或指定文档类型

注意不要把整个工作邮箱直接接入,否则私人邮件、无关附件和重复文件都可能进入系统。

十二、备份与恢复

1. 必须备份哪些内容

至少备份:

  • PostgreSQL 数据库
  • media 目录
  • data 目录
  • export 目录
  • docker-compose.yml
  • .env

其中 media 和数据库最关键。只有文件没有数据库,元数据会丢;只有数据库没有 media,原文档会丢。

2. 简单备份命令

创建备份目录:

1
mkdir -p /opt/paperless-backup

导出数据库:

1
2
cd /opt/paperless
docker compose exec -T db pg_dump -U paperless paperless > /opt/paperless-backup/paperless-db.sql

打包文件:

1
2
3
4
5
6
tar -czf /opt/paperless-backup/paperless-files.tar.gz \
/opt/paperless/media \
/opt/paperless/data \
/opt/paperless/export \
/opt/paperless/docker-compose.yml \
/opt/paperless/.env

加密备份示例:

1
2
gpg -c /opt/paperless-backup/paperless-files.tar.gz
gpg -c /opt/paperless-backup/paperless-db.sql

3. 恢复演练

建议每季度至少做一次恢复测试:

  1. 在测试机器上部署同版本 paperless-ngx
  2. 恢复数据库
  3. 恢复 media 和 data 目录
  4. 登录检查文档、缩略图、搜索和下载是否正常

没有恢复验证的备份,只能算“心理安慰”。

十三、升级建议

升级前先做备份,然后再执行:

1
2
3
4
cd /opt/paperless
docker compose pull
docker compose up -d
docker compose logs -f webserver

更稳妥的做法:

  • 不要在工作日高峰升级
  • 先阅读版本发布说明
  • 使用明确版本号,不盲目使用 latest
  • 升级前导出数据库和文件
  • 升级后测试上传、OCR、搜索、下载、权限和邮件导入

如果是公司使用,建议先在测试环境验证。

十四、合同与报销场景最佳实践

1. 先定规则,再导历史文件

不要一上来导入几千份历史文件。先用 20 到 50 份真实文件测试分类体系,确认文档类型、标签、自定义字段和存储路径都合理,再批量导入。

2. 文件标题要可读

推荐标题格式:

1
年份-对象-事项-编号

示例:

1
2
3
2026-某某科技-软件采购合同-HT202606001
2026-张三-上海差旅报销-BX202606018
2026-阿里云-云服务器发票-FP12345678

3. 标签不要替代所有字段

标签适合表达状态、项目、部门、敏感级别;金额、编号、付款日期这类信息更适合自定义字段。

4. 扫描质量优先

建议:

  • 300 DPI
  • 黑白文字用灰度或黑白模式
  • 保持页面平整
  • 避免阴影、反光和裁切
  • 多页合同保存为单个 PDF

5. 建立敏感资料规则

身份证、银行卡、劳动合同、薪酬资料、股权协议等文件,应单独标签和授权,不要默认全员可见。

6. 保留原件策略

paperless-ngx 可以减少纸质文件查找成本,但是否销毁纸质原件要看当地法律、税务要求、公司制度和合同性质。重要合同、票据、印章页和法律文件建议保留纸质原件。

7. 定期清理待处理队列

每周检查:

  • 是否有 OCR 失败文件
  • 是否有未分类文档
  • 是否有重复上传
  • 是否有错误通讯方
  • 是否有权限设置不当的敏感文件

十五、常见问题

1. 中文 OCR 不生效怎么办?

检查 .env 中是否设置:

1
PAPERLESS_OCR_LANGUAGE=chi_sim+eng

然后确认镜像中具备对应 OCR 语言数据。修改配置后重启服务:

1
docker compose up -d

如果旧文档已经入库,需要重新处理或重新上传才能得到新的 OCR 结果。

2. 上传后搜索不到内容怎么办?

排查顺序:

  1. 查看 Web 页面中文档是否处理完成
  2. 查看日志是否有 OCR 错误
  3. 确认文件不是加密 PDF
  4. 确认扫描件清晰度足够
  5. 等待索引完成后再搜索

日志命令:

1
docker compose logs -f webserver

3. 文件很多会不会很慢?

几千到几万份文档通常可以正常使用,但要关注:

  • PostgreSQL 而不是 SQLite
  • 服务器 CPU 和内存
  • OCR 队列压力
  • 磁盘 IO
  • 备份耗时
  • 缩略图和全文索引体积

如果历史文件很多,建议分批导入。

4. 能不能替代企业网盘?

不完全替代。paperless-ngx 更适合“归档后的凭证和文档”,不适合作为多人协作编辑文件的网盘。合同定稿、发票、扫描件、审批记录适合放进来;正在协作编辑的 Word、Excel 不适合直接作为主要工作流。

5. 能不能替代报销系统?

不能完整替代。它能保存和检索报销资料,但审批、预算、付款、记账、发票验真仍需要财务系统或人工流程。

十六、推荐部署方案

个人或家庭工作室

  • NAS 或小主机
  • Docker Compose
  • 仅内网或 Tailscale 访问
  • 每周自动备份到移动硬盘或对象存储

小团队

  • 独立 Linux 服务器
  • PostgreSQL + Redis
  • 反向代理 + HTTPS
  • 按角色设置用户权限
  • 每日数据库备份,每周完整备份

对隐私要求高的组织

  • 仅内网访问
  • VPN 或堡垒机
  • 禁止公网暴露
  • 加密备份
  • 管理员最小化
  • 定期权限审计
  • 制定纸质原件保留制度

十七、结论

paperless-ngx 最适合做“私有化文档档案库”,尤其适合合同、发票、报销凭证、付款记录和长期留存资料。它的优势在于开源、自托管、OCR、全文搜索、自动归档和元数据管理;短板是需要自己维护服务器,也不能替代完整的财务审批系统。

如果你的痛点是“合同和报销资料散落在微信、邮箱、网盘、电脑文件夹里,关键时刻找不到”,paperless-ngx 非常值得部署。建议先从小范围试点开始:选一个部门、一个项目或最近一年的资料,建立分类规则,跑通上传、搜索、权限和备份,再逐步扩大使用范围。

真正好用的文档管理,不是把所有文件都扔进系统,而是让每份重要文件在未来任何一天都能被准确找回、被正确授权、被可靠备份。paperless-ngx 正好可以承担这个角色。

参考资料