Skip to content

How to Deploy Stirling-PDF on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-host Stirling-PDF on a VPS with Docker — merge, split, OCR, compress and redact PDFs on your own server, with the default admin password changed and HTTPS in front.

Before you start
  • A VPS with 2 GB RAM (the ultra-lite image runs on less)
  • A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
  • A domain you can point at the server
  • Docker Engine + Compose installed (see the base guide below)
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What Stirling-PDF is

Stirling-PDF is a web app and REST API with more than 50 PDF tools: merge, split, rotate, convert to and from other formats, OCR, compress, redact, sign, add watermarks, and chain several of those into a pipeline. The point of running your own copy is where the files go. Online PDF tools upload your contracts and bank statements to someone else's server; Stirling-PDF processes them on yours.

It is a Java / Spring Boot application with a TypeScript front end. The licensing is open core: the MIT-licensed core runs without a licence key, while SSO, auditing and some other enterprise features are paid. Everything in this guide uses the free core.

One thing surprises people coming from older tutorials: login is on by default. A fresh container creates an admin account with a known password, which you change on first sign-in. That default is the reason this guide exists as more than one docker run line.

Server sizing

The catalog lists 2 GB of RAM as the minimum for the standard image. It is a Java application that also calls out to tools such as LibreOffice and an OCR engine for some operations, so memory use depends heavily on what you ask it to do: compressing a small PDF is cheap, converting a large office document or OCR'ing a long scan is not.

Upstream publishes three image variants, all from docker.stirlingpdf.com/stirlingtools/stirling-pdf:

Tag What it includes When to use it
latest All PDF features Most installs
latest-fat Everything plus extra fonts and conversion tools Best conversion fidelity, more disk
latest-ultra-lite Core features only Small VPS, fastest start, basic operations

On a 1 GB box, use latest-ultra-lite. Disk is modest: 10–20 GB covers the OS, the image and the settings volume, since processed files aren't kept.

Prepare the server

This guide assumes Docker Engine and the Compose plugin are installed, with a ufw firewall. If not, start with Docker & Compose on Ubuntu.

Open SSH and the proxy ports only; port 8080 stays on loopback:

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable
sudo ufw status verbose
Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)
Vultralso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $5.00/mo
Get Vultr (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install Stirling-PDF (Docker Compose)

The upstream Docker guide documents four bind mounts: /configs for settings and the user database, /logs, /pipeline for saved automations, and /usr/share/tessdata for extra OCR languages. This guide keeps the first three and leaves tessdata to the image, so the bundled OCR data stays in place; add that mount later only if you need more languages.

mkdir -p ~/stirling-pdf/stirling-data/{configs,logs,pipeline}
cd ~/stirling-pdf
cat > docker-compose.yml <<'YAML'
services:
  stirling-pdf:
    image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
    container_name: stirling-pdf
    restart: unless-stopped
    ports:
      # Loopback only: Caddy is the only way in from outside.
      - "127.0.0.1:8080:8080"
    volumes:
      - ./stirling-data/configs:/configs
      - ./stirling-data/logs:/logs
      - ./stirling-data/pipeline:/pipeline
    environment:
      SYSTEM_DEFAULTLOCALE: en-US
YAML
docker compose up -d

Java takes a little while to start. Wait until the web UI answers — with login enabled, the root URL either serves the app or redirects to the login page:

for i in $(seq 1 60); do
  code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/)
  case "$code" in 200|302) echo "Stirling-PDF is up ($code)"; break ;; esac
  sleep 5
done
case "$code" in 200|302) true ;; *) docker compose logs --tail 50; false ;; esac

First login: change the default password

Per the upstream docs, a fresh container starts with login enabled and a default admin account:

  • Username: admin
  • Password: stirling

Change this password immediately after first login. Anyone who can reach the instance before you do can sign in with those credentials, which is another reason to keep port 8080 on loopback and only expose the app through HTTPS once you're ready to log in straight away.

From the admin account you can add more users under the account settings. If you truly want a single-user tool with no authentication — for example, reachable only over a VPN — upstream lets you opt out with SECURITY_ENABLELOGIN=false. Don't do that on an instance with a public hostname.

HTTPS + domain

Point an A record such as pdf.example.com at the server and terminate TLS in front of 127.0.0.1:8080, following Automatic HTTPS with Caddy:

pdf.example.com {
    request_body {
        max_size 200MB
    }
    reverse_proxy 127.0.0.1:8080
}

The request_body block keeps Caddy from rejecting large uploads; pick a limit that matches the files you work with. Stirling-PDF has its own upload limit too: SYSTEM_MAXFILESIZE (in MB) appears in the upstream example Compose files. If Caddy runs as a container rather than on the host, 127.0.0.1 is the proxy's own loopback — put both services in one Compose project and use reverse_proxy stirling-pdf:8080.

Using it

The web UI lists the tools by category; files are processed and handed back to you, not stored. A few features worth knowing:

  • Pipelines (the "Automate" feature) chain operations — for example OCR, then compress, then add a watermark — and save them for reuse. Saved pipelines live in the /pipeline mount.
  • The REST API exposes the same operations, so scripts and other services can call it. The API documentation is linked from the project's README.
  • Language: SYSTEM_DEFAULTLOCALE sets the default UI language (for example de-DE or fr-FR); unset, it follows the browser.

Stirling-PDF pairs well with a document archive: clean up, merge or redact a file here, then file it in Paperless-ngx.

Securing it

  • Change admin / stirling on first login — this is the only mandatory step.
  • Keep login enabled on anything with a public hostname, and create individual accounts rather than sharing the admin login.
  • Keep the port on loopback. ss -ltnp | grep 8080 should show 127.0.0.1:8080.
  • Patch it. Upstream's update procedure is simply pulling the image again; do it on a schedule (see Upgrades).

Backups

Processed files aren't kept, so the only state is stirling-data: settings, the user database and an encryption key in configs, plus your saved pipelines. On start the container takes ownership of the mounted folders for its own user, and some files (the credential encryption key among them) are readable only by that user — so archive with sudo, or the backup silently misses them. Stop the container for a consistent copy, archive the directory, and start it again:

cd ~/stirling-pdf
docker compose stop
sudo tar czf stirling-pdf-$(date +%F).tar.gz docker-compose.yml stirling-data
docker compose start
sudo tar tzf stirling-pdf-$(date +%F).tar.gz | grep credential-encryption.key

Copy the archive off the server. Restoring is the reverse: extract it into ~/stirling-pdf on a new box and run docker compose up -d.

Upgrades

cd ~/stirling-pdf
docker compose pull
docker compose up -d

The latest tag moves with each release; your settings and accounts survive because they live in the bind mounts. Back up stirling-data first and read the release notes before a major version — upstream publishes a migration guide for the v1-to-v2 change, where several settings were renamed.

Troubleshooting

The page doesn't load right after starting. Give Java a minute; watch docker compose logs -f stirling-pdf for the startup message.

The container keeps restarting. Upstream's advice: check the logs, check free RAM and disk, and try the latest-ultra-lite image on limited hardware.

Permission errors on the mounted folders. The directories must exist and be writable by the container's user. Creating them before the first start, as above, avoids root-owned folders. Afterwards they belong to the container's user, so use sudo to read or copy them from the host.

Uploads fail on big files. Raise Caddy's request_body limit and, if needed, SYSTEM_MAXFILESIZE.

Verification + next steps

You're done when you can load https://pdf.example.com over a valid certificate, log in with your new admin password (the old one no longer works), merge two PDFs and download the result, and you have a copy of stirling-data off the box.

Next, save a pipeline for the operation you repeat most, and create accounts for anyone else who will use it. For hosts, see Best VPS for Self-Hosting.

Next steps

How to self-host Stirling-PDF →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.