# 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. |
||
|---|---|---|
| .. | ||
| build.sh | ||
| entrypoint.sh | ||
| nginx.conf | ||
| README.md | ||
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 featuresDOCKER_ENABLE_SECURITY- Enable authenticationPUID/PGID- User/Group IDsSYSTEM_MAXFILESIZE- Max upload size (MB)TESSERACT_LANGS- Comma-separated OCR language codesJAVA_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:
VITE_API_BASE_URLpoints to correct backend URL- Backend container is running and accessible
- Network connectivity between containers
Backend not starting (MODE=BOTH or BACKEND)
Check:
- Sufficient memory allocated (4GB recommended)
- Java heap size (
JAVA_CUSTOM_OPTS) - 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
- MODE=BOTH: Backend not exposed externally (runs on internal port)
- MODE=BACKEND: API exposed directly - consider API authentication
- MODE=FRONTEND: Only serves static files - minimal attack surface
Enable security features:
environment:
DOCKER_ENABLE_SECURITY: "true"
SECURITY_ENABLELOGIN: "true"
Support
- Documentation: https://docs.stirlingpdf.com
- GitHub Issues: https://github.com/Stirling-Tools/Stirling-PDF/issues
- Docker Hub: https://hub.docker.com/r/stirlingtools/stirling-pdf
License
MIT License - See repository for full details