Bitdoze Logo

How to Self-Host Stirling PDF (Docker, Traefik, Dokploy)

Self-host Stirling PDF with Docker to merge, split, convert, and secure PDFs privately. Step-by-step guide covering Traefik, Dokploy, API, and MCP setup.

DragosDragos25 min read
How to Self-Host Stirling PDF (Docker, Traefik, Dokploy)

PDF documents are everywhere: contracts, invoices, reports, scanned forms. Manipulating them usually means paying for Acrobat Pro, uploading files to some third-party web tool, or cobbling together command-line utilities that half-work.

Stirling PDF is a self-hosted web application that handles merging, splitting, converting, compressing, OCR, signing, and dozens more PDF operations, all running on your own infrastructure. The project hit V2 in late 2025 with a full React frontend rewrite, stateful undo/redo, desktop apps, a built-in MCP server for AI agents, and Automate/Pipelines for chaining operations. It has over 91,000 GitHub stars and 30M+ downloads. The free self-hosted tier supports up to 5 users with no feature restrictions on operations.

This guide walks through three deployment paths: standalone Docker Compose, Traefik with Dockge, and Dokploy. Each one is copy-pasteable and includes verify steps.

For more useful self-hosted applications, check out our guide on Docker containers for home servers.

What is Stirling PDF?

Stirling PDF is an open-core, self-hosted PDF platform. The free tier gives you full access to 60+ tools, no credits, no watermarks, no artificial limits on the number of operations. It runs as a single Docker container with a Java processing backend, React frontend, and optional integrations for Tesseract OCR, LibreOffice, and PDFium.

Key capabilities of Stirling PDF

  • Document management: merge, split, rotate, reorganize, and compare PDF pages
  • Format conversion: PDFs to/from images, Word, Excel, HTML, Markdown, and more
  • Security operations: add/remove passwords, digital signatures, encryption, redaction
  • Compression and optimization: reduce file sizes while maintaining quality
  • OCR integration: extract text from scanned documents using Tesseract
  • Metadata management: clean, edit, or remove document metadata
  • Batch processing: handle multiple documents simultaneously via the Automate/Pipeline UI
  • API access: RESTful endpoints for automation workflows and scripting
  • MCP server: expose PDF operations as tools for AI agents (Claude Desktop, etc.)
  • File sharing and group signing: share documents for collaborative signing (alpha since v2.9.0)
  • Desktop apps: Windows, macOS, and Linux native clients for local processing

How Stirling PDF works

Component Function Details
Web interface Browser-based GUI React frontend, 38+ languages, dark mode
Processing engine Java-based PDF core JDK 25, JPDFium for memory-efficient merge/split
OCR engine Tesseract integration Language packs via tessdata directory
Office conversions LibreOffice DOCX, XLSX, PPTX to PDF and back
API layer RESTful endpoints Swagger UI at /swagger-ui.html
MCP server AI agent integration POST /mcp, off by default
Storage Temporary + persistent H2 DB, settings.yml, optional S3 backend

Stirling PDF is an open-source project. View documentation and contribute at the GitHub repository and project website. Full docs are at docs.stirlingpdf.com.

Licensing: free, server, and enterprise

Stirling PDF moved to an open-core model. The breakdown for self-hosters:

Licensing tiers

Free (self-hosted): Up to 5 users, all 60+ operations, no credits or feature gating. This is what you get by default when you deploy with Docker. Genuinely free and unlimited in operations.

Server ($99/mo or $999/yr): 100 users (add blocks of 100), OAuth2 SSO, external PostgreSQL, support tickets, Google Drive integration.

Enterprise (custom pricing): SAML2, air-gapped certificate activation, Prometheus metrics, audit logs, SLAs.

Activation: Settings → Plan (in-app Stripe) or settings.ymlpremium.key.

For a solo operator or small team, the free tier is all you need. The paid tiers matter when you need SSO or external database support.

Prerequisites

Before deploying Stirling PDF, make sure you have the following:

Resource requirements

