Stirling-PDF/docker/unified
Anthony Stirling d2677e64dd
OCR fix and Mobile QR changes (#5433)
# Description of Changes
## OCR / Tesseract path handling

Makes tessDataPath resolution deterministic with priority: config >
TESSDATA_PREFIX env > default.
Updates language discovery to use runtimePathConfig.getTessDataPath()
instead of raw config value.
Ensure default OCR dir is debian based not alpine

## Mobile scanner: feature gating + new conversion settings
Adds system.mobileScannerSettings (convert-to-PDF + resolution + page
format + stretch) exposed via backend config and configurable in the
proprietary admin UI.
Enforces enableMobileScanner on the MobileScannerController endpoints
(403 when disabled).
Frontend mobile upload flow can now optionally convert received images
to PDF (pdf-lib + canvas).

## Desktop/Tauri connectivity work
Expands tauri-plugin-http permissions and enables dangerous-settings.
Adds a very comprehensive multi-stage server connection diagnostic
routine (with lots of logging).


<img width="688" height="475" alt="image"
src="https://github.com/user-attachments/assets/6f9c1aec-58c7-449b-96b0-52f25430d741"
/>


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
2026-01-12 11:18:37 +00:00
..
build.sh docker (#4711) 2025-10-27 16:45:18 +00:00
entrypoint.sh OCR fix and Mobile QR changes (#5433) 2026-01-12 11:18:37 +00:00
nginx.conf Bug/v2/signature fixes (#5104) 2025-12-02 22:48:29 +00:00
README.md docker (#4711) 2025-10-27 16:45:18 +00:00

Stirling-PDF Unified Container

Single Docker container that can run as frontend + backend, frontend only, or backend only using the MODE environment variable.

Quick Start

MODE=BOTH (Default)

Single container with both frontend and backend on port 8080:

docker run -p 8080:8080 \
  -e MODE=BOTH \
  stirlingtools/stirling-pdf:unified

Access at: http://localhost:8080

MODE=FRONTEND

Frontend only, connecting to separate backend:

docker run -p 8080:8080 \
  -e MODE=FRONTEND \
  -e VITE_API_BASE_URL=http://backend:8080 \
  stirlingtools/stirling-pdf:unified

MODE=BACKEND

Backend API only:

docker run -p 8080:8080 \
  -e MODE=BACKEND \
  stirlingtools/stirling-pdf:unified

Access API at: http://localhost:8080/api Swagger UI at: http://localhost:8080/swagger-ui/index.html


Architecture

MODE=BOTH (Default)

┌─────────────────────────────────────┐
│     Port 8080 (External)            │
│  ┌───────────────────────────────┐  │
│  │         Nginx                 │  │
│  │  • Serves frontend (/)        │  │
│  │  • Proxies /api/* → backend   │  │
│  └───────────┬───────────────────┘  │
│              │                       │
│  ┌───────────▼───────────────────┐  │
│  │    Backend (Internal 8081)    │  │
│  │  • Spring Boot                │  │
│  │  • PDF Processing             │  │
│  │  • UnoServer                  │  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘

MODE=FRONTEND

┌─────────────────────────────┐      ┌──────────────────┐
│   Frontend Container        │      │  Backend         │
│   Port 8080                 │      │  (External)      │
│  ┌───────────────────────┐  │      │                  │
│  │       Nginx           │  │──────▶  :8080/api       │
│  │  • Serves frontend    │  │      │                  │
│  │  • Proxies to backend │  │      │                  │
│  └───────────────────────┘  │      └──────────────────┘
└─────────────────────────────┘

MODE=BACKEND

┌─────────────────────────────┐
│   Backend Container         │
│   Port 8080                 │
│  ┌───────────────────────┐  │
│  │   Spring Boot         │  │
│  │  • API Endpoints      │  │
│  │  • PDF Processing     │  │
│  │  • UnoServer          │  │
│  └───────────────────────┘  │
└─────────────────────────────┘

Environment Variables

MODE Configuration

Variable Values Default Description
MODE BOTH, FRONTEND, BACKEND BOTH Container operation mode

MODE=BOTH Specific

Variable Default Description
BACKEND_INTERNAL_PORT 8081 Internal port for backend when MODE=BOTH

MODE=FRONTEND Specific

Variable Default Description
VITE_API_BASE_URL http://backend:8080 Backend URL for API proxying

Standard Configuration

All modes support standard Stirling-PDF environment variables:

  • DISABLE_ADDITIONAL_FEATURES - Enable/disable OCR and LibreOffice features
  • DOCKER_ENABLE_SECURITY - Enable authentication
  • PUID / PGID - User/Group IDs
  • SYSTEM_MAXFILESIZE - Max upload size (MB)
  • TESSERACT_LANGS - Comma-separated OCR language codes
  • JAVA_CUSTOM_OPTS - Additional JVM options

See full configuration docs at: https://docs.stirlingpdf.com


Docker Compose Examples

Example 1: All-in-One (MODE=BOTH)

File: docker/compose/docker-compose-unified-both.yml

services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8080:8080"
    volumes:
      - ./data:/usr/share/tessdata:rw
      - ./config:/configs:rw
    environment:
      MODE: BOTH
    restart: unless-stopped

Example 2: Separate Frontend & Backend

File: docker/compose/docker-compose-unified-frontend.yml

services:
  backend:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8081:8080"
    environment:
      MODE: BACKEND
    volumes:
      - ./data:/usr/share/tessdata:rw
      - ./config:/configs:rw

  frontend:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8080:8080"
    environment:
      MODE: FRONTEND
      VITE_API_BASE_URL: http://backend:8080
    depends_on:
      - backend

Example 3: Backend API Only

File: docker/compose/docker-compose-unified-backend.yml

services:
  stirling-pdf-api:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8080:8080"
    environment:
      MODE: BACKEND
    volumes:
      - ./data:/usr/share/tessdata:rw
      - ./config:/configs:rw
    restart: unless-stopped

Building the Image

# From repository root
docker build -t stirlingtools/stirling-pdf:unified -f docker/Dockerfile.unified .

Build Arguments

Argument Description
VERSION_TAG Version tag for the image

Example:

docker build \
  --build-arg VERSION_TAG=v1.0.0 \
  -t stirlingtools/stirling-pdf:unified \
  -f docker/Dockerfile.unified .

Use Cases

1. Simple Deployment (MODE=BOTH)

  • Best for: Personal use, small teams, simple deployments
  • Pros: Single container, easy setup, minimal configuration
  • Cons: Frontend and backend scale together

2. Scaled Frontend (MODE=FRONTEND + BACKEND)

  • Best for: High traffic, need to scale frontend independently
  • Pros: Scale frontend containers separately, CDN-friendly
  • Example:
    services:
      backend:
        image: stirlingtools/stirling-pdf:unified
        environment:
          MODE: BACKEND
        deploy:
          replicas: 1
    
      frontend:
        image: stirlingtools/stirling-pdf:unified
        environment:
          MODE: FRONTEND
          VITE_API_BASE_URL: http://backend:8080
        deploy:
          replicas: 5  # Scale frontend independently
    

3. API-Only (MODE=BACKEND)

  • Best for: Headless deployments, custom frontends, API integrations
  • Pros: Minimal resources, no nginx overhead
  • Example: Use with external frontend or API consumers

4. Multi-Backend Setup

  • Best for: Load balancing, high availability
  • Example:
    services:
      backend-1:
        image: stirlingtools/stirling-pdf:unified
        environment:
          MODE: BACKEND
    
      backend-2:
        image: stirlingtools/stirling-pdf:unified
        environment:
          MODE: BACKEND
    
      frontend:
        image: stirlingtools/stirling-pdf:unified
        environment:
          MODE: FRONTEND
          VITE_API_BASE_URL: http://load-balancer:8080
    

Port Configuration

All modes use port 8080 by default:

  • MODE=BOTH: Nginx listens on 8080, proxies to backend on internal 8081
  • MODE=FRONTEND: Nginx listens on 8080
  • MODE=BACKEND: Spring Boot listens on 8080

Expose port 8080 in all configurations:

ports:
  - "8080:8080"

Health Checks

MODE=BOTH and MODE=BACKEND

healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 3

MODE=FRONTEND

healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8080/ || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 3

Troubleshooting

Check logs

docker logs stirling-pdf-container

Look for the startup banner:

===================================
Stirling-PDF Unified Container
MODE: BOTH
===================================

Invalid MODE error

ERROR: Invalid MODE 'XYZ'. Must be BOTH, FRONTEND, or BACKEND

Fix: Set MODE to one of the three valid values.

Frontend can't connect to backend (MODE=FRONTEND)

Check:

  1. VITE_API_BASE_URL points to correct backend URL
  2. Backend container is running and accessible
  3. Network connectivity between containers

Backend not starting (MODE=BOTH or BACKEND)

Check:

  1. Sufficient memory allocated (4GB recommended)
  2. Java heap size (JAVA_CUSTOM_OPTS)
  3. Volume permissions for /tmp/stirling-pdf

Migration Guide

From Separate Containers → MODE=BOTH

Before:

services:
  frontend:
    image: stirlingtools/stirling-pdf:frontend
    ports: ["80:80"]

  backend:
    image: stirlingtools/stirling-pdf:backend
    ports: ["8080:8080"]

After:

services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:unified
    ports: ["8080:8080"]
    environment:
      MODE: BOTH

From Legacy → MODE=BACKEND

services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:latest
    ports: ["8080:8080"]

Becomes:

services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:unified
    ports: ["8080:8080"]
    environment:
      MODE: BACKEND

Performance Tuning

MODE=BOTH

environment:
  JAVA_CUSTOM_OPTS: "-Xmx4g -XX:MaxRAMPercentage=75"
  BACKEND_INTERNAL_PORT: 8081
deploy:
  resources:
    limits:
      memory: 4G
    reservations:
      memory: 2G

MODE=FRONTEND (Lightweight)

deploy:
  resources:
    limits:
      memory: 512M
    reservations:
      memory: 256M

MODE=BACKEND (Heavy Processing)

environment:
  JAVA_CUSTOM_OPTS: "-Xmx8g"
deploy:
  resources:
    limits:
      memory: 10G
    reservations:
      memory: 4G

Security Considerations

  1. MODE=BOTH: Backend not exposed externally (runs on internal port)
  2. MODE=BACKEND: API exposed directly - consider API authentication
  3. MODE=FRONTEND: Only serves static files - minimal attack surface

Enable security features:

environment:
  DOCKER_ENABLE_SECURITY: "true"
  SECURITY_ENABLELOGIN: "true"

Support


License

MIT License - See repository for full details