8.0 KiB
113 — Stirling PDF Deployment Guide
Status: PLANNED — not yet deployed CT ID: 113 · IP: 192.168.1.113 Domain:
pdf.spendlik.skLast updated: 2026-06-22
Overview
Stirling PDF is a self-hosted, open-source PDF toolkit with 50+ operations (merge, split, OCR, compress, convert, redact, sign, rotate, watermark, etc.). All processing happens locally — no documents leave the network.
Primary use case in this homelab: PDF preprocessing for the Paperless-ngx pipeline (CT 111). Potential n8n integration for automated document processing.
Stack: single Docker container (Java/Spring backend + Next.js frontend), no database required.
Resource Allocation
| Resource | Allocation |
|---|---|
| CT ID | 113 |
| IP | 192.168.1.113 |
| CPUs | 2 |
| RAM | 1 GB (idle ~512 MB; OCR/conversion peaks higher) |
| Disk | 8 GB |
| Template | Debian 13 (trixie) |
| Privileged | Yes (Docker requires it) |
| Nesting | Enabled (features: nesting=1) |
Phase 1 — Create LXC Container
In the Proxmox web UI terminal on the host:
pct create 113 local:vztmpl/debian-13-standard_13.0-1_amd64.tar.zst \
--hostname stirling-pdf \
--cores 2 \
--memory 1024 \
--swap 512 \
--rootfs local-lvm:8 \
--net0 name=eth0,bridge=vmbr0,ip=192.168.1.113/24,gw=192.168.1.1 \
--unprivileged 0 \
--features nesting=1 \
--ostype debian \
--start 1
Enter the container:
pct enter 113
Phase 2 — Base Setup
apt update && apt upgrade -y
apt install -y nano curl ca-certificates gnupg lsb-release
Phase 3 — Install Docker
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
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/debian \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Verify:
docker run --rm hello-world
Phase 4 — Deploy Stirling PDF
mkdir -p /opt/stirling-pdf
cd /opt/stirling-pdf
nano docker-compose.yml
Paste:
services:
stirling-pdf:
image: stirlingtools/stirling-pdf:latest
container_name: stirling-pdf
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./trainingData:/usr/share/tessdata
- ./extraConfigs:/configs
- ./logs:/logs
environment:
- DOCKER_ENABLE_SECURITY=false
- INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
- LANGS=en_GB
⚠️
DOCKER_ENABLE_SECURITY=falseis correct for setups where authentication is handled externally by Authelia. Do not enable internal login as well — it conflicts.
Start:
docker compose up -d
docker compose logs -f
Wait for the message Started StirlingPDFApplication. Then verify locally:
curl -s http://localhost:8080 | grep -i stirling
Phase 5 — nginx Reverse Proxy (CT 101)
Enter CT 101:
pct enter 101
nano /etc/nginx/sites-available/stirling-pdf
Paste:
server {
listen 80;
server_name pdf.spendlik.sk;
location / {
proxy_pass http://192.168.1.113:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100M;
}
}
⚠️
client_max_body_size 100Mis important — large PDFs will be rejected without it.
Enable and reload:
ln -s /etc/nginx/sites-available/stirling-pdf /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Phase 6 — SSL Certificate
Still in CT 101:
certbot --nginx -d pdf.spendlik.sk
⚠️ After certbot runs, always inspect the config:
cat /etc/nginx/sites-available/stirling-pdf
Check for:
- Duplicate
server_namedirectives - Missing closing
}brace listen 443 sslblock correctly added
If anything looks wrong, fix manually — do not re-run certbot without correcting first.
Phase 7 — DNS Record
In WebSupport admin panel:
- Add A record:
pdf→ current public IP - Check both DNS management pages — missing the second page has caused outages before
- Note the numeric record ID assigned by WebSupport
- Add the record ID to
00_index.mdDNS table
Phase 8 — DDNS Updater (CT 108)
Enter CT 108:
pct enter 108
nano /usr/local/bin/ddns-update.sh
Add an entry for pdf.spendlik.sk using the record ID obtained in Phase 7, following the existing pattern in the script.
Phase 9 — Authelia Protection (CT 102)
Enter CT 102:
pct enter 102
nano /etc/authelia/configuration.yml
In the access_control.rules section, add a bypass rule for the Stirling PDF API (needed if wiring to n8n) before the catch-all 2FA rule:
- domain: pdf.spendlik.sk
resources:
- "^/api/.*"
policy: bypass
- domain: pdf.spendlik.sk
policy: two_factor
⚠️ Rule order is first-match-wins. The API bypass must precede the catch-all
two_factorrule or n8n calls will be blocked by 2FA.
Restart Authelia:
docker compose restart
Add Authelia middleware to the nginx vhost in CT 101 (refer to how other Authelia-protected services are configured — e.g., automation.spendlik.sk).
Phase 10 — Verify
Test from mobile data (not LAN — hairpin NAT):
https://pdf.spendlik.skloads and Authelia prompts for 2FA- After login, Stirling PDF home page is accessible with all tool categories visible
- Upload a test PDF and run merge or compress — file should process and download
API Integration with n8n
Stirling PDF exposes a full REST API. Swagger UI is available at:
https://pdf.spendlik.sk/swagger-ui/index.html
Example n8n HTTP Request node — compress a PDF:
POST https://pdf.spendlik.sk/api/v1/general/compress-pdf
Content-Type: multipart/form-data
fileInput: <binary PDF>
optimizeLevel: 3
For API calls from n8n, the Authelia bypass rule on
/api/*(Phase 9) allows Bearer-free requests from within the LAN.
Common operations available via API:
| Operation | Endpoint |
|---|---|
| Merge PDFs | POST /api/v1/general/merge-pdfs |
| Split PDF | POST /api/v1/general/split-pdf |
| Compress PDF | POST /api/v1/general/compress-pdf |
| PDF to image | POST /api/v1/convert/pdf/img |
| Add OCR layer | POST /api/v1/misc/add-ocr-pdf |
| Rotate pages | POST /api/v1/general/rotate-pdf |
| Remove metadata | POST /api/v1/misc/remove-blanks |
Full API reference at the Swagger UI on your instance after deployment.
Paperless-ngx Integration Ideas
Stirling PDF sits naturally upstream of Paperless-ngx for preprocessing:
- Compress oversized scans before consume — reduces NAS storage for Modelář magazines
- Rotate misaligned pages from batch scans
- Strip metadata from sensitive documents before ingestion
- OCR layer addition for scanned PDFs that Paperless struggles with (though Paperless has its own OCR — use Stirling for pre-processing only when needed)
A simple n8n workflow pattern:
New file in NAS consume folder (webhook or poll)
→ Stirling PDF: compress + rotate
→ Save back to consume folder
→ Paperless picks it up automatically
Resource Notes
- Idle RAM: ~512 MB
- OCR operations: can spike to ~800 MB temporarily
- LibreOffice conversions (PDF → DOCX etc.): heaviest operation, may need RAM bump to 2 GB if used frequently
- 2 CPU cores sufficient for single-user use
Gotchas
| Issue | Fix |
|---|---|
| Large PDF uploads rejected | client_max_body_size 100M in nginx config |
| certbot corrupts nginx config | Always inspect after issuance |
| n8n API calls blocked by Authelia | Add /api/* bypass rule before catch-all |
| Container won't start after Proxmox reboot | Check pct config 113 for boot order; add --onboot 1 if missing |