Minimum: 2 CPU cores, 2GB RAM, 10GB disk Recommended: 4+ CPU cores, 4GB+ RAM, SSD storage Image size: The latest tag is approximately 1GB compressed. Budget for the download.

Heavy conversions (LibreOffice) and OCR operations need more RAM. The latest-ultra-lite variant is available for Raspberry Pi and low-end VPS but lacks compress, OCR, and office conversions.

Image variants:

Variant Tag Best for Missing features
Standard :latest Most deployments None
Fat :latest-fat High-fidelity conversions, extra fonts Larger image size
Ultra Lite :latest-ultra-lite Raspberry Pi, low-end VPS No compress, OCR, office conversions, repair, PDF/A

Infrastructure requirements:

Setup option 1: Docker and Docker Compose (standalone)

This is the simplest path. A single container, no reverse proxy, good for local network access or testing before adding HTTPS.

Step 1: Create project structure

mkdir -p ~/stirling-pdf && cd ~/stirling-pdf

Step 2: Configure Docker Compose

Create a docker-compose.yml file:

services:
  stirling-pdf:
    image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
    container_name: stirling-pdf
    ports:
      - "8080:8080"
    volumes:
      - ./stirling-data/tessdata:/usr/share/tessdata    # OCR language files
      - ./stirling-data/configs:/configs                # settings.yml + H2 DB (back this up!)
      - ./stirling-data/logs:/logs
      - ./stirling-data/customFiles:/customFiles
      - ./stirling-data/pipeline:/pipeline              # Automate / folder-scan configs
    environment:
      - SECURITY_ENABLELOGIN=true                       # login is ON by default
      - SECURITY_INITIALLOGIN_USERNAME=admin            # optional, first boot only
      - SECURITY_INITIALLOGIN_PASSWORD=ChangeMeNow123!  # optional, first boot only
      - SYSTEM_DEFAULTLOCALE=en-US                      # UI language (hyphenated)
      - SYSTEM_GOOGLEVISIBILITY=false                   # block search engine indexing
      - SYSTEM_MAXFILESIZE=500                          # per-file MB (1-999)
      - SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE=2000MB
      - SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE=2000MB
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/api/v1/info/status"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

Default login credentials

V2 ships with login enabled by default. The default account is admin / stirling. Change the password immediately after first login. Some builds force a password change on first login. You can preset initial credentials with SECURITY_INITIALLOGIN_USERNAME and SECURITY_INITIALLOGIN_PASSWORD (only honored on first boot).

For anonymous access (no login required), set SECURITY_ENABLELOGIN=false and DISABLE_ADDITIONAL_FEATURES=false.

Step 3: Initialize directories and deploy

mkdir -p stirling-data/{tessdata,configs,logs,customFiles,pipeline}
docker compose up -d

Watch the logs to confirm startup:

docker compose logs -f

Look for Started StirlingPDF in the output. If you see unknown configuration key warnings, those are deprecated env vars. Harmless but noisy. Remove them from your compose file.

Step 4: Configure OCR support (optional)

Download Tesseract language packs for OCR:

# English is required. Do not delete eng.traineddata
wget -P stirling-data/tessdata/ https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata
wget -P stirling-data/tessdata/ https://github.com/tesseract-ocr/tessdata/raw/main/fra.traineddata
wget -P stirling-data/tessdata/ https://github.com/tesseract-ocr/tessdata/raw/main/deu.traineddata
wget -P stirling-data/tessdata/ https://github.com/tesseract-ocr/tessdata/raw/main/spa.traineddata
wget -P stirling-data/tessdata/ https://github.com/tesseract-ocr/tessdata/raw/main/chi_sim.traineddata

Restart the container after adding language files:

docker compose restart stirling-pdf

Step 5: Verify installation

  • Web UI: Navigate to http://localhost:8080
  • Health check: curl http://localhost:8080/api/v1/info/status
  • API docs: Browse to http://localhost:8080/swagger-ui.html

Installation complete

Your Stirling PDF instance is running. Log in with your credentials (or admin/stirling if you didn’t preset them) and change the password immediately.

