Stirling-PDF 深度導讀

把一支 GitHub 上 79K stars 的開源專案,從定位到資安一次講完。 適合:想為團隊 / 客戶導入 self-hosted PDF 處理平台的工程師、IT 與資安人員。


1. 專案定位

Stirling-PDF 在 PDF 工具光譜上的座標:

構面Stirling-PDFAdobe Acrobatpdftk / qpdfpdf.js / PSPDFKit
部署self-hosted(Docker / Desktop / K8s)桌面 + 雲(Adobe 控制)CLI onlySDK / SaaS
介面瀏覽器 UI + Desktop + REST API + Pipeline桌面 GUISDK / library
工具數50+(合併 / 拆分 / OCR / 簽署 / redact / 轉檔)100+~10視 SDK
隱私完全本地(檔案不出機器)雲傳輸本地視部署
授權open-core(免費核心 + 付費 Enterprise)商用開源商用
語系40+ 語系主流幾種N/AN/A
適用場景內部 PDF 平台 / API 整合 / 法務 / 醫療個人 / SMB開發者腳本App 內 PDF

一句話:當你需要一個「能放進公司 DMZ、不會把客戶 PDF 送到 Adobe 雲、又有 Acrobat 級工具數量」的 PDF 平台時,Stirling-PDF 是現階段最成熟的開源選項。


2. 安裝指南

2.1 最快路徑:Docker 一行(5 分鐘)

1docker run -p 8080:8080 docker.stirlingpdf.com/stirlingtools/stirling-pdf

開瀏覽器到 http://localhost:8080 即可使用。

2.2 三種 image 變體

Tag大小含 LibreOffice / OCR適用
:latest~1.5 GB一般推薦
:latest-ultra-lite~400 MB純 PDF 操作、資源受限
:latest-fat~3 GB✅ + 預載字型 / lib冷啟動敏感、企業

2.3 docker-compose(建議:unified-both + 持久化 volume)

 1services:
 2  stirling-pdf:
 3    image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
 4    container_name: stirling-pdf
 5    ports:
 6      - "8080:8080"
 7    volumes:
 8      - ./stirling-data/configs:/configs
 9      - ./stirling-data/logs:/logs
10      - ./stirling-data/tessdata:/usr/share/tessdata
11      - ./stirling-data/pipeline:/pipeline
12    environment:
13      LANGS: en_GB,zh_TW
14      SECURITY_ENABLELOGIN: "true"
15      SECURITY_JWT_PERSISTENCE: "true"
16      SECURITY_JWT_ENABLEKEYROTATION: "true"
17      SYSTEM_MAXFILESIZE: "100"
18    deploy:
19      resources:
20        limits:
21          cpus: "1.0"
22          memory: 2048M
23    restart: unless-stopped

啟動:docker compose up -d

2.4 Desktop client(Tauri)

Releases 下載對應平台:

  • .dmg(macOS,v2.10.1 起為 unified installer)
  • .exe(Windows)
  • .AppImage / .rpm / .deb(Linux,v2.10.0 起新增)

桌面版內嵌 JRE + backend,雙擊即用、不需 Docker。

2.5 開發環境(Task + Gradle)

1# 一次安裝所有開發依賴
2task install
3
4# 啟動本地開發
5task dev
6
7# 跑測試套件
8task test

詳細見 DeveloperGuide.md


3. 核心架構解析

Stirling-PDF 是典型的「前後端分離 + 外部 binary 編排」架構:


flowchart TD
    User[使用者瀏覽器 / Desktop / curl]
    Frontend[Frontend SPA
React + Svelte + Tauri
frontend/editor] API[Spring Boot REST API
app/core ~50 controllers] PDFBox[Apache PDFBox
核心 PDF 解析] Engine[Python engine
engine/ 輔助處理] LibreOffice[LibreOffice
Office → PDF] Tesseract[Tesseract OCR
掃描檔文字識別] QPDF[qpdf / unoserver
底層操作] User --> Frontend User --> API Frontend --> API API --> PDFBox API --> Engine API --> LibreOffice API --> Tesseract API --> QPDF

