<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Stirling-Pdf – Serverküche</title><link>https://serverkueche.de/en/tags/stirling-pdf/</link><description>Stirling-Pdf – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>en-US</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Thu, 10 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/en/tags/stirling-pdf/index.xml" rel="self" type="application/rss+xml"/><item><title>Stirling-PDF: The PDF Toolbox on Your Own Server</title><link>https://serverkueche.de/en/tutorials/stirling-pdf-toolbox/</link><pubDate>Thu, 10 Sep 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/en/tutorials/stirling-pdf-toolbox/</guid><description>Merge, compress, convert PDFs and make them searchable with OCR – locally instead of on online services: Stirling-PDF behind Traefik, with login.</description><content:encoded><![CDATA[<p>&ldquo;Merge PDF online&rdquo;, &ldquo;compress PDF free&rdquo; – for tasks like these you&rsquo;d usually upload your documents to some web service, often with confidential content. Stirling-PDF does the same on your own server: over 50 PDF tools, and your files never leave your control.</p>
<h2 id="what-are-we-building">What are we building?</h2>
<p>A complete PDF toolbox with <strong>Stirling-PDF v2.14.2</strong> behind <a href="/en/tutorials/traefik-reverse-proxy/">Traefik</a>, secured with a login. By the end you merge PDFs, compress and rotate them, convert between formats, make scanned documents searchable with <strong>OCR</strong>, redact content, add passwords or watermarks – all in the browser, all locally. Exactly the right tool to prepare documents from <a href="/en/tutorials/self-host-paperless-ngx/">Paperless</a> or <a href="/en/tutorials/self-host-nextcloud/">Nextcloud</a>.</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>A server with <a href="/en/tutorials/traefik-reverse-proxy/">Traefik</a> running and <a href="/en/tutorials/docker-compose-basics/">Docker Compose</a></li>
<li>A <a href="/en/tutorials/connect-domain-to-server/">subdomain pointing at the server</a> – <code>YOUR_DOMAIN</code> below</li>
</ul>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /en/tutorials/stirling-pdf-toolbox/" data-content-piece="VPS 1000 G12">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Recommendation</span>
    <span title="Links marked with * are affiliate links.">Ad</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCores · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">from €10.36/month</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Stirling-PDF runs well on a small VPS; only OCR of large files wants more RAM.</p>
    </div>
    <a href="https://www.netcup.com/en/server/vps/vps-1000-g12-iv-12m?ref=44083" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 1000 G12 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Go to netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € voucher</strong> for new netcup customers:</span><code data-track-voucher="36nc17844976032"
        class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(new customers only, no domains)</span>
</p></div>
</div>

<h2 id="step-by-step">Step by step</h2>
<h3 id="step-1-project-and-compose-file">Step 1: Project and Compose file</h3>
<p>Stirling-PDF is stateless at its core – it processes files and returns them without storing them permanently. Only configuration and OCR language data live in volumes. Create the project:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir -p /opt/stirling/data /opt/stirling/configs <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/stirling</span></span></code></pre></div>
</div>
<p>The <code>compose.yaml</code> – replace <code>YOUR_DOMAIN</code>:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">stirling-pdf</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">stirlingtools/stirling-pdf:2.14.2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">./data:/usr/share/tessdata  </span><span class="w"> </span><span class="c"># OCR language data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">./configs:/configs          </span><span class="w"> </span><span class="c"># configuration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">LANGS</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;en_GB&#39;</span><span class="w">                  </span><span class="c"># UI language</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">proxy]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.enable=true&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.stirling.rule=Host(`YOUR_DOMAIN`)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.stirling.entrypoints=websecure&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.stirling.tls.certresolver=le&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.services.stirling.loadbalancer.server.port=8080&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">networks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">proxy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">external</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span></span></span></code></pre></div>
</div>
<h3 id="step-2-start-and-wait-for-healthy">Step 2: Start and wait for &ldquo;healthy&rdquo;</h3>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose up -d</span></span></code></pre></div>
</div>
<p>The image ships its own health check, and Traefik only routes to the container once it&rsquo;s <code>healthy</code> – which takes about 20–30 seconds after start (the Java application needs a moment). Check:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose ps</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">NAME                      IMAGE                              STATUS
</span></span><span class="line"><span class="cl">stirling-stirling-pdf-1   stirlingtools/stirling-pdf:2.14.2  Up (healthy)</span></span></code></pre></div>
</div>
<h3 id="step-3-first-login-and-forced-password-change">Step 3: First login and forced password change</h3>
<p>Open <code>https://YOUR_DOMAIN/</code>. Stirling-PDF v2 is protected by a login by default – an important difference from many other tools, and one you shouldn&rsquo;t disable if the service is publicly reachable.</p>
<p><figure class="my-6"><img src="/en/tutorials/stirling-pdf-toolbox/sp-login_hu_9e8c58ea593452e.webp" srcset="/en/tutorials/stirling-pdf-toolbox/sp-login_hu_abef7d403aa2c77a.webp 480w, /en/tutorials/stirling-pdf-toolbox/sp-login_hu_9e8c58ea593452e.webp 768w, /en/tutorials/stirling-pdf-toolbox/sp-login_hu_a65b0493c8b03bdd.webp 1200w, /en/tutorials/stirling-pdf-toolbox/sp-login_hu_7f0e1da46b4bad7c.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/stirling-pdf-toolbox/sp-login_hu_3b0aef3adb59e34e.webp"
    alt="The Stirling-PDF login page with fields for username and password" title="The login protects the toolbox – on by default in Stirling-PDF v2"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">The login protects the toolbox – on by default in Stirling-PDF v2</figcaption></figure></p>
<p>Log in with the default credentials <strong><code>admin</code> / <code>stirling</code></strong>. On first login Stirling-PDF immediately <strong>forces</strong> a password change – good. Set a strong password; then log in again with the new one.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Change the default credentials immediately
  </p>
  <div class="prose-kitchen text-sm"><code>admin</code>/<code>stirling</code> are publicly known. As long as this password is in effect, your toolbox is open to anyone who knows the domain. The forced change on first login is intentional – don&rsquo;t skip it, and choose a real password.</div>
</div>
<h3 id="step-4-the-toolbox">Step 4: The toolbox</h3>
<p>After login you see the interface: your files on the left, the full tool catalog on the right, grouped into categories like Signing, Document security and Verification.</p>
<p><figure class="my-6"><img src="/en/tutorials/stirling-pdf-toolbox/sp-tools_hu_81e0be9b55818aba.webp" srcset="/en/tutorials/stirling-pdf-toolbox/sp-tools_hu_35a4dceccb6f443b.webp 480w, /en/tutorials/stirling-pdf-toolbox/sp-tools_hu_81e0be9b55818aba.webp 768w, /en/tutorials/stirling-pdf-toolbox/sp-tools_hu_adbc225e971ed613.webp 1200w, /en/tutorials/stirling-pdf-toolbox/sp-tools_hu_261c037580b0e2bc.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/stirling-pdf-toolbox/sp-tools_hu_f4c0f572125af27b.webp"
    alt="The Stirling-PDF interface with an upload area in the center and the tool catalog on the right" title="Over 50 tools grouped by task – merge, compress, convert, OCR and more"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Over 50 tools grouped by task – merge, compress, convert, OCR and more</figcaption></figure></p>
<p>Getting started is always the same: load a PDF via <strong>Upload from computer</strong> (or drag &amp; drop), then pick the tool you want on the right. The file appears in the built-in viewer:</p>
<p><figure class="my-6"><img src="/en/tutorials/stirling-pdf-toolbox/sp-file_hu_c5cc3c7895191886.webp" srcset="/en/tutorials/stirling-pdf-toolbox/sp-file_hu_85c7e574cf5a5182.webp 480w, /en/tutorials/stirling-pdf-toolbox/sp-file_hu_c5cc3c7895191886.webp 768w, /en/tutorials/stirling-pdf-toolbox/sp-file_hu_4d0ff60ec82a904b.webp 1200w, /en/tutorials/stirling-pdf-toolbox/sp-file_hu_5f429ea55ef0bf5d.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/stirling-pdf-toolbox/sp-file_hu_d9cc7fb9b0b31642.webp"
    alt="A loaded PDF in the Stirling-PDF viewer with page navigation and the tool catalog beside it" title="A loaded PDF in the viewer – on the right you pick the tool to apply to it"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">A loaded PDF in the viewer – on the right you pick the tool to apply to it</figcaption></figure></p>
<p>The most useful tools in everyday use:</p>
<ul>
<li><strong>Merge / Split:</strong> combine multiple PDFs into one or separate out pages.</li>
<li><strong>Compress:</strong> reduce file size for sending by email.</li>
<li><strong>Convert:</strong> PDF ↔ image, Word/Office → PDF and back.</li>
<li><strong>OCR &amp; clean scans:</strong> make scanned documents searchable (that&rsquo;s what the <code>tessdata</code> language data is for).</li>
<li><strong>Redact:</strong> permanently remove confidential parts – not just paint over them in black.</li>
</ul>
<h3 id="step-5-add-ocr-languages-optional">Step 5: Add OCR languages (optional)</h3>
<p>For OCR in a given language, Stirling-PDF needs the matching Tesseract language data. The official image ships common languages; if one is missing, drop the corresponding <code>.traineddata</code> file into the mounted <code>data</code> folder (<code>/usr/share/tessdata</code>). After that the language is available in the OCR tool.</p>
<h2 id="when-things-go-wrong">When things go wrong</h2>
<div class="troubleshoot not-prose">
<p><strong>The page doesn&rsquo;t load (Traefik 404) even though the container is running.</strong> The health check isn&rsquo;t <code>healthy</code> yet – Traefik deliberately doesn&rsquo;t route then. Wait 20–30 seconds after start; check the status with <code>docker inspect -f '{{.State.Health.Status}}' stirling-stirling-pdf-1</code>.</p>
<p><strong>Login with <code>admin</code>/<code>stirling</code> fails.</strong> Either the password was already changed (then use the new one), or the config in the <code>configs</code> volume is inconsistent. To reset, stop the app and check the user config in the <code>configs</code> folder; if in doubt clear the folder (note: this resets all settings).</p>
<p><strong>OCR can&rsquo;t find my language.</strong> The matching <code>.traineddata</code> is missing from the <code>tessdata</code> volume. Get the file from the Tesseract language packs and place it in the <code>data</code> folder (see step 5).</p>
<p><strong>A conversion (e.g. Office → PDF) fails.</strong> Such conversions need extra tools (LibreOffice) that are only included in the larger image variants. For the full feature set use the <code>-fat</code> variant of the image (<code>stirlingtools/stirling-pdf:2.14.2-fat</code>).</p>
<p><strong>Large files cause errors or long waits.</strong> OCR and conversion are memory-intensive. On a small VPS RAM can run short – then either process smaller files or move to a larger product.</p>

</div>

<h2 id="maintenance--backups">Maintenance &amp; backups</h2>
<ul>
<li><strong>Updates.</strong> Occasionally bump the image tag (<code>stirlingtools/stirling-pdf:2.14.2</code>) to the current version and <code>docker compose up -d</code>. Stirling-PDF is actively developed and gets new tools frequently; a look at the release notes is worthwhile. The rest runs through your normal <a href="/en/tutorials/keep-docker-stack-updated/">update process</a>.</li>
<li><strong>The backup is small.</strong> Because the file processing is stateless, you only need to back up the <code>configs</code> folder (login, settings) and any custom OCR language data – best with <a href="/en/tutorials/restic-backups/">Restic</a>. You store the processed PDFs yourself anyway.</li>
<li><strong>Security.</strong> The login is the first line of defense – keep the admin password strong and current. Since potentially confidential documents pass through here, running behind HTTPS (Traefik) and a login is mandatory; a publicly reachable Stirling-PDF without a password would be a serious data leak.</li>
</ul>
]]></content:encoded></item></channel></rss>