Common failure: Blank login page after startup. Check container logs with docker compose logs stirling-pdf, ensure volume directories have correct permissions (chmod -R 755 ./stirling-data).

Setup option 2: Traefik and Dockge integration

This setup puts Stirling PDF behind Traefik with automatic HTTPS via Let’s Encrypt. Dockge provides a web interface for managing the compose stack.

Prerequisites

This configuration requires a working Traefik and Dockge setup. Follow the Traefik wildcard certificate guide for SSL configuration.

Step 1: Verify network configuration

# Check for existing Traefik network
docker network ls | grep traefik-net

# Create if it doesn't exist
docker network create traefik-net

Step 2: Docker Compose configuration

Create a docker-compose.yml with Traefik labels:

services:
  stirling-pdf:
    image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
    container_name: stirling-pdf
    volumes:
      - ./stirling-data/tessdata:/usr/share/tessdata
      - ./stirling-data/configs:/configs
      - ./stirling-data/logs:/logs
      - ./stirling-data/customFiles:/customFiles
      - ./stirling-data/pipeline:/pipeline
    environment:
      - SECURITY_ENABLELOGIN=true
      - SECURITY_INITIALLOGIN_USERNAME=admin
      - SECURITY_INITIALLOGIN_PASSWORD=ChangeMeNow123!
      - SYSTEM_DEFAULTLOCALE=en-US
      - SYSTEM_GOOGLEVISIBILITY=false
      - SYSTEM_MAXFILESIZE=500
      - SYSTEM_ROOTURIPATH=/
      - SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE=2000MB
      - SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE=2000MB
    networks:
      - traefik-net
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.stirling-pdf.rule=Host(`pdf.yourdomain.com`)"
      - "traefik.http.routers.stirling-pdf.entrypoints=https"
      - "traefik.http.routers.stirling-pdf.tls=true"
      - "traefik.http.routers.stirling-pdf.tls.certresolver=letsencrypt"
      - "traefik.http.services.stirling-pdf.loadbalancer.server.port=8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/api/v1/info/status"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

networks:
  traefik-net:
    external: true

Note: App branding (name, description, logo) is now configured in-app via Settings → UI, not through environment variables. The old UI_APPNAME and UI_HOMEDESCRIPTION env vars are removed in V2.