關鍵設計:

  1. 多模組 Gradle 專案settings.gradle):

    • app/common — 共用 model / utility
    • app/core — 50+ controller + service(自由 open-source 核心)
    • app/proprietary — 付費功能(SSO、audit、enterprise)
    • app/saas — SaaS 模式(Supabase 整合)
    • engine/ — Python 輔助 engine(與 Java backend 透過 subprocess / HTTP 互通)
  2. Controller 群組app/core/src/main/java/.../controller/api/):

    • 基本操作:MergeController / SplitPDFController / RotationController / CropController / RearrangePagesPDFController / ScalePagesController
    • 進階:EditTableOfContentsController / EditTextController / BookletImpositionController / PdfOverlayController / PosterPdfController
    • 子資料夾:converters/ / filters/ / form/ / security/ / misc/ / pipeline/
  3. 外部 binary probeExternalAppDepConfig):用 ProcessBuilder + timeout 在啟動時探測 LibreOffice / unoserver / qpdf 等是否可用,可用就啟用對應 controller,不可用就 disable,這是「同一 image 支援 ultra-lite / standard / fat」的核心機制。

  4. 資料持久化

    • 預設用 H2 嵌入式 DB(檔案存 /configs/stirling-pdf-DB-*.mv.db
    • 可切換成 PostgreSQL(見 DATABASE.md 與官方 External Database 文件)
    • ⚠️ H2 不支援多容器共用(已知問題 #6395),如需橫向擴展,請改用 PostgreSQL

安裝流程圖


flowchart LR
    A[選擇部署模式] --> B{需求}
    B -->|快速試用| C[docker run
單行命令] B -->|生產內部用| D[docker-compose
+ volume 持久化] B -->|個人桌面| E[下載 Tauri
installer] B -->|企業| F[K8s + PostgreSQL
+ SSO] C --> G[localhost:8080] D --> G E --> H[本機 file://] F --> I[內部域名]

4. Docker compose 與部署選項

docker/compose/ 提供 6 種範本,依用途選擇:

檔案用途
docker-compose.yml最簡單(demo 站使用)
docker-compose.fat.ymlfat image,預載字型
docker-compose.ultra-lite.yml最小化(不含 LibreOffice / OCR)
docker-compose-unified-both.yml推薦:單容器同時跑 backend + frontend
docker-compose-unified-backend.yml只跑 backend(適合 API-only 整合)
docker-compose-unified-frontend.yml只跑 frontend(接外部 backend)

docker/embedded/compose/ 另有 6 個更貼近真實場景的範本:

  • docker-compose-latest-security.yml — 啟用登入 / 權限
  • docker-compose-latest-fat-security.yml — fat + 登入
  • docker-compose-latest-security-remote-uno.yml — 把 unoserver 拆到獨立容器
  • docker-compose-latest-fat-endpoints-disabled.yml — 部分 endpoint 停用(縮小攻擊面)

重要環境變數:

變數預設說明
SECURITY_ENABLELOGINfalse啟用登入(生產環境必開)
SYSTEM_DEFAULTLOCALEen-US預設語系
SYSTEM_MAXFILESIZE100上傳 PDF 上限(MB)
LANGS全部啟用的語系(如 en_GB,zh_TW
SECURITY_JWT_PERSISTENCEfalseJWT key 持久化(多 instance 必開)
DISABLE_ADDITIONAL_FEATUREStrue關閉付費功能
METRICS_ENABLEDfalse暴露 Prometheus metrics

REST API:/api/v1/...(健康檢查 /api/v1/info/status 應回 UP


5. 應用場景

場景 A:法務 / 合約團隊內部 PDF 平台

  • 痛點:合約不能丟到 SmallPDF / iLovePDF
  • 解法:內部 server 跑 Stirling-PDF + SSO + audit log;合約 redact / 簽署都在內網完成
  • 設定docker-compose-latest-fat-security.yml + PostgreSQL + LDAP / SAML

場景 B:客服 / 行政自動化

  • 痛點:每天收到 100+ 份掃描 PDF 需要 OCR + 合併 + 蓋章
  • 解法:用 Pipeline 功能拖拉建立工作流,或 curl 直接打 REST API
  • API 範例
    1curl -X POST http://localhost:8080/api/v1/general/merge-pdfs \
    2  -F "fileInput=@a.pdf" -F "fileInput=@b.pdf" \
    3  -o merged.pdf
    

場景 C:開發者整合進現有後台

  • 痛點:自己重新實作 PDF 處理太貴
  • 解法:起一個 backend-only 容器,內部後台直接打 API
  • 設定docker-compose-unified-backend.yml,外部 frontend 自己做

場景 D:個人桌面取代 Acrobat

  • 痛點:Adobe Acrobat 訂閱貴 / 不想雲端傳輸
  • 解法:下載 Tauri Desktop 版,完全離線使用

場景 E:批次 OCR 大量歷史掃描檔

  • 痛點:歷史檔案上萬份待 OCR
  • 解法:Pipeline UI 拖拉「OCR → 壓縮 → 重新命名」 batch job,或直接 cron + curl

6. 資安掃描報告

本節基於對 v2.11.0 之後 commit 的靜態掃描 + 設計層審查,不代表完整滲透測試。 官方有 SECURITY.md 與漏洞回報流程。

6.1 紅黃綠燈

項目燈號觀察
程式碼基本衛生🟢無硬編碼密碼 / token;secrets 全走環境變數(${SUPABASE_EDGE_FUNCTION_SECRET:} 等預設空字串)
ProcessBuilder 使用🟢僅見於 ExternalAppDepConfig 探測外部 binary 是否存在(List cmd + timeout);非 user-controlled string
反射(reflect)🟢全部出現在 src/test/(單元測試存取 private field),無 production 反射執行
預設無登入🟡SECURITY_ENABLELOGIN=false 是 demo 預設,正式環境必須改 true;否則任何能連到 :8080 的人都可上傳檔案
H2 DB 多容器共用🟡Issue #6395 — H2 不支援多 process 寫入,volume 共享會破壞 admin 認證;生產務必用 PostgreSQL
LibreOffice / unoserver 攻擊面🟡多年來 LibreOffice CVE 不少;上傳 .docx / .ppt 會走 LibreOffice 轉檔;建議搭配檔案類型白名單 + sandbox
PDFBox 解析未知 PDF🟡解析複雜或 malformed PDF 是常見 attack vector;近期 issue #6317(cert-sign 與空白密碼產生 corrupted PDF)顯示 edge case 仍有
上傳大小限制🟡SYSTEM_MAXFILESIZE 預設 100 MB(demo 設定);公開暴露建議下調並加 rate limit
容器以非 root 執行🟢官方 Dockerfile 有切換 user,遵循 OCI 最佳實踐
依賴更新節奏🟢Dependabot 全自動,近一週 10+ 個 bump(idna / requests / ws / protobufjs / spotless / codeql-action)
OpenSSF Scorecard🟢官方有貼 badge,分數可在 https://scorecard.dev/viewer/?uri=github.com/Stirling-Tools/Stirling-PDF
公開到 Internet🔴不建議直接暴露到公網;必須放在 reverse proxy(Caddy / Nginx)後 + IP 白名單 / VPN / SSO + WAF

6.2 部署建議(生產環境檢查清單)

  • SECURITY_ENABLELOGIN=true 一律開啟
  • 改用 PostgreSQL(不再用 H2)
  • 反向代理(Caddy / Nginx)+ TLS 終結
  • IP 白名單 / VPN / Cloudflare Access / 公司 SSO
  • SYSTEM_MAXFILESIZE 依實際需求設定,並在反向代理層加 rate limit
  • 上傳檔案目錄掛 read-only 副本 / 定期掃毒(ClamAV)
  • 容器以非 root user 跑、capabilities drop(已是預設)
  • 監控 /api/v1/info/status healthcheck + Prometheus metrics
  • 訂閱 GitHub Security Advisories
  • 每月跟 release(每月 1-2 個 minor)

6.3 攻擊面總結

攻擊向量風險緩解
上傳惡意 PDF(PDFBox parser bug)sandbox + 檔案大小限制 + 不執行 PDF JS
上傳惡意 Office 檔(LibreOffice CVE)用 ultra-lite image(無 LibreOffice)/ remote unoserver 隔離
公開未認證 instance 被當免費 PDF APISECURITY_ENABLELOGIN=true + 反向代理認證
多容器共用 H2 → admin 密碼漂移改 PostgreSQL
Dependabot 之外的供應鏈風險OpenSSF Scorecard + SBOM

7. FAQ

Q1:免費版功能會被閹割嗎? A:核心 50+ 工具全部在 app/core(open-core 模式),完全免費可用。付費差異在 app/proprietary(SSO / audit log / enterprise support)與 app/saas(managed cloud)。

Q2:可以放心處理機密合約嗎? A:技術上可以(檔案不出機器、預設不送遙測)。但要做到「機密級」需自行加上 §6.2 的所有控制。

Q3:為什麼有時候轉檔失敗? A:常見是 LibreOffice / unoserver 沒裝(用 ultra-lite image 時)或 crash(issue #6397)。看 logs /logs/stirling-pdf.log 並對照官方 Discord。

Q4:可以橫向擴展嗎? A:可以,但必須先換成 PostgreSQL,因為 H2 不支援多 instance 共享。

Q5:與 Paperless-ngx 差異? A:Paperless 偏「文件管理 + 索引 + 全文搜尋」,Stirling-PDF 偏「PDF 工具集 + 編輯」。兩者互補:Paperless 收進文件 → Stirling 編輯 / OCR / 拆分。

Q6:API 認證怎麼做? A:開啟 SECURITY_ENABLELOGIN 後,UI 走 session;API 用 JWT bearer token(SECURITY_JWT_* 系列環境變數)。

Q7:可以加自訂工具嗎? A:可以,見 ADDING_TOOLS.md(6 步驟:Controller → Service → 註冊 → tooltip → 翻譯 → 測試)。

Q8:translations 怎麼貢獻? A:見 devGuide/HowToAddNewLanguage.md;維護 40+ 語系是專案重要工作流之一。


8. 進階技巧

8.1 用 Pipeline 取代手動操作

UI 的 Pipeline 功能可以把多步驟串成 JSON 工作流,存成 .json 後可重複呼叫,等同 PDF 版 Airflow。

8.2 Headless API 整合 n8n / Zapier

REST API 是標準 multipart/form-data,n8n / Zapier 的 HTTP node 可直接打。範例:

1# OCR 一份掃描檔
2curl -X POST http://stirling:8080/api/v1/misc/ocr-pdf \
3  -F "fileInput=@scan.pdf" \
4  -F "languages=eng,chi_tra" \
5  -o ocr.pdf

8.3 用 ultra-lite image + remote unoserver 拆風險

把 LibreOffice 攻擊面隔離到獨立 unoserver 容器,主 image 用 ultra-lite。範本:docker/embedded/compose/docker-compose-latest-security-remote-uno.yml

8.4 在 K8s 跑

官方文件提供 Helm chart 與 K8s manifest,PV 掛 /configs / /logs / /tessdata,HPA 設 CPU-based scaling,搭配 PostgreSQL StatefulSet。

8.5 自架 SSO

SECURITY_OAUTH2_* / SECURITY_SAML2_* 系列變數支援 Keycloak / Okta / Azure AD / Google。


9. 整合進其他工作流

整合對象做法
AI 知識管線docling / markitdown 抽 PDF 文字後丟給 LLM;Stirling-PDF 負責前處理(合併 / OCR / 拆章節)
Paperless-ngxPaperless consume folder → Stirling OCR / split → 回寫 Paperless
n8n / ZapierHTTP node + multipart 直接打 /api/v1/...
NextcloudNextcloud Files external app + Stirling API
CI / GitHub Actionsrunner 內裝 Docker,用 Stirling 預處理測試 fixture
法務簽署流程上傳 → redact → sign → 寄出,全程 audit log

10. 重點摘要 Checklist

  • 確認部署模式(Docker / Desktop / K8s)
  • 選擇 image 變體(standard / ultra-lite / fat)
  • 設定環境變數(至少:SECURITY_ENABLELOGIN=true + LANGS + SYSTEM_MAXFILESIZE
  • 持久化 volume(/configs / /logs / /tessdata / /pipeline
  • 改用 PostgreSQL(如要多 instance / 生產)
  • 放在反向代理 + TLS + SSO / VPN 後
  • 訂閱 GitHub Security Advisories
  • 規劃月度版本升級節奏(跟著 release notes)
  • 文件化內部工作流(Pipeline JSON / API 整合腳本)
  • 訂團隊內 PDF 處理 SOP(哪些用 Stirling、哪些用 Adobe)

11. 進一步閱讀


本文件由 AI-knowledge template gh-tutorial-qd 工作流自動生成(2026-05-25)。基於 v2.11.0 release 後的快照,未來版本可能有差異。