Paperless-ngx: Automated Workflows, OCR Optimization, and Custom Rules (Part 2)
Take control of your document management. Optimize OCR settings, configure custom import workflows, and automate document categorization.
1. Advanced OCR Optimization and Engine Settings
To achieve maximum accuracy and performance, you must tune Tesseract within Paperless-ngx. Modify your Docker environment variables (docker-compose.env or the environment: block in docker-compose.yml) to adjust OCR behavior.
# Define the OCR mode. Options: skip (default), force, redo, skip_noarchive.
# Use 'skip' to only run OCR on documents that do not have embedded text.
# Use 'force' to run OCR on all documents, overriding pre-existing text layers.
PAPERLESS_OCR_MODE=skip
# Install and enable multiple OCR languages (space-separated, lowercase ISO 639-3 codes)
# Ensure corresponding language packs are available or downloaded.
PAPERLESS_OCR_LANGUAGES=eng deu fra
# Limit the number of pages processed per document to prevent resource exhaustion.
# Setting to 0 disables the limit (default).
PAPERLESS_OCR_PAGES=0
# Pass custom parameters directly to Tesseract.
# "oem": OCR Engine Mode (3 = Default, based on what's available).
# "tessedit_char_whitelist": restrict OCR to specific characters if processing raw forms.
PAPERLESS_OCR_USER_ARGS='{"oem": 3, "presorted_langs": true}'
For multi-core hosts, you can control the resource utilization of OCR processing:
# Set the maximum number of parallel threads Tesseract is allowed to use per page.
# By default, Tesseract uses all available cores. Limit this to prevent CPU starvation.
OMP_THREAD_LIMIT=2
# Number of parallel document tasks Paperless-ngx handles.
# Equal to the number of concurrent celery workers.
PAPERLESS_WEBSERVER_WORKERS=2
PAPERLESS_TASK_WORKERS=2
2. Mounting and Configuring the Consume Folder via NFS/Samba
When ingestion occurs from a network scanner or a remote server, mounting the consume folder over NFS or Samba requires tuning to avoid file locks, permission mismatches, and missed file-system events.
Samba (CIFS) Mount Configuration
Add the share to your host's /etc/fstab to ensure a persistent mount:
//192.168.1.50/scans /mnt/paperless-consume cifs credentials=/etc/samba/credentials,uid=1000,gid=1000,iocharset=utf8,vers=3.0,nofail,x-systemd.automount 0 0
NFS Mount Configuration
Alternatively, if using NFS:
192.168.1.50:/volume1/scans /mnt/paperless-consume nfs rsize=1048576,wsize=1048576,timeo=600,retrans=2,nofail,x-systemd.automount 0 0
Docker Compose Bind Mount & Permission Matching
Map the local mount point into the container. You must ensure the environment variables USERMAP_UID and USERMAP_GID match the owner of the network share.
services:
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless-webserver
environment:
- USERMAP_UID=1000
- USERMAP_GID=1000
# Force polling because network filesystems do not reliably trigger inotify events
- PAPERLESS_CONSUMER_POLLING=10
# Delay in seconds to wait after a file is detected before consuming it
# Prevents paperless from consuming a file that is still being written
- PAPERLESS_CONSUMER_INOTIFY_DELAY=5
volumes:
- /mnt/paperless-consume:/usr/src/paperless/consume
- paperless-data:/usr/src/paperless/data
- paperless-media:/usr/src/paperless/media
3. Automated File Classification & Matching Rules
Paperless-ngx matching algorithms dictate how tags, correspondents, document types, and storage paths are automatically assigned to incoming documents.
| Match Type | Algorithm / Logic | Best Use Case | Matching Rule Example |
|---|---|---|---|
| None | No automatic assignment. | Manual triaging. | N/A |
| Any | Matches if any listed word is found (case-insensitive). | Grouping various related terms. | invoice bill statement |
| All | Matches if all listed words are found (case-insensitive). | Precise compound matching. | electric utility service |
| Exact | Matches the exact string, including spaces. | Fixed strings or titles. | Acme Corp LLC |
| Regular Expression | Python-style regex matches the text. | Complex patterns (IDs, VATs). | \bDE[0-9]{9}\b |
| Fuzzy | Matches using Levenshtein distance similarity. | Scanned documents with poor OCR. | Telekom |
| Auto | Naive Bayes classifier trained on existing documents. | High-volume structured document streams. | N/A |
Setting Up a RegEx Match Rule for Invoices
To automatically assign the tag Invoice using a regular expression match rule: 1. Navigate to Tags -> Create. 2. Name the tag: Invoice. 3. Set Matching algorithm to Regular Expression. 4. Set Matching pattern to search for invoice numbers or currency notations: regex (?i)\b(invoice|rechnung|facture|bill)\b
4. Advanced Email Fetching Configurations
Automate the processing of electronic invoices, receipts, and bank statements directly from your mailboxes.
IMAP Connection Setup
Navigate to Settings -> Mail Accounts -> Add Account: - IMAP Server: imap.protonmail.ch (or your mail provider's address) - Port: 993 - Security: SSL/TLS - Username & Password: Use a dedicated App Password.
Custom Mail Rules
Configure granular mail rules via Settings -> Mail Rules -> Add Rule:
# Conceptual logic executed by Paperless-ngx Mail Rule Parser
Rule-Name: "Utility Bill Parser"
Trigger-On: "Inbox"
Filter-Criteria:
Sender-Contains: "billing@utilityprovider.com"
Subject-Contains: "your invoice"
Has-Attachment: True
Processing-Action:
Extract-Attachment: "Only attachments matching pattern: *.pdf"
On-Success: "Mark as read and archive email"
Assign-Metadata:
Tag: "Utility"
Correspondent: "Utility Provider"
Document-Type: "Invoice"
To configure this in the UI: 1. Source: Select your configured Mail Account. 2. Folder: INBOX (or a subfolder like Invoices). 3. Filter From: billing@utilityprovider.com. 4. Filter Subject: your invoice. 5. Action: Process attachments. 6. Action parameter: *.pdf. 7. Assign Tag: Utility. 8. Assign Correspondent: Utility Provider. 9. Assign Document Type: Invoice.
5. Custom Document Workflows and Automation Triggers
Workflows (introduced in Paperless-ngx v2.0+) execute actions based on triggers and conditions. This replaces the legacy post-consume scripts for most routing tasks, though they can still run in tandem.
Workflow Example: Direct Routing and Slack Webhook
In this scenario, whenever a document tagged High Priority is consumed, a custom webhook is executed to alert the team.
Step 1: Create the Post-Consume Script
Write a Python script /usr/src/paperless/scripts/post-consume-webhook.py inside the container:
#!/usr/bin/env python3
import os
import sys
import requests
# Paperless-ngx passes environment variables containing document context
document_id = os.environ.get("DOCUMENT_ID")
document_title = os.environ.get("DOCUMENT_TITLE")
document_tags = os.environ.get("DOCUMENT_TAGS")
download_url = f"https://paperless.local/api/documents/{document_id}/download/"
webhook_url = "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
payload = {
"text": f"๐จ *New Document Processed* ๐จ\n*Title:* {document_title}\n*Tags:* {document_tags}\n*Link:* <{download_url}|Download PDF>"
}
try:
response = requests.post(webhook_url, json=payload, timeout=10)
response.raise_for_status()
print("Notification sent successfully.")
except Exception as e:
print(f"Failed to send webhook: {e}", file=sys.stderr)
sys.exit(1)
Make sure the script is executable:
chmod +x /usr/src/paperless/scripts/post-consume-webhook.py
Step 2: Configure Environment for External Scripts
Add the script path to your Docker compose configuration to allow Paperless-ngx to run it:
PAPERLESS_POST_CONSUME_SCRIPT=/usr/src/paperless/scripts/post-consume-webhook.py
Step 3: Define Custom UI Workflows
Go to Workflows in the Paperless-ngx Web UI: 1. Create Workflow: - Name: Archive Financial Docs 2. Trigger: - Type: Document Added - Source: Consume Folder - Filter: Document matches Invoice tag. 3. Action: - Type: Assign Storage Path - Storage Path: {{ year }}/{{ correspondent }}/{{ title }} - Add Tag: Archived