Deployment guide

Paperless-ngx

Videos

Overview: Paperless-ngx on Ubuntu 24.04 LTS on Azure: overview (watch on YouTube)

Launch and log in: Paperless-ngx on Ubuntu 24.04 LTS on Azure: launch and log in (watch on YouTube)

Deep Dive: Paperless-ngx on Ubuntu 24.04 LTS on Azure: deep dive (watch on YouTube)

Overview

Paperless-ngx is the popular open source document management system: a self-hosted, searchable digital archive for your paperless office. Drop a scan or PDF into the consume directory and Paperless OCRs it, extracts the text, tags and indexes it, then archives a searchable original.

Paperless-ngx is the popular open source document management system: a self-hosted, searchable digital archive for your paperless office. Drop a scan or PDF into the consume directory and Paperless runs OCR on it, extracts the text, tags and indexes it, then archives a searchable original.

This SecureAnyCloud image runs Paperless-ngx bare metal behind nginx, with PostgreSQL, Redis and the full OCR pipeline on the same VM. Administrator and database credentials are generated on the first boot of every VM, so no two deployments share a password. No documents and no shared credentials ship in the image.

What you get:

  • Paperless-ngx 2.20 installed from the official release tarball into /opt/paperless
  • The granian application server on loopback :8000 serving the bundled Angular frontend, behind an nginx reverse proxy on :80
  • A Celery worker and a Celery beat scheduler for the background task pipeline, plus a consumer process that watches an input folder for new documents
  • PostgreSQL database on a dedicated 20 GiB data disk at /var/lib/postgresql
  • Application, media archive, consume folder and search index on a dedicated 60 GiB data disk at /opt/paperless
  • Redis as the Celery task broker. PostgreSQL and Redis are bound to the loopback interface only.
  • The full tesseract OCR pipeline, built on tesseract, Ghostscript and OCRmyPDF, so scanned PDFs and images become fully text searchable on import
  • Per-VM administrator, database and secret-key credentials generated at first boot, including a fresh Django secret key. The administrator and PostgreSQL passwords are written to /root/paperless-ngx-credentials.txt with mode 0600, so only root can read them.
  • Separate Azure data disks, apart from the operating system disk: the Paperless application code, document media archive, data directory, consume folder and search index live under /opt/paperless, and the PostgreSQL data directory sits at /var/lib/postgresql. Both disks are captured into the image, re-provisioned with every VM you deploy, and can be resized independently.
  • Seven systemd units enabled and active
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2ms (2 vCPU / 8 GiB RAM) is the recommended starting size. The OCR pipeline is processor and memory heavy, and document throughput benefits from both.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network. Also allow 80/tcp from the networks your users will reach Paperless on, plus 443/tcp once you enable HTTPS.

1

Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Paperless-ngx by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

Review the two dedicated data disks on the Disks tab, then select Review + create and Create. First boot initialisation takes approximately one to three minutes after the VM starts.

2

Deploy from the Azure CLI

Replace the resource group, image reference, VNet and subnet with your own values:

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:paperless-ngx-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name paperless \
  --image sac1647283583153:paperless-ngx-ubuntu-24-04:default:latest \
  --size Standard_B2ms \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name paperless --port 80 --priority 1010

First boot takes a few minutes. On first boot the VM finishes its per-VM setup in the background. It generates the VM's own credentials and starts the services. If you connect as soon as the VM shows as running, wait for that setup to finish before you continue:

Run sudo cloud-init status --wait in your SSH session.

The command prints status: done when the VM is ready. The credentials and services described below exist only after that.

3

Connect and retrieve the initial credentials

Connect over SSH with the key pair you supplied at deploy time:

ssh azureuser@<vm-public-ip>

The per-VM administrator and PostgreSQL passwords are written to a root-only file. Read the file with sudo:

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

The file lists the Paperless administrator username (admin) and password, the database name, user and password, and the URL of the web interface. Store these somewhere safe.

4

Confirm the services are running

The image runs seven systemd units. Confirm that all of them are active:

systemctl is-active postgresql redis-server nginx \
  paperless-webserver paperless-task-queue paperless-scheduler paperless-consumer curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/accounts/login/

All seven units report active, and the sign-in page returns 200.

5

Understand the trusted host model

Django, the web framework Paperless is built on, serves only requests whose Host header it trusts. It also accepts form posts only from trusted origins.

On first boot the VM adds its own public and private addresses to PAPERLESS_URL and PAPERLESS_CSRF_TRUSTED_ORIGINS in /opt/paperless/paperless.conf. The web interface is therefore reachable immediately on the VM's launch address. If you put Paperless behind a custom domain or a load balancer, add that hostname too and restart the webserver:

sudo sed -i 's|^PAPERLESS_URL=.*|PAPERLESS_URL=https://paperless.your-domain.example|' /opt/paperless/paperless.conf
sudo systemctl restart paperless-webserver
6

Sign in to the Paperless web interface

Browse to http://<vm-public-ip>/. Paperless opens its sign-in page. Enter the administrator username (admin) and the administrator password from /root/paperless-ngx-credentials.txt, then select Sign in.

After you sign in, you reach the Dashboard, which shows saved views and statistics. The Documents list is the heart of the platform: every document you import is processed with OCR, tagged and made full text searchable there.

For a production deployment, rotate the administrator password that was generated on first boot. Open My Profile from the user menu and change it there.

7

Import and OCR your first document

Paperless imports documents by watching a consume directory. The consumer picks up anything you drop into /opt/paperless/consume, runs OCR, indexes it and archives it automatically.

Copy a PDF or scanned image into the directory with sudo cp <your-file>.pdf /opt/paperless/consume/. Then make the paperless user the owner with sudo chown paperless:paperless /opt/paperless/consume/<your-file>.pdf.

Within a few seconds the consumer hands the file to a Celery worker, which runs OCR and indexing. The file then leaves the consume directory and appears in the Documents list in the web interface, with its extracted text searchable. Check the pipeline's recent activity at any time:

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

Scanners and network shares can write straight into /opt/paperless/consume over NFS, SMB or scp. This is the usual way to feed a paperless office.

8

The REST API

Paperless exposes a full REST API under /api/. The API requires authentication, while the sign-in page itself is open. Verify both with curl. The unauthenticated request is rejected and the authenticated one succeeds:

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

For automation and integrations, issue a long-lived API token from My Profile in the web interface and pass it as Authorization: Token <token>.

9

Organise with tags, correspondents and document types

Paperless organises documents with tags, correspondents (who a document is from), document types (invoice, contract, payslip) and storage paths. Create these from the left-hand menu.

Then build matching rules so Paperless applies them automatically on import. For example, tag everything from a given correspondent, or match documents whose OCR text contains a keyword. Pin the searches you run most as saved views on the dashboard.

10

Manage services and run commands

The paperless-webserver unit runs the granian application server on 127.0.0.1:8000, and nginx reverse proxies port 80 to it. The paperless-task-queue and paperless-scheduler units are the Celery worker and beat scheduler. The paperless-consumer unit watches the consume directory.

Confirm the runtime versions:

/opt/paperless/.venv/bin/python -c 'import django; print("Django", django.get_version())' ls -ld /opt/paperless/src /opt/paperless/.venv /opt/paperless/media

Run Paperless management commands as the paperless user, with the configuration path set:

sudo -u paperless PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf \
  /opt/paperless/.venv/bin/python /opt/paperless/src/manage.py <command>
11

Check the dedicated data disks

The PostgreSQL database tier and the Paperless application and data tier each live on their own Azure data disk. Both disks are separate from the OS disk and captured into the image, so every VM you deploy is provisioned with both. Confirm the mounts:

findmnt -no SOURCE,SIZE,FSTYPE,TARGET /var/lib/postgresql
findmnt -no SOURCE,SIZE,FSTYPE,TARGET /opt/paperless

The database disk mounts at /var/lib/postgresql (20 GiB) and the data disk at /opt/paperless (60 GiB). As your archive grows, resize either disk independently in the Azure Portal. Then grow the filesystem with sudo resize2fs on the corresponding device.

12

Enable HTTPS with Let's Encrypt

For any production deployment, serve the site over HTTPS so that session cookies and document transfers cannot be intercepted. The image ships with nginx, which certbot can configure automatically.

This procedure assumes the following:

  • A DNS record points your fully qualified domain name at the VM's public IP address
  • An NSG rule allows 443/tcp
  • You have added the domain to PAPERLESS_URL and PAPERLESS_CSRF_TRUSTED_ORIGINS (step 5)
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d paperless.your-domain.example \
  --non-interactive --agree-tos -m you@your-domain.example \
  --redirect

After certbot finishes, point Paperless at the HTTPS URL so that it generates correct links and trusts the origin:

sudo sed -i 's|^PAPERLESS_URL=.*|PAPERLESS_URL=https://paperless.your-domain.example|' /opt/paperless/paperless.conf
sudo systemctl restart paperless-webserver
13

Back up and maintain Paperless

Back up two things together: the PostgreSQL database and the document store under /opt/paperless/media. The cleanest backup is Paperless's own document exporter, which writes a self-contained, importable archive:

sudo mkdir -p /var/backups/paperless && sudo chown paperless:paperless /var/backups/paperless
sudo -u paperless PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf \
  /opt/paperless/.venv/bin/python /opt/paperless/src/manage.py document_exporter /var/backups/paperless
sudo ls /var/backups/paperless

Copy the export directory to Azure Blob Storage or another object store. Because the data and database tiers are on their own data disks, you can also take coordinated Azure disk snapshots. The scheduler runs Paperless's periodic tasks, such as email checking and index optimisation, automatically.

Ubuntu's unattended-upgrades is enabled, so kernel and package security patches apply automatically. To update Paperless itself, follow the upgrade workflow in the official documentation at https://docs.paperless-ngx.com/.

Scaling beyond a single VM

For larger deployments, decouple Paperless from the single-VM pattern:

  • Move PostgreSQL to Azure Database for PostgreSQL and update the database host in /opt/paperless/paperless.conf
  • Move the document store to Azure Blob Storage mounted via BlobFuse, or to Azure Files
  • Move Redis to Azure Cache for Redis and point PAPERLESS_REDIS at the cache endpoint
  • Put the web tier behind Azure Application Gateway, add the gateway hostname to the trusted origins, and run the Celery workers on dedicated VMs

The official Paperless-ngx documentation at https://docs.paperless-ngx.com/ covers each of these.

Support

This image is backed by 24/7 SecureAnyCloud support, with a response within 24 hours and a one-hour average for critical issues. Contact sales@secureanycloud.com for help with deployment, upgrades, OCR language configuration, consume-folder automation, TLS termination and database administration.

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch Paperless-ngx 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