Documenso 常用命令与运维实战

Documenso v2.21.1 运维命令与 REST API v2 全流程实测:健康检查与迁移命令、API Token 创建、创建文档/添加收件人/放置字段/分发/签署/完结逐条 curl 实测回显、签署件三件套下载、pg_dump 备份恢复与排障排查路径。

Documenso电子签名PDF 处理Nodejs2026/10/28

Documenso 常用命令与运维实战

部署完成后的 Documenso(v2.21.1)日常运维由三类操作构成:服务与数据库的容器命令(迁移、备份、健康检查)、面向集成的 REST API v2(信封/收件人/字段的完整生命周期)、以及排查问题的日志与数据库直查。本文全部命令在一台 v2.21.1 实测实例上真实执行,输出为逐行照抄的实测回显;部署背景与排障实录见《Documenso Docker Compose 部署实战》,环境变量含义见《Documenso 配置参数详解》。

一、服务状态与健康检查

1.1 服务与端口确认

docker compose ps --format 'table {{.Name}}\t{{.Status}}\t{{.Ports}}'

实测回显:

NAME                        STATUS                    PORTS
documenso-v2.21.1-db        Up 26 minutes (healthy)   5432/tcp
documenso-v2.21.1-mailpit   Up 26 minutes (healthy)   1025/tcp, 1110/tcp, 0.0.0.0:8133->8025/tcp, [::]:8133->8025/tcp
documenso-v2.21.1-web       Up 10 minutes             0.0.0.0:8130->3000/tcp, [::]:8130->3000/tcp

1.2 两个免认证健康端点

curl -s http://localhost:8130/api/health
curl -s http://localhost:8130/api/certificate-status

实测回显:

{"status":"ok","timestamp":"2026-10-28T06:40:42.132Z","checks":{"database":{"status":"ok"},"certificate":{"status":"ok"}}}
{"isAvailable":true,"timestamp":"2026-10-28T06:40:42.165Z"}

/api/health 同时探测数据库连通性与签署证书可读性,/api/certificate-status 单独报告证书可用性。监控探针建议打这两个端点而不是首页。

二、数据库迁移命令

v2.21.1 镜像的启动脚本(start.sh)在每次容器启动时自动执行迁移:

🗄️  Running database migrations...
166 migrations found in prisma/migrations
No pending migrations to apply.

需要手动执行时,注意镜像内工作目录是 /app/apps/remix,根 package.json 的 prisma:migrate-deploy 脚本指向 monorepo workspace(实测直接调用报 Missing script: "prisma:migrate-deploy"),正确姿势是显式指定 schema 路径:

docker exec -w /app/apps/remix documenso-v2.21.1-web \
  npx prisma migrate deploy --schema ../../packages/prisma/schema.prisma

实测回显:

No pending migrations to apply.

该命令幂等,可在升级前后反复执行核对。升级流程(改镜像版本 → docker compose up -d → 迁移自动应用)见 B2 篇第六节。

三、REST API v2 全流程实测

3.1 创建 API Token

v2 API 用 Bearer Token 认证。Token 在网页端「设置 → API Tokens」创建,也可通过应用的内部 tRPC 过程脚本化创建(需已登录会话):

curl -s -b jar.txt -X POST "http://localhost:8130/api/trpc/apiToken.create?batch=1" \
  -H "Origin: http://localhost:8130" -H "Content-Type: application/json" \
  -d '{"0":{"json":{"tokenName":"ops-token","teamId":3,"expirationDate":null}}}'

实测回显(响应只回 id 与 token,Token 明文仅出现这一次,务必留存;重复执行会生成多个同名 Token):

{"result":{"data":{"json":{"id":2,"token":"api_2bzzf0uucrga8llu"}}}}

踩坑提示:expirationDate 字段必须显式传(可为 null),省略会报 Zod 校验错误 Required。下文所有 curl 均以 api_xk0pdedpjkjq39in 为实测 Token。

3.2 创建文档(信封 + PDF 上传)

v2 API 中文档统一为 envelope 模型。创建是 multipart 请求,JSON 元数据放 payload,PDF 放 files:

curl -s -X POST http://localhost:8130/api/v2/envelope/create \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" \
  -F 'payload={"title":"运维实测-服务合同","type":"DOCUMENT"};type=application/json' \
  -F 'files=@test-contract.pdf;type=application/pdf'

实测回显:

{"id":"envelope_ntdhuchwxyaicakh"}

踩坑提示:文件字段名是 files(复数)。误用 file 时创建返回 200 且正常给出 id,但后续取 envelopeItems 为空数组、放置字段报 Envelope item not found——这是最容易踩的静默坑。

创建后取信封详情确认 PDF 项已挂载:

curl -s http://localhost:8130/api/v2/envelope/envelope_ntdhuchwxyaicakh \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in"

实测回显(节选):

"envelopeItems": [{"envelopeId": "envelope_ntdhuchwxyaicakh", "documentDataId": "cmvrqo80g0007lh247ic92hc8",
  "id": "envelope_item_fzlekendwtmafbao", "title": "test-contract.pdf", "order": 1}]
"status": "DRAFT"

