Fully verified91,063

Documents

Stirling PDF

Stirling PDF combines editing, conversion, OCR, compression, signing, and automated PDF processing in one web interface. This recipe makes authentication mandatory, uses local H2, and binds to localhost, so documents never need to reach a cloud service.

Alternative to Adobe AcrobatAlternative to SmallpdfAlternative to iLovePDFLicenseRef-Stirling-PDF-User-LicenseVersion 2.14.3

Overview

Stirling PDF is a web suite of more than 60 PDF operations: merging and splitting, editing, OCR, office-format conversion, compression, signing, metadata editing, and automation pipelines. It suits personal or small internal document workflows that would otherwise send files to Adobe Acrobat Online, Smallpdf, or iLovePDF. An official desktop client can connect to a self-hosted server.

The recipe runs the pinned 2.14.3 standard image with mandatory authentication and embedded H2, and the interface defaults to English — one variable switches it. Settings, users, and H2 persist in /configs; branding lives under /customFiles, automation under /pipeline, and OCR data under /usr/share/tessdata. External PostgreSQL is omitted because upstream classifies custom databases as paid Server/Enterprise functionality.

Security and licensing

The full application smoke test has passed on amd64; backup and restore remain untested in practice. Authentication is enabled, while URL-to-PDF, analytics, PostHog, Scarf, and search-engine indexing are disabled. Complex PDF and office files remain untrusted input that can attack parsers or exhaust resources.

Stirling PDF is open-core, not wholly MIT. The standard image contains parts under the Stirling PDF User License, which restricts production, commercial, and client-facing use without a subscription. Upstream also advertises a Free tier for up to five users; because the interaction is unclear, obtain written confirmation of applicable rights before production use.

Update tracking

These are stored results of separate checks, not real-time data. An unknown status means the check has not been performed yet.

New releases

Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.

Current version 2.14.3Sep 1, 2026, 12:21 AM UTC

Critical vulnerabilities

Result of a dedicated Docker image scan, not a Compose configuration check.

Not checkedNot checked

Breaking updates

A new major version is found by comparing version numbers. A compatibility verdict is entered by hand after reading the release notes and the migration steps.

Not checkedNot checked

compose.yaml

Upstream Compose changes relative to the verified recipe.

Upstream Compose is not trackedNot checked

Outdated Docker images

Pinned image tags checked for newer versions.

Not checkedNot checked

From observation to action

Update plan

The recipe already pins the latest known release. The steps below show the evidence retained for that version.

2.14.32.14.3
  1. Open the release evidence

    Open this release on GitHub ↗ The link is evidence to review, not proof of compatibility.

  2. Review the version boundary

    The version numbers do not cross a major compatibility boundary. No compatibility verdict has been recorded.

  3. Prepare image-tag changes

    No image-tag change is currently planned.

  4. Follow the documented migration shape

    Manual steps after the pull. Release-specific migration steps still come from the release notes and installation guide.

  5. Protect the rollback point

    No version change is currently planned. The recipe includes a backup procedure. Restore has not been tested.

  6. Verify the updated recipe

    An exact Fully verified check for this target was recorded on 2026-09-03.

Read the update procedure in the installation guide ↓

Specifications

Security and exposure

Installation levels

The status shows how fully the published recipe meets each level's requirements.

Partial

For home

A minimal setup for a local network or access through a VPN.

  • Single server
  • Local access
  • Minimum components

You still need to add: single server, local access, minimum components.

Partial

For a VPS

A public deployment with protected access and backups.

  • Domain
  • HTTPS via reverse proxy
  • Off-server backup

You still need to add: domain, https via reverse proxy, off-server backup.

Partial

Reliable

A setup designed for predictable operations and observability.

  • Separate database
  • Healthcheck
  • External monitoring
  • CPU and memory limits

You still need to add: separate database, external monitoring, cpu and memory limits.

Tailored to your server

Configuration generator

Answer five questions and download a ready-to-run Stirling PDF bundle.

Runs locally
01 Do you have a domain?
02 Which reverse proxy?
03 Server architecture
04 Where should data be stored?

Use an absolute path for a separate disk, such as /srv/stirling-pdf.

05 Is VPN access required?

Your bundle is ready

The archive is created in your browser. Your answers are never sent anywhere.

Screenshots

Screenshots have not been added yet.

Quick start

Read the full guide first: it explains external access, backups, and data locations.