Step 3: Deploy via Dockge

  1. Access your Dockge dashboard (typically https://dockge.yourdomain.com)
  2. Click “New Stack” and name it stirling-pdf
  3. Paste the Docker Compose configuration above
  4. Update pdf.yourdomain.com in the Traefik labels to your actual domain
  5. Click deploy and monitor the logs

Step 4: DNS configuration

Point your subdomain to the server:

Record Type Name Value TTL
A pdf your-server-ip 300

Or use a CNAME if your domain already resolves:

Record Type Name Value TTL
CNAME pdf yourdomain.com 300

DNS propagation

DNS changes may take 5-15 minutes to propagate. Wait before verifying HTTPS access.

Step 5: Verify HTTPS access

After DNS propagates:

  • HTTPS: Navigate to https://pdf.yourdomain.com
  • SSL certificate: Check that the Let’s Encrypt certificate is valid (click the lock icon in your browser)
  • API docs: Browse to https://pdf.yourdomain.com/swagger-ui.html

Setup option 3: Dokploy deployment

Dokploy provides a graphical interface with automated SSL certificate management. This works well if you prefer clicking over typing.

Step 1: Dokploy platform setup

If Dokploy isn’t installed yet, follow the Dokploy installation and configuration guide.

Step 2: Create Stirling PDF project

  1. Access your Dokploy dashboard
  2. Click “New Project” and name it stirling-pdf
  3. Select “Compose” as the application type. Do not use the built-in Stirling PDF template, which may be pinned to an old V1 version

Dokploy create service form showing compose application type selection

Step 3: Environment variables configuration

Set these environment variables in Dokploy:

Variable Value Description
SECURITY_ENABLELOGIN true Enable login (default in V2)
SECURITY_INITIALLOGIN_USERNAME admin Initial admin username (first boot only)
SECURITY_INITIALLOGIN_PASSWORD ChangeMeNow123! Initial password (first boot only)
SYSTEM_DEFAULTLOCALE en-US UI language
SYSTEM_GOOGLEVISIBILITY false Block search engine indexing
SYSTEM_MAXFILESIZE 500 Max file size in MB

Use this in the Dokploy compose configuration:

environment:
  - SECURITY_ENABLELOGIN=${SECURITY_ENABLELOGIN}
  - SECURITY_INITIALLOGIN_USERNAME=${SECURITY_INITIALLOGIN_USERNAME}
  - SECURITY_INITIALLOGIN_PASSWORD=${SECURITY_INITIALLOGIN_PASSWORD}
  - SYSTEM_DEFAULTLOCALE=${SYSTEM_DEFAULTLOCALE}
  - SYSTEM_GOOGLEVISIBILITY=${SYSTEM_GOOGLEVISIBILITY}
  - SYSTEM_MAXFILESIZE=${SYSTEM_MAXFILESIZE}

Step 4: Domain and SSL configuration

  1. Navigate to the “Domains” section in your Dokploy project
  2. Add your domain: pdf.yourdomain.com
  3. Enable SSL/TLS certificate generation
  4. Enable automatic certificate renewal
  5. Configure HTTP to HTTPS redirection

Dokploy domain configuration panel with SSL toggle enabled

Step 5: Deploy and monitor

  1. Click the “Deploy” button in Dokploy
  2. Monitor the deployment logs for errors
  3. Verify the health indicator shows green
  4. Access your instance and test a PDF operation

Dokploy deployment panel showing build logs and status

Deploy with Dokploy

Upgrading from V1 to V2

If you’re running an older V1 (0.4x) installation, here’s what to know before upgrading:

V1 to V2 migration

Back up first. Stop the container and tar your configs/ directory. It contains the H2 database file.

docker compose stop stirling-pdf
tar -czf stirling-v1-backup-$(date +%Y%m%d).tar.gz ./stirling-data/configs

What changes:

  • Settings migrate automatically. The H2 DB schema upgrades on first start
  • Users must re-login once (JWT format changed)
  • Deprecated env vars (DOCKER_ENABLE_SECURITY, LANGS, UI_APPNAME, UI_HOMEDESCRIPTION, INSTALL_BOOK_AND_ADVANCED_HTML_OPS) throw unknown configuration key warnings. Harmless but noisy. Remove them.
  • Thymeleaf template customizations in customFiles/templates/ no longer work (React rewrite). Static overrides in customFiles/static/ still do.
  • The default image registry changed to docker.stirlingpdf.com/stirlingtools/stirling-pdf

Update your image tag and compose file, then docker compose up -d. Check the logs for migration messages.

Authentication and user management

V2 has login enabled by default.

Default credentials: admin / stirling. Change immediately after first login.

Preset initial credentials (first boot only, via environment variables):

environment:
  - SECURITY_INITIALLOGIN_USERNAME=myadmin
  - SECURITY_INITIALLOGIN_PASSWORD=YourSecurePassword123!

These are only honored on the very first startup. After that, manage users through the admin UI.

Roles: Admin users can manage all settings and users. Regular users get access to PDF operations based on configuration.

API keys: Each user can generate a personal API key from Account → Settings. For automation, set a global API key:

environment:
  - SECURITY_CUSTOMGLOBALAPIKEY=your-long-random-key-here

Login lockout: By default, accounts lock after 5 failed attempts. Configure with:

environment:
  - SECURITY_LOGINATTEMPTCOUNT=5       # set -1 to disable lockout
  - SECURITY_LOGINRESETTIMEMINUTES=120  # lockout duration

SSO: OAuth2 is available on the Server tier ($99/mo). SAML2 requires Enterprise. For a solo operator on the free tier, stick with local accounts.

Anonymous mode (no login at all):

environment:
  - SECURITY_ENABLELOGIN=false
  - DISABLE_ADDITIONAL_FEATURES=false

For production deployments, read our guide on handling secrets in Docker Compose to avoid putting passwords in plain text.

API integration and automation

Stirling PDF exposes a REST API. With login enabled, all API calls require authentication.

API authentication

Get your API key from Account → Settings in the web UI, or set a global key via SECURITY_CUSTOMGLOBALAPIKEY. Pass it as a header:

X-API-KEY: your-api-key

API documentation is available at /swagger-ui.html (also accessible via Settings → API Documentation). The online Scalar registry is at registry.scalar.com/@stirlingpdf.

Example: PDF to images

curl -X POST "https://pdf.yourdomain.com/api/v1/convert/pdf-to-img" \
  -H "X-API-KEY: your-api-key" \
  -H "Content-Type: multipart/form-data" \
  -F "[email protected]" \
  -F "imageFormat=PNG" \
  -F "singleOrMultiple=multiple"

Example: Pipeline (OCR + compress in one call)

The Pipeline/Automate system lets you chain multiple operations in a single API call:

curl -X POST "https://pdf.yourdomain.com/api/v1/pipeline/handleData" \
  -H "X-API-KEY: your-api-key" \
  -F "[email protected]" \
  -F 'json={"name":"OCR-compress","pipeline":[
        {"operation":"/api/v1/misc/ocr-pdf","parameters":{"languages":["eng"],"ocrType":"skip-text"}},
        {"operation":"/api/v1/misc/compress-pdf","parameters":{"optimizeLevel":2}}]}' \
  --output result.pdf

Pipeline error handling

Pipeline errors currently collapse to HTTP 200 with an empty body. Always verify the output starts with %PDF- (or PK for ZIP-based formats). If you get an empty file, check the container logs for the actual error.

For async processing, add ?async=true to the pipeline URL and poll GET /api/v1/general/job/{id} for status.

n8n workflow integration

Connect Stirling PDF with self-hosted n8n for document processing workflows:

  1. Trigger: Email attachment received or file dropped in a watched folder
  2. Process: Single pipeline call to OCR + compress + convert
  3. Store: Save result to your document management system

A single pipeline call replaces what used to require 5+ chained API nodes. For simple merges without a UI, you can also use pdfunite from the Linux command line.

MCP server for AI agents

Stirling PDF ships with a built-in MCP (Model Context Protocol) server that exposes PDF operations as tools for AI agents. This is useful if you’re building AI workflows that need to process documents.

What is MCP?

MCP is a protocol that lets AI assistants like Claude use external tools. Stirling PDF’s MCP server lets an AI agent merge, split, convert, compress, and secure PDFs without writing API code. See our introduction to the Model Context Protocol for background.

Enable the MCP server in your compose file:

environment:
  - MCP_ENABLED=true
  - MCP_AUTH_MODE=apikey
  - MCP_ALLOWEDOPERATIONS=stirling_pages,stirling_convert,stirling_misc,stirling_security

Available tool groups: stirling_pages (merge/split/rotate), stirling_convert (format conversions), stirling_misc (compress/OCR/repair), stirling_security (passwords/signatures), stirling_upload, stirling_download.

Claude Desktop configuration: Add this to your claude_desktop_config.json:

{
  "mcpServers": {
    "stirling-pdf": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://pdf.yourdomain.com/mcp",
        "--header",
        "X-API-KEY: your-api-key"
      ]
    }
  }
}

Request and response limits default to 10MB. The MCP server does not include an AI engine. It exposes PDF operations as tools that external AI agents can call.

Security best practices and data protection

Stirling PDF has had real security issues. Here’s what you need to know.

SSRF protection

URL-to-PDF conversion is disabled by default (system.enableUrlToPDF: false) because of SSRF risk. If you enable it, SSRF protection is on by default at MEDIUM level (blocks RFC1918, localhost, link-local, and cloud metadata endpoints). Set to MAX for allowlist-only mode:

# In settings.yml
system:
  enableUrlToPDF: true
  urlToPdfProtection: MAX
  allowedDomains:
    - "trusted-domain.com"

Security advisories

Stirling PDF has had several security advisories. Key ones:

Date Severity Issue CVE Fixed in
Aug 2025 High SSRF via convert endpoints CVE-2025-55150, CVE-2025-55151 V1 v1.1.0
Mar 2026 High Path traversal in markdown-to-PDF GHSA-wccq-mg6x-2w22 V2
Mar 2026 Moderate Stored XSS via EML export GHSA-xmhg-fv84-jgfc V2
Jul 2026 High Stored XSS in Info Summary GHSA-qc47-qgh9-xj63 V2.14.2
Jul 2026 High API key disclosure via Pipeline GHSA-3xxh-mm3g-c9w5 V2.14.2

Always run the latest version

Security fixes only ship in the latest release. There are no backports to older versions. Pin to a specific tag in production (e.g., v2.14.3), but update promptly when security releases drop. Releases come out 2-4 times per week.

Network and access security

  • Block search engine indexing: SYSTEM_GOOGLEVISIBILITY=false (already set in the compose examples above)
  • Disable unused endpoints: Configure endpoints.toRemove in settings.yml to disable API endpoints you don’t use
  • HTTPS only: Always run behind a reverse proxy with TLS. Never expose port 8080 directly to the internet
  • Rate limiting: Login-attempt lockout plus fail2ban integration for brute-force protection

Storage and backup

What to back up

Critical data lives in these locations (all under your mounted volumes):

Path Contents Priority
configs/stirling-pdf-DB-*.mv.db H2 database (users, settings, history) Critical
configs/settings.yml Application configuration Critical
customFiles/ Custom templates and static overrides High
tessdata/ OCR language packs Medium (re-downloadable)
pipeline/ Automate workflow configs Medium

Backup procedure

# Stop the container for a consistent snapshot
docker compose stop stirling-pdf

# Create a compressed backup
tar -czf stirling-backup-$(date +%Y%m%d-%H%M%S).tar.gz \
  -C ./stirling-data configs customFiles tessdata pipeline

# Restart
docker compose start stirling-pdf

Restore procedure

# Stop the container
docker compose stop stirling-pdf

# Extract backup (overwrites current data)
tar -xzf stirling-backup-YYYYMMDD-HHMMSS.tar.gz -C ./stirling-data

# Verify critical files exist
ls -la ./stirling-data/configs/stirling-pdf-DB-*.mv.db
ls -la ./stirling-data/configs/settings.yml

# Restart
docker compose start stirling-pdf

S3 storage (optional)

V2.12+ supports S3-compatible storage for uploads and artifacts. This is useful for multi-server setups or when you want durable storage separate from the container host. Configure in settings.yml under the storage section. The Server and Enterprise tiers also support external PostgreSQL instead of the embedded H2 database.

Performance and resource management

Sizing guidance

Server specs Max file size Use case
2 CPU / 2-4GB RAM 200-500 MB Personal use, occasional documents
4 CPU / 8GB RAM 1000 MB Small team, regular processing
8+ CPU / 16GB+ RAM 2000 MB Heavy batch processing, large scans

V2.12.0 introduced JPDFium for merge and split operations, using up to 99% less memory than the previous engine. V2.14.3 fixed crashes when processing 2GB+ PDFs.

Docker resource limits

Set hard limits to prevent a runaway process from killing your server:

services:
  stirling-pdf:
    # ... other configuration
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 4G
        reservations:
          cpus: '1.0'
          memory: 2G

For memory tuning, set JAVA_TOOL_OPTIONS=-Xmx2g to cap the JVM heap.

Monitoring and health checks

The health endpoint /api/v1/info/status is always accessible without authentication. Use it with Uptime Kuma, Beszel, or any monitoring tool that supports HTTP health checks.

Usage statistics are available at /api/v1/info/requests/all (total requests) and /api/v1/info/requests/unique (unique requests).

Troubleshooting common issues

Blank login page after fresh install

This usually means the container started but the frontend couldn’t initialize. Check:

  1. Container logs: docker compose logs stirling-pdf
  2. Volume permissions: chmod -R 755 ./stirling-data
  3. Sufficient memory: the container needs at least 2GB. Check with docker stats
Unknown configuration key warnings on startup

These are deprecated V1 environment variables. Common offenders:

  • DOCKER_ENABLE_SECURITY — removed in V2 (auth is built-in)
  • LANGS — replaced by SYSTEM_DEFAULTLOCALE
  • UI_APPNAME / UI_HOMEDESCRIPTION — now configured in-app (Settings → UI)
  • INSTALL_BOOK_AND_ADVANCED_HTML_OPS — the latest image already includes LibreOffice

Remove these from your compose file. The warnings are harmless but clutter the logs.

Users logged out after upgrading

V2 changed the JWT token format. All users must re-login once after upgrading from V1. This is expected behavior, not a bug.

Custom templates not loading

V2 replaced the Thymeleaf template engine with React. Custom templates in customFiles/templates/ no longer work. Static file overrides in customFiles/static/ still function. Check the migration docs for details.

Pipeline returns empty response

Pipeline errors collapse to HTTP 200 with an empty body. Check that:

  1. Your output starts with %PDF- (or PK for ZIP formats)
  2. The API key has sufficient permissions
  3. The input file isn’t corrupted
  4. Check container logs for the actual error message
HTTP 431 during SSO login

If you get HTTP 431 (Request Header Fields Too Large) during OAuth2/SSO login, increase the Jetty header size:

environment:
  - SERVER_JETTY_MAX_HTTP_REQUEST_HEADER_SIZE=16384

Debugging

Enable detailed logging by setting SYSTEM_LOGFILE=/logs/stirling.log in your environment variables. Check the log file for application-level errors.

Maintenance and updates

Update procedure

cd ~/stirling-pdf

# Pull the latest image
docker compose pull

# Recreate the container
docker compose up -d

# Clean up old images
docker image prune -f

Version pinning: In production, consider pinning to a specific tag (e.g., docker.stirlingpdf.com/stirlingtools/stirling-pdf:v2.14.3) instead of :latest. This prevents surprise breakage from automatic updates. When you’re ready to upgrade, update the tag and run docker compose pull && docker compose up -d.

Back up before major upgrades. The v2.12.0 release itself recommended backing up before upgrading. Releases come out 2-4 times per week and include security fixes — subscribe to the GitHub releases feed to stay informed.

For automated container updates, consider auto-updating Docker containers with Tugtainer.

Maintenance schedule

  • Weekly: Monitor disk usage, check container health status
  • Monthly: Update Docker image, review logs for errors or security warnings
  • Quarterly: Review resource limits, audit user accounts and API keys
  • Before major upgrades: Back up configs/, customFiles/, tessdata/, pipeline/

Conclusion

Self-hosting Stirling PDF gives you a private, capable PDF processing platform that runs on your own infrastructure. The V2 rewrite brought a modern React frontend, memory-efficient PDFium processing, a built-in MCP server for AI agent integration, and Automate/Pipelines for chaining operations.

  • Data control: Documents never leave your server — no third-party uploads, no privacy tradeoffs
  • Cost-effective: The free self-hosted tier covers up to 5 users with all 60+ operations
  • Configurable limits: File size limits, user counts, and features are all adjustable
  • API and MCP automation: REST API for scripting, MCP for AI agents, Pipelines for chaining operations
  • Multi-layered security: Login, API keys, SSRF protection, rate limiting, HTTPS
  • Scalable: From a Raspberry Pi (ultra-lite image) to a beefy server handling 2GB PDFs

Start with Option 1 (standalone Docker Compose) to get running in 5 minutes. Add Traefik when you need HTTPS. Use Dokploy if you want a GUI. The desktop apps are a bonus for local processing on your own machines.

Start Your Stirling PDF Journey

Explore our guides on Docker container orchestration with Dockge, Traefik reverse proxy configuration, and Dokploy platform management.