Deployment guide

Paperless-ngx with Tika and Gotenberg

Overview

Paperless-ngx is a popular open source, self-hosted document management system: a searchable digital archive for your paperless office. Drop a document into the consume directory and Paperless indexes it, tags it and archives a searchable copy.

Stock Paperless-ngx handles PDFs and images through its OCR pipeline, but it cannot read Office documents on its own. This SecureAnyCloud image adds the two companion services that give it full Office document support, already installed, wired together and verified:

  • Apache Tika extracts the text and metadata from Office files.
  • Gotenberg converts Office files to PDF, so Paperless has a readable preview and thumbnail.

A Word, Excel, PowerPoint, OpenDocument or RTF file dropped into the consume directory arrives in Paperless as a fully searchable document with a rendered preview, exactly like a scanned PDF. There is nothing to configure: PAPERLESS_TIKA_ENABLED, PAPERLESS_TIKA_ENDPOINT and PAPERLESS_TIKA_GOTENBERG_ENDPOINT are already set and verified at build time.

What you get:

  • Paperless-ngx 3.0.5 installed from the official release tarball into /opt/paperless
  • Apache Tika Server 3.3.2 on OpenJDK 17, bound to loopback 127.0.0.1:9998
  • Gotenberg 8.34.0 with LibreOffice 24.2, bound to loopback 127.0.0.1:3000
  • Office ingestion pre-wired and verified: DOC, DOCX, XLS, XLSX, PPT, PPTX, PPSX, ODT, ODS, ODP, ODG and RTF
  • A bare-metal install with no containers: the granian application server serves the bundled Angular frontend on loopback :8000, a Celery worker and Celery beat scheduler run the background pipeline, and a consumer process watches the input folder
  • nginx as a reverse proxy on :80, the only public listener on the machine. Apache Tika and Gotenberg are internal services: they bind to loopback only, are reachable only by the Paperless workers on the same VM, and have no authentication of their own, so they are deliberately never exposed.
  • PostgreSQL as the database and Redis as the task broker
  • Application code, media archive, data directory, consume folder and search index under /opt/paperless, and the PostgreSQL data directory at /var/lib/postgresql
  • A dedicated 60 GiB data disk at /opt/paperless and a dedicated 20 GiB data disk at /var/lib/postgresql. Both are separate from the operating system disk, are captured into the image, are re-provisioned with every VM and can be resized independently.
  • The full tesseract OCR pipeline for scans and images
  • Per-VM administrator, PostgreSQL and Django secret-key credentials generated on the first boot of every VM, so two VMs launched from this image never share passwords. They are written to /root/paperless-ngx-gotenberg-tika-credentials.txt with mode 0600, readable only by root. No documents and no shared credentials ship in the image.
  • Nine systemd units, enabled and active
  • 24/7 SecureAnyCloud support

Prerequisites

  • An Azure subscription with permission to create virtual machines
  • An SSH key pair for the azureuser account
  • A network security group that allows inbound TCP 22 (SSH) and TCP 80 (HTTP) from your address
  • Standard_B2ms (2 vCPU, 8 GiB) is the recommended size and the minimum we support. This image runs Paperless, a Java service and a LibreOffice conversion engine together. On a 4 GiB VM they contend for memory during conversion. On Standard_B2ms the whole stack idles at roughly 1 GiB and leaves over 6 GiB free.
1

Deploy from the Azure Marketplace

In the Azure portal, choose Create a resource, search for Paperless-ngx with Tika and Gotenberg by SecureAnyCloud, and select Create.

Pick your resource group and region, then choose the Standard_B2ms size. For the authentication type, select SSH public key with the username azureuser. Allow inbound ports 22 and 80, then select Review + create.

2

Deploy from the Azure CLI

az group create --name paperless-rg --location eastus
az vm image terms accept --urn sac1647283583153:paperless-ngx-gotenberg-tika:default:latest
az vm create \
  --resource-group paperless-rg \
  --name paperless-vm \
  --image sac1647283583153:paperless-ngx-gotenberg-tika:default:latest \
  --size Standard_B2ms \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
az vm open-port --resource-group paperless-rg --name paperless-vm --port 80 --priority 1001
# Get the public IP address
az vm list-ip-addresses --resource-group paperless-rg --name paperless-vm \
  --query "[0].virtualMachine.network.publicIpAddresses[0].ipAddress" -o tsv
3

Connect and Retrieve Initial Credentials

First boot generates the per-VM credentials. Wait about a minute after the VM reports running, then connect:

ssh azureuser@<vm-ip>

Read the credentials file. It has mode 0600 and is owned by root, so you need sudo:

sudo cat /root/paperless-ngx-gotenberg-tika-credentials.txt

The file lists the per-VM administrator password, the PostgreSQL password and the URL for this VM:

paperless.url=http://<vm-ip>/ paperless.admin.user=admin paperless.admin.pass=<PAPERLESS_ADMIN_PASSWORD> paperless.db.name=paperless paperless.db.user=paperless paperless.db.pass=<generated per VM>

These values are unique to this VM. Store them in your password manager and treat the file as sensitive.

4

Confirm the Services Are Running

Nine systemd units make up this image. Check that all nine report active:

systemctl is-active postgresql redis-server tika gotenberg nginx \
  paperless-webserver paperless-task-queue paperless-scheduler paperless-consumer

Each line returns active. In order, the units are the database, the task broker, the Apache Tika text extraction service, the Gotenberg conversion service, the web front end, the Paperless application server, the Celery worker, the Celery scheduler and the directory consumer.

5

Check the Office Ingestion Services

Apache Tika and Gotenberg are what make Office documents work. Confirm that both are healthy:

curl -s http://127.0.0.1:9998/version; echo
curl -s http://127.0.0.1:3000/health; echo

Tika reports Apache Tika 3.3.2. Gotenberg returns a JSON health document with "status":"up" and, nested under details, the LibreOffice engine also up. Gotenberg uses LibreOffice to turn Office files into PDF.

6

The Internal Service Model

Both companion services are bound to the loopback interface and are not reachable from outside the VM. Confirm the bindings:

ss -ltn | grep -E ':(80|9998|3000)[[:space:]]'

Port 80 listens on 0.0.0.0 because nginx serves the Paperless web interface to your users. Ports 3000 and 9998 listen only on 127.0.0.1, so only the Paperless workers on this VM can reach Gotenberg and Tika.

This matters. Apache Tika Server and Gotenberg both ship without any authentication of their own, and an exposed document conversion endpoint is a well-known server-side request forgery and denial-of-service risk. Keeping them on loopback is the security model of this image.

Do not publish ports 9998 or 3000 in your network security group. Do not change the bind address in /etc/systemd/system/tika.service or /etc/systemd/system/gotenberg.service.

7

First Login to the Paperless Web Interface

Browse to http://<vm-ip>/. Paperless redirects you to the sign-in page.

Sign in as admin with the password from Step 3. The dashboard opens.

Change the administrator password from the user menu in the top right.

8

Import Your First Office Document

This is what the image is for. Copy any Word or Excel file into the consume directory, and Paperless picks it up automatically. From your workstation, run:

scp quarterly-report.docx azureuser@<vm-ip>:/tmp/
sudo install -o paperless -g paperless -m 0644 /tmp/quarterly-report.docx /opt/paperless/consume/

If you have no Office file to hand, create a real .docx on the VM and ingest that instead. It is a genuine Word document, not a renamed text file, so it exercises the same Tika and Gotenberg path that your own documents take:

python3 - <<'DOCX' import zipfile t = "Quarterly report for the sac paperless archive. Revenue is up and filing is automatic." ct = ('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">' '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>' '<Default Extension="xml" ContentType="application/xml"/>' '<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>' '</Types>') rels = ('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>' '</Relationships>') doc = ('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">' f'<w:body><w:p><w:r><w:t>{t}</w:t></w:r></w:p></w:body></w:document>') with zipfile.ZipFile("/tmp/quarterly-report.docx", "w", zipfile.ZIP_DEFLATED) as z: z.writestr("[Content_Types].xml", ct); z.writestr("_rels/.rels", rels) z.writestr("word/document.xml", doc) print("created /tmp/quarterly-report.docx") DOCX
sudo install -o paperless -g paperless -m 0644 /tmp/quarterly-report.docx /opt/paperless/consume/ echo "queued for ingestion"

The consumer notices the file within a few seconds. Paperless sends it to Apache Tika for the text and metadata and to Gotenberg for a PDF rendition, then indexes the result. The first conversion takes a little longer because LibreOffice has to start up.

Watch the task run in the log:

sudo journalctl -u paperless-task-queue -n 20 --no-pager

Refresh the Documents view in the browser. Your Office files are listed with rendered previews.

Open a document and select the Content tab. The text on the left is what Apache Tika extracted from the original Office file, and the page on the right is the PDF that Gotenberg rendered from it. Because the text is indexed, the document is full-text searchable.

You can confirm the same from the command line:

sudo -u paperless env -C /opt/paperless/src \
  PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf \
  /opt/paperless/.venv/bin/python manage.py shell -c " from documents.models import Document as D from pathlib import Path for d in D.objects.all().order_by('id'): ap = Path(d.archive_path) if d.archive_path else None print(f'id={d.id} {d.original_filename} text={len(d.content or \"\")} chars archive={ap.name if ap else \"-\"}') "

Each row shows the original Office filename, how many characters of text Tika extracted, and the PDF that Gotenberg produced.

9

Supported Formats

Through Tika and Gotenberg, this image ingests:

Format Extensions

Word .doc, .docx

Excel .xls, .xlsx

PowerPoint .ppt, .pptx, .ppsx

OpenDocument .odt, .ods, .odp, .odg

Rich text .rtf

Paperless's own pipeline continues to handle PDFs. Scans and photographs are OCRed with tesseract as normal.

This image does not ingest email files (.eml). Paperless renders emails to PDF with a headless browser engine, and no redistributable browser build is available for Ubuntu 24.04, so that route is not included. Email files placed in the consume directory are ignored and do not produce a failed task. Everything in the table above is fully supported.

10

The REST API

Paperless exposes a REST API that accepts the same credentials. Run these checks to see the access rules in action:

# The sign-in page is served without authentication curl -s -o /dev/null -w "login page: %{http_code}\n" http://127.0.0.1/accounts/login/
# Without credentials the API is rejected curl -s -o /dev/null -w "unauthenticated: %{http_code}\n" http://127.0.0.1/api/documents/
# With the admin credentials it returns 200 curl -s -o /dev/null -w "authenticated: %{http_code}\n" \
  -u "admin:<PAPERLESS_ADMIN_PASSWORD>" http://127.0.0.1/api/documents/

The login page returns 200, the unauthenticated API call returns 403, and the authenticated call returns 200.

11

Services and Operations

# Status of a single component systemctl status tika --no-pager | head -5
# Restart the whole application tier
sudo systemctl restart paperless-webserver paperless-task-queue paperless-scheduler paperless-consumer
# Logs
sudo journalctl -u paperless-consumer -n 30 --no-pager sudo journalctl -u gotenberg -n 30 --no-pager

Tuning for a larger VM. The image is sized for Standard_B2ms, so the Celery worker runs a single task worker and the Apache Tika heap is capped at 1 GiB. If you move to a larger size, raise PAPERLESS_TASK_WORKERS in /opt/paperless/paperless.conf and -Xmx in /etc/default/tika, then restart the affected services.

12

The Dedicated Data Disks

df -h /opt/paperless /var/lib/postgresql

/opt/paperless holds the application, the media archive, the consume folder and the search index. /var/lib/postgresql holds the database. Both are separate Azure managed disks captured into the image, so they are re-provisioned on every VM. You can grow them independently in the portal without touching the OS disk.

13

Enable HTTPS with Let's Encrypt

The image serves plain HTTP, so it works immediately on a bare IP address. For production, put a DNS name in front of it and add a certificate:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d paperless.your-domain.com

Certbot edits the nginx site in place and installs a renewal timer. Then add your hostname to PAPERLESS_CSRF_TRUSTED_ORIGINS in /opt/paperless/paperless.conf and restart paperless-webserver.

14

Backups and Maintenance

A complete backup is the PostgreSQL database plus the media archive:

sudo -u postgres pg_dump paperless | gzip > /var/backups/paperless-$(date +%F).sql.gz
sudo tar czf /var/backups/paperless-media-$(date +%F).tar.gz -C /opt/paperless media

Paperless also ships a document exporter that writes documents and metadata together in a portable form. See the upstream documentation for document_exporter.

Unattended-upgrades is enabled in this image and applies operating system security updates.

Scaling Beyond a Single VM

This image is a single-VM appliance. Paperless, PostgreSQL, Redis, Tika and Gotenberg all run together, which suits teams and departmental archives well.

To grow beyond one VM, move PostgreSQL to Azure Database for PostgreSQL and Redis to Azure Cache for Redis by editing the connection settings in /opt/paperless/paperless.conf. Because Tika and Gotenberg are plain HTTP services, you can also move them onto their own hosts and point to them with PAPERLESS_TIKA_ENDPOINT and PAPERLESS_TIKA_GOTENBERG_ENDPOINT. Keep them on a private network, because neither has authentication.

Support

SecureAnyCloud maintains this image and provides 24/7 support. Contact sales@secureanycloud.com with the Azure region, the VM size and the output of systemctl is-active for the affected service.

Deploy on Azure

Launch Paperless-ngx with Tika and Gotenberg on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure