在线合并 PDF、压缩文件或者给合同打码,最让人不放心的往往不是工具好不好用,而是文件到底传去了哪里。身份证、合同、报价单这类资料,我不建议随手扔进来路不明的在线 PDF 网站。
Stirling PDF 可以把常用 PDF 工具放到自己的 VPS:合并、拆分、压缩、格式转换、OCR、加水印、删除元数据都在浏览器里完成。文件处理发生在自己的服务器上,入口、账号和备份也由自己控制。
这篇教程使用 Docker Compose 部署标准镜像,Caddy 负责 HTTPS。后端 8080 端口只监听 127.0.0.1,不会直接暴露到公网;同时开启登录、中文界面、健康检查和持久化目录。
Stirling PDF 很适合下面几种情况:
- 经常处理合同、扫描件,不想上传到第三方网站;
- 小团队需要一个共用的 PDF 工具箱;
- 想通过 API 批量合并、OCR 或转换 PDF;
- 已有一台 VPS,希望把闲置资源利用起来。
它也有明显限制。OCR、Office 转 PDF 和大文件压缩都可能瞬间吃掉不少 CPU 与内存;服务器管理员仍然可以接触宿主机,所以“自托管”不等于“任何人都看不到文件”。如果只是偶尔处理一份不敏感的 PDF,桌面软件反而省事。
个人使用可以从 2 核、2GB 内存、20GB SSD 起步。需要中文 OCR、Office 文档转换,或者几个人同时使用时,建议至少 2 核、4GB 内存、40GB SSD。
| 使用场景 | 建议配置 | 镜像选择 |
|---|---|---|
| 合并、拆分、旋转 PDF | 2 核 2GB | latest |
| OCR、Office 转换、日常团队使用 | 2-4 核 4GB | latest |
| 需要额外字体和更完整转换能力 | 4 核 8GB | latest-fat |
| 低配机器,只用基础功能 | 1-2 核 1-2GB | latest-ultra-lite |
标准镜像对大多数人够用。latest-fat 体积更大,但额外字体和工具更齐;latest-ultra-lite 省磁盘,却不适合依赖登录与完整 OCR 的公网部署。
系统以 Ubuntu 24.04 LTS 为例。准备一个已经解析到 VPS 公网 IP 的域名,例如 pdf.example.com,安全组和 UFW 只开放 SSH、80、443。
如果服务器还没装 Docker,使用 Docker 官方仓库安装。装完先确认两个命令都有输出:
docker --version
docker compose version
不要继续使用已经停止维护的 docker-compose v1。后面的命令都使用 Compose v2,也就是中间带空格的 docker compose。
创建部署目录:
sudo mkdir -p /opt/stirling-pdf/data/{configs,customFiles,logs,pipeline,tessdata}
sudo chown -R "$USER":"$USER" /opt/stirling-pdf
cd /opt/stirling-pdf
不要把示例密码直接放到公网。先生成一串随机密码,再写进权限为 600 的 .env:
openssl rand -base64 24
nano .env
chmod 600 .env
.env 内容如下,把第二行替换成刚才生成的值:
STIRLING_ADMIN_USER=admin
STIRLING_ADMIN_PASSWORD=请替换成随机密码
环境变量仍然能被有 Docker 管理权限的人查看,因此 Docker 管理权限本身就应该只给可信管理员。首次登录后,再在 Stirling PDF 的账号设置里修改密码。
创建 /opt/stirling-pdf/compose.yaml:
services:
stirling-pdf:
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
container_name: stirling-pdf
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
volumes:
- ./data/configs:/configs
- ./data/customFiles:/customFiles:rw
- ./data/logs:/logs
- ./data/pipeline:/pipeline
- ./data/tessdata:/usr/share/tessdata
environment:
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
SECURITY_INITIALLOGIN_USERNAME: "${STIRLING_ADMIN_USER:?set STIRLING_ADMIN_USER in .env}"
SECURITY_INITIALLOGIN_PASSWORD: "${STIRLING_ADMIN_PASSWORD:?set STIRLING_ADMIN_PASSWORD in .env}"
SYSTEM_DEFAULTLOCALE: "zh-CN"
SYSTEM_GOOGLEVISIBILITY: "false"
SHOW_SURVEY: "false"
healthcheck:
test:
- CMD-SHELL
- >-
curl -fsS http://localhost:8080/api/v1/info/status |
grep -q 'UP'
interval: 30s
timeout: 10s
retries: 10
start_period: 60s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
cpus: "2.0"
memory: 4G
先让 Compose 展开环境变量并检查语法,再启动:
docker compose config >/dev/null
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 stirling-pdf
官方只为最新版本提供安全支持,因此示例使用 latest。这不代表应该每天盲目更新。首次跑通后记录当前镜像摘要,升级前备份 /configs,再执行 pull 和重建:
docker image inspect \
docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest \
--format '{{index .RepoDigests 0}}'
如果官方镜像站拉取失败,可以改用 Docker Hub 的 stirlingtools/stirling-pdf:latest,或 GitHub Container Registry 的 ghcr.io/stirling-tools/stirling-pdf:latest。
Stirling PDF 会接收合同、证件和其他敏感文件,不要用明文 HTTP 登录。安装 Caddy 后编辑 /etc/caddy/Caddyfile:
pdf.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:8080
request_body {
max_size 200MB
}
}
检查配置并重载:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo systemctl status caddy --no-pager
如果你还没配过 Caddy,可以先看VPS 用 Caddy 反向代理完全指南。
确认后端没有对公网监听:
sudo ss -lntp | grep ':8080'
curl -fsS http://127.0.0.1:8080/api/v1/info/status
curl -I https://pdf.example.com
第一条应该看到 127.0.0.1:8080,不能是 0.0.0.0:8080;健康接口会返回包含 UP 的 JSON。随后打开 https://pdf.example.com,用 .env 里的管理员账号登录并立刻修改密码。
Stirling PDF 的 OCR 使用 Tesseract。标准 Docker 镜像通常包含简体中文等常用语言包;实际可用语言仍要以当前容器里的文件为准:
docker exec stirling-pdf sh -lc \
'find /usr/share/tessdata -maxdepth 1 -name "*.traineddata" -printf "%f\n" | sort'
中文简体对应 chi_sim.traineddata,繁体对应 chi_tra.traineddata,英文对应 eng.traineddata。界面里看不到某种语言时,不要只改下拉框;先确认对应语言包是否真的存在。
OCR 的效果还取决于原文件。300 DPI、文字清楚、页面方向正确的扫描件,通常比手机随手拍、阴影明显、字号小于 8pt 的图片好很多。Tesseract 能识别文字,但不会可靠还原复杂表格结构和公式。
处理一份测试扫描件后,至少确认三件事:能搜索中文、能复制文字、下载后的 PDF 能在常用阅读器打开。只看到任务完成提示,不代表识别结果真的可用。
最危险的配置是关闭登录后把 8080 直接开放公网。别人不但能消耗你的 CPU 和内存,还可能上传恶意构造的文件试探转换组件。
上线前逐项检查:
SECURITY_ENABLELOGIN=true,管理员密码已经更换;- 8080 只绑定
127.0.0.1,公网只开放 80/443; /configs已持久化,.env权限为600;- 不需要的用户、API Key 和功能及时关闭;
- 定期拉取安全更新,但每次更新前先备份;
- 服务器磁盘设置告警,避免临时文件或日志把磁盘写满。
Stirling PDF 的安全页面明确说明旧版本不会回补安全修复。公网实例不要多年不升级,也不要把“容器能启动”当成安全维护已经完成。
免费版登录用户、本地设置和内置 H2 数据库主要保存在 /configs。最省心的做法是备份整个 data 目录,而不是只复制 compose.yaml。
先停容器,做一份一致性更好的压缩包:
cd /opt/stirling-pdf
mkdir -p backups
docker compose stop stirling-pdf
tar -czf "backups/stirling-data-$(date +%F-%H%M%S).tar.gz" data
docker compose start stirling-pdf
本机压缩包不算完整备份。再用 restic、rclone 或对象存储把它复制到另一台机器,并设置保留周期。具体可以照着VPS 备份恢复演练指南做一次异机恢复。
恢复时不要直接覆盖正在使用的数据库文件:
cd /opt/stirling-pdf
docker compose stop stirling-pdf
mv data "data.before-restore-$(date +%F-%H%M%S)"
tar -xzf backups/stirling-data-YYYY-MM-DD-HHMMSS.tar.gz
docker compose up -d
curl -fsS http://127.0.0.1:8080/api/v1/info/status
恢复后要实际登录,确认账号、设置和 OCR 语言仍在。备份文件存在但从没恢复过,只能算“有压缩包”,不能算“有恢复能力”。
先看退出原因和最近日志:
docker inspect stirling-pdf --format '{{.State.ExitCode}} {{.State.OOMKilled}}'
docker compose logs --tail=200 stirling-pdf
free -h
df -h
OOMKilled=true 通常是内存不足,尤其容易出现在 OCR 或 Office 转换时。先降低并发、换标准或 ultra-lite 镜像;仍然频繁 OOM,就应该加内存,而不是无限加 Swap。
先分清限制在哪一层:Caddy 的 request_body max_size、Stirling PDF 自己的上传限制,以及前面是否还有 Cloudflare。三层任意一层更小,都会返回 413。改完配置后重新验证,不要一口气把限制放到无限大。
检查 /configs 是否真的挂载:
docker inspect stirling-pdf \
--format '{{range .Mounts}}{{println .Destination .Source}}{{end}}'
ls -lah /opt/stirling-pdf/data/configs
如果 /configs 没有映射到宿主机,删容器时账号和设置也会一起消失。
先确认选的是 chi_sim,再检查扫描分辨率、页面方向和对比度。对已经有文本层的 PDF 使用自动模式即可,强制重新 OCR 反而可能让原本清楚的文字变差。
部署完成后,我会按下面这套标准验收,而不是只看首页能不能打开:
docker compose ps显示容器为 healthy;- 8080 只监听回环地址,公网无法直接访问;
- HTTPS 证书有效,HTTP 自动跳转 HTTPS;
- 未登录用户不能使用 PDF 工具;
- 合并、压缩、中文 OCR 各跑一份测试文件;
- 重启容器后账号和设置仍然存在;
- 从备份恢复到测试目录,能重新登录并处理文件。
如果你准备长期给团队使用,再把容器日志轮转、磁盘告警和升级窗口补上。生产 Compose 的健康检查、资源限制和回滚思路,可以继续看VPS Docker Compose 生产配置清单。
Stirling PDF 的价值不只是“免费 PDF 工具很多”,而是敏感文件不必经过陌生网站。用 2 核 4GB VPS、Docker Compose、Caddy HTTPS 和强制登录搭好后,再做一轮 OCR、重启和恢复测试,这套服务才算真正可用。