3.3 添加收件人

curl -s -X POST http://localhost:8130/api/v2/envelope/recipient/create-many \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" -H "Content-Type: application/json" \
  -d '{"envelopeId":"envelope_ntdhuchwxyaicakh","data":[{"email":"signer@documenso.local","name":"签署人小王","role":"SIGNER","signingOrder":1}]}'

实测回显:

{"data":[{"envelopeId":"envelope_ntdhuchwxyaicakh","role":"SIGNER","readStatus":"NOT_OPENED",
"signingStatus":"NOT_SIGNED","sendStatus":"NOT_SENT","id":3,"email":"signer@documenso.local",
"name":"签署人小王","token":"vpiHe34_DquOGC51CKlkl",...,"signingOrder":1,"rejectionReason":null}]}

要点:响应直接返回收件人 id(3)与签署 token(vpiHe34_DquOGC51CKlkl),后续签署与回执都要用;role 可选 CC/SIGNER/VIEWER/APPROVER/ASSISTANT。

3.4 放置签署字段

curl -s -X POST http://localhost:8130/api/v2/envelope/field/create-many \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" -H "Content-Type: application/json" \
  -d '{"envelopeId":"envelope_ntdhuchwxyaicakh","data":[{"recipientId":3,"type":"SIGNATURE","page":1,"positionX":35,"positionY":20,"width":25,"height":8,"envelopeItemId":"envelope_item_fzlekendwtmafbao"}]}'

实测回显:

{"data":[{"envelopeId":"envelope_ntdhuchwxyaicakh","envelopeItemId":"envelope_item_fzlekendwtmafbao",
"type":"SIGNATURE","id":2,"recipientId":3,"page":1,"positionX":"35","positionY":"20","width":"25",
"height":"8","customText":"","inserted":false,"fieldMeta":{"fontSize":18,"overflow":"auto","type":"signature"},...}]}

两个踩坑提示:坐标定位键是 page(不是 pageNumber,传错报 Zod union 校验失败);envelopeItemId 必须带(不传报 Envelope item not found)。坐标与宽高为页面百分比。

3.5 分发签署

curl -s -X POST http://localhost:8130/api/v2/envelope/distribute \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" -H "Content-Type: application/json" \
  -d '{"envelopeId":"envelope_ntdhuchwxyaicakh","meta":{"subject":"请签署:运维实测-服务合同","distributionMethod":"EMAIL"}}'

实测回显:

{"success":true,"id":"envelope_ntdhuchwxyaicakh","recipients":[{"id":3,"name":"签署人小王",
"email":"signer@documenso.local","token":"vpiHe34_DquOGC51CKlkl","role":"SIGNER","signingOrder":1,
"signingUrl":"http://localhost:8130/sign/vpiHe34_DquOGC51CKlkl"}]}

响应自带直签 signingUrl(无需等邮件)。同时签署请求邮件已投递到 Mailpit(实测回显):

3VIvrvpR17doPMXg84XXvR | 请签署:运维实测-服务合同 | to: signer@documenso.local

3.6 收件人签署与文档完结

签署动作走应用内部 tRPC 过程(带收件人 token,无需管理员权限),字段签署使用类型化签名(value 传纯文本即 typed signature):

curl -s -X POST "http://localhost:8130/api/trpc/envelope.field.sign?batch=1" \
  -H "Origin: http://localhost:8130" -H "Content-Type: application/json" \
  -d '{"0":{"json":{"token":"vpiHe34_DquOGC51CKlkl","envelopeId":"envelope_ntdhuchwxyaicakh","fieldId":2,"fieldValue":{"type":"SIGNATURE","value":"王小签"}}}}'

实测回显(节选):

{"result":{"data":{"json":{"signedField":{...,"inserted":true,"fieldMeta":{"fontSize":18,...},"signature":{"id":...

全部收件人签完后调用完结,由后台任务 internal.seal-document 用 .p12 证书封存 PDF:

curl -s -X POST "http://localhost:8130/api/trpc/recipient.completeDocumentWithToken?batch=1" \
  -H "Origin: http://localhost:8130" -H "Content-Type: application/json" \
  -d '{"0":{"json":{"token":"vpiHe34_DquOGC51CKlkl","documentId":3}}}'

实测回显:

{"json": {"status": "SIGNED"}}

踩坑提示:documentId 是数字(信封 secondaryId document_3 的序号),传 envelope id 字符串报 Expected number, received string。

约 10 秒后核对终态:

curl -s http://localhost:8130/api/v2/envelope/envelope_ntdhuchwxyaicakh \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" | grep -oE '"status":"[A-Z]+"|"completedAt":"[^"]+"'

实测回显:

"status":"COMPLETED"
"completedAt":"2026-10-28T06:38:35.110Z"

3.7 签署回执与三件套下载

签署完成后,签署人与管理员各收一封完成回执(Mailpit 实测):

41xNvG528YBm3i4RrceYtq | Signing Complete! | to: signer@documenso.local
3VgAovE8TRRLVFlysv3DvF | Signing Complete! | to: admin@documenso.local

经 API 下载签署件、审计日志、签署证书三件套:

curl -s "http://localhost:8130/api/v2/document/3/download" \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" -o signed.pdf
curl -s "http://localhost:8130/api/v2/envelope/envelope_ntdhuchwxyaicakh/audit-log/download" \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" -o audit.pdf
curl -s "http://localhost:8130/api/v2/envelope/envelope_ntdhuchwxyaicakh/certificate/download" \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in" -o signing-cert.pdf

实测回显(三件均为有效 PDF;签署件含数字签名结构 /ByteRange,即真实 PKCS#7/CAdES 封签而非贴图):

audit HTTP 200 bytes 384622
cert  HTTP 200 bytes 188000
signed HTTP 200 bytes 214229

3.8 列表查询与状态巡检

curl -s "http://localhost:8130/api/v2/envelope?page=1&perPage=10" \
  -H "Authorization: Bearer api_xk0pdedpjkjq39in"

实测回显:

total: None | count: 3
envelope_ntdhuchwxyaicakh | COMPLETED | 运维实测-服务合同 | 2026-10-28T06:38:35.110Z
envelope_ztsnuznecwvuninx | PENDING | E2E 测试合同 | -
envelope_ohshoktubcrcyswe | DRAFT | E2E 测试合同 | -

注意列表端点是单数 /envelope(/envelopes 返回 404)。DRAFT/PENDING/COMPLETED 三态分别对应未分发、签署中、已完成。

四、备份与恢复命令

4.1 卷盘点

NEXT_PUBLIC_UPLOAD_TRANSPORT=database 时全部业务数据都在单一数据卷:

docker volume ls --format '{{.Name}}' | grep documenso

实测回显:

documenso-v2211-stack_database

除卷之外,certs/cert.p12 签署证书与 compose 文件里的三把密钥是数据之外的必要备份物。

4.2 逻辑备份(pg_dump 自定义格式)

docker exec documenso-v2.21.1-db pg_dump -U documenso -d documenso --no-owner -Fc -f /tmp/documenso-backup.dump
docker cp documenso-v2.21.1-db:/tmp/documenso-backup.dump ./documenso-backup.dump

实测回显(294 KB,实测库 54 张表共 12 MB):

-rw-r--r-- 1 root root 294706 Oct 28 14:39 documenso-backup.dump

校验备份可读(列内容表数量):

docker exec documenso-v2.21.1-db pg_restore --list /tmp/backup-test.dump | grep -c "TABLE DATA"

实测回显:

54

4.3 纯 SQL 导出与恢复演练

可读性更好的纯 SQL(仅结构示例):

docker exec documenso-v2.21.1-db pg_dump -U documenso -d documenso --no-owner | head -3

实测回显:

--
-- PostgreSQL database dump
--

恢复到既有库(演练时建议起一个全新数据库验证):

docker cp ./documenso-backup.dump documenso-v2.21.1-db:/tmp/restore.dump
docker exec documenso-v2.21.1-db pg_restore -U documenso -d documenso --clean --if-exists /tmp/restore.dump

恢复后重启应用容器并复查 /api/health 双 ok。

五、排障排查路径

实测沉淀的排查顺序(按命中率排序):

  1. /api/health 双 ok? certificate 非 ok 直奔证书权限(B2 篇坑一)。
  2. 应用日志:docker compose logs documenso | grep -E 'JOBS|Error|failed'。封存/邮件任务失败都在这里,实测中的 EACCES: permission denied、Task exceeded retries 即由此发现。
  3. 邮件链路:Mailpit 收件箱(http://宿主机:8133)是否收到对应邮件。验证邮件不到 = SMTP 配置问题;签署邀请不到 = 分发未完成或 SMTP 问题。
  4. 数据库直查:状态机不动时查权威状态:
docker exec documenso-v2.21.1-db psql -U documenso -d documenso \
  -tAc "SELECT id, status, \"completedAt\" FROM \"Envelope\" WHERE id = 'envelope_ntdhuchwxyaicakh';"

实测回显:

envelope_ntdhuchwxyaicakh|COMPLETED|2026-10-28 06:38:35.11
  1. 任务卡死:internal.seal-document 重试耗尽后不会自愈,修复根因后对同一文档重新走一遍签署/完结流程(实测中 PENDING 文档修复证书权限后仍需重签)。

六、命令速查表

场景命令
健康检查curl -s http://localhost:8130/api/health
证书状态curl -s http://localhost:8130/api/certificate-status
手动迁移docker exec -w /app/apps/remix <web 容器> npx prisma migrate deploy --schema ../../packages/prisma/schema.prisma
数据库备份docker exec <db 容器> pg_dump -U documenso -d documenso --no-owner -Fc -f /tmp/b.dump
备份拷出docker cp <db 容器>:/tmp/b.dump ./b.dump
恢复pg_restore -U documenso -d documenso --clean --if-exists
信封列表GET /api/v2/envelope?page=1&perPage=10(Bearer Token)
下载签署件GET /api/v2/document/<documentId>/download
下载审计日志GET /api/v2/envelope/<id>/audit-log/download
下载签署证书GET /api/v2/envelope/<id>/certificate/download

相关文档