Prepare settingscp .env.example .env
Launchdocker compose up -d
Check statusdocker compose ps

Step-by-step guide

1. Check the Ubuntu or Debian server

Use Ubuntu 22.04+ or Debian 12+ with Docker Engine and Compose v2.24+. Allocate at least 2 CPUs, 2 GB RAM, and 10 GB disk; 4 GB RAM is recommended. OCR, LibreOffice, and large PDFs can briefly consume more CPU, RAM, and temporary space.

docker --version
docker compose version

2. Prepare the recipe and required credentials

mkdir -p ~/services/stirling-pdf
cd ~/services/stirling-pdf
cp .env.example .env
chmod 600 .env
mkdir -p data/{configs,customFiles,pipeline,tessdata}
sed -i "s|^STIRLING_PDF_INITIAL_PASSWORD=.*|STIRLING_PDF_INITIAL_PASSWORD=$(openssl rand -base64 36 | tr -d '\n')|" .env

Before the first start, replace STIRLING_PDF_INITIAL_USERNAME and save the generated password in a secret manager. Initial-login variables are consumed only while H2 is created; editing .env later does not reset the password. This recipe never uses the upstream admin/stirling default.

Every .env variable:

  • STIRLING_PDF_PORT is the local web port, normally 8080;
  • STIRLING_PDF_URL is the exact public origin with a scheme, no trailing /, and no path; it becomes the frontend URL, backend URL, and sole CORS origin;
  • STIRLING_PDF_DATA_PATH is the root of four bind-mounted directories;
  • STIRLING_PDF_INITIAL_USERNAME and STIRLING_PDF_INITIAL_PASSWORD are required non-default first-administrator credentials;
  • STIRLING_PDF_DEFAULT_LOCALE is the UI locale, default en-GB; ru-RU and the other supported locales work too;
  • STIRLING_PDF_UPLOAD_LIMIT_MB is a defensive file and request limit from 1 to 999 MB;
  • STIRLING_PDF_BACKUP_DIR selects the host archive directory.

configs holds settings, users, and the stirling-pdf-DB-<schema-version>.mv.db H2 file; customFiles holds branding and signatures; pipeline holds automations and watched folders; tessdata holds OCR languages. Read logs with docker compose logs: persistent /logs is not needed for recovery and is deliberately omitted.

3. Start and change the password

docker compose config
docker compose pull
docker compose up -d --wait
curl --fail http://127.0.0.1:8080/api/v1/info/status

Open STIRLING_PDF_URL, sign in with the initial credentials, and immediately change the password in account settings. Authentication is enabled. Analytics, PostHog, Scarf, Google visibility, and URL-to-PDF are disabled; the health endpoint remains reachable without login. Do not expose the service until login has been verified.

VPS deployment

Keep 127.0.0.1:${STIRLING_PDF_PORT}:8080, allow only SSH, HTTP, and HTTPS in the firewall, and expose the app through a proxy on the same host. Set the real HTTPS origin in STIRLING_PDF_URL, DNS, and proxy before first startup. H2 fits this free single-container recipe; do not add external PostgreSQL as an “improvement” without an applicable paid licence.

Trusted LAN access

Prefer a VPN or ssh -L 8080:127.0.0.1:8080 user@server; temporarily set STIRLING_PDF_URL=http://localhost:8080 for that tunnel. For permanent LAN access, replace only 127.0.0.1 in Compose with a specific private address, set the matching origin, and restrict the port by firewall. Do not use 0.0.0.0 without filtering.

Domain and HTTPS

Set STIRLING_PDF_URL=https://pdf.example.com without a path or trailing slash, replace the domain in proxy/Caddyfile, proxy/nginx.conf, or proxy/traefik.yaml, and recreate the container. Caddy obtains a certificate, Nginx expects Certbot, and Traefik uses the letsencrypt resolver. Preserve Host, X-Forwarded-Proto, and client addresses, and keep the proxy upload limit aligned with STIRLING_PDF_UPLOAD_LIMIT_MB. A containerized proxy cannot reach host localhost; use a reachable host gateway or shared Docker network.

Backup

chmod +x backup.sh restore.sh smoke-test.sh
./backup.sh

The script stops Stirling PDF so H2 cannot change while it archives configs, customFiles, pipeline, and tessdata together, then restarts the container. The archive contains H2 users and sensitive settings: encrypt it, copy it off the server, and test restores regularly. Input and temporary PDFs are normally deleted and are not backed up. Copy any separately allowed pipeline directories outside STIRLING_PDF_DATA_PATH yourself.

Restore

Restore irreversibly replaces all four directories. Put the same 2.14.3 version in Compose, retain the active .env, verify free space, and run:

./restore.sh ./backups/stirling-pdf-YYYYMMDDTHHMMSSZ.tar.gz
docker compose ps
curl --fail http://127.0.0.1:8080/api/v1/info/status

The script saves the replaced state in an emergency archive, restores the stopped snapshot, and waits for health. The procedure has restore_tested: false; test a copy on another server first and verify login, settings, custom files, and pipelines.

Update

Back up first and read the new release notes, migration guide, and licence. Replace only the exact stirlingtools/stirling-pdf:2.14.3 tag with a reviewed semantic version, never latest, then run:

docker compose pull
docker compose up -d --wait
docker compose logs --tail=200 stirling-pdf
curl --fail http://127.0.0.1:8080/api/v1/info/status

Startup may migrate H2 and create a file with a new schema version. Review major releases, persistent-path changes, and the User License separately.

Rollback

Never run an old image over already migrated H2. Stop the container, restore the old exact tag, and restore the complete pre-update archive with restore.sh. H2 has no supported downgrade: migration rollback means returning synchronized configs, customFiles, pipeline, and tessdata. Without a backup, preserve the current state and contact upstream instead of renaming H2 files manually.

Stop and remove

docker compose down preserves bind-mounted data. After verifying an external backup, remove everything irreversibly:

docker compose down
rm -rf ./data ./backups .env

Sources: Docker installation, configuration, production, health, and backup, analytics, modes and licensing, and the 2.14.3 licence.

Troubleshooting

Stirling PDF does not become healthy

docker compose ps
docker compose logs --tail=200 stirling-pdf
docker inspect --format '{{json .State.Health}}' "$(docker compose ps -q stirling-pdf)"
curl -v http://127.0.0.1:8080/api/v1/info/status

The endpoint must return JSON with status: UP. First startup is slower while H2 and tools are prepared. Verify 2 GB RAM, free disk space, port 8080, and permissions on all four data directories.

Initial credentials are rejected

SECURITY_INITIALLOGIN_* applies only while the first database is created. If configs already contains stirling-pdf-DB-*.mv.db, editing .env does not change that user. Do not delete H2 with settings and users: restore a known backup or use an upstream-supported reset procedure. Ensure .env has no CHANGE_ME and inspect interpolation with docker compose config.

STIRLING_PDF_URL must exactly match the browser origin: scheme, domain, and optional port, with no path or trailing /. Run docker compose up -d --force-recreate after changing it. Verify proxy Host and X-Forwarded-Proto. This recipe supports root /, not a subpath.

Uploads return 413 or disconnect

Align STIRLING_PDF_UPLOAD_LIMIT_MB with Nginx client_max_body_size or Caddy request_body max_size. Check temporary space and RAM: processing can need several times the source file size. Do not remove limits from a public service without resource controls.

OCR is missing a language

Inspect data/tessdata and logs. Every image variant may not bundle the required traineddata; add only an official Tesseract tessdata file to the mounted directory. Do not switch away from the standard image without rechecking features and architecture support.

H2 errors after an update

Do not run an old image over a new schema or rename stirling-pdf-DB-<schema-version>.mv.db. Preserve the failed configs, restore the old tag and complete pre-update archive through restore.sh. Without a backup, stop the container and request upstream migration guidance.

The reverse proxy returns 502

On the host, run curl http://127.0.0.1:8080/api/v1/info/status, then inspect the upstream, timeouts, and proxy network namespace. Inside a container, 127.0.0.1 refers to that proxy, not Stirling PDF on the host.

Official sources

Latest release: 2026-08-06 · GitHub Stars: 91,063 · metadata checked Sep 1, 2026, 12:21 AM UTC

Disclaimer

Fossary is an independent informational catalog and is not affiliated with the developers of the listed applications. We collect information from public sources and verify published recipes, but we do not develop, distribute, or control these applications.

A listing or validation status is not a requirement, endorsement, or personal recommendation to use an application. You decide whether it is suitable and use it at your own risk. We do not warrant an application's security, availability, or fitness for purpose and, to the extent permitted by law, are not liable for resulting loss or damage. Review its license, security settings, data processing, and backup procedures before installation.