Paperless-ngx is one of the best self-hosted document management systems you can run. It automatically ingests, OCRs, tags, and stores your scanned files so you never have to dig through a filing cabinet again. The whole workflow hinges on one feature: the consume folder, a watched directory where you drop files and let the system handle the rest.
When that consume folder works, paperless-ngx feels like magic. You scan a document, it lands in a shared folder, and within seconds it is searchable from your browser. When it breaks, files just sit there silently, and that is the single most common frustration reported across the self-hosting community.
In this guide I will walk you through how to set up paperless-ngx and fix documents stuck in the consume folder. I have pulled together the official documentation, dozens of GitHub discussions, Reddit threads, and real user pain points so you get a single, complete reference. Whether you are doing a fresh Docker install or debugging a NAS setup that has been ignoring your files for days, you will find the exact steps here.
We will cover the full Docker Compose installation, consume folder configuration with every important environment variable, a diagnostic workflow for stuck documents, network share fixes for SMB and NFS, and a verification checklist so you can confirm everything actually works.
Table of Contents
Quick-Start Summary for Experienced Users
If you already have paperless-ngx installed and just need the fix for stuck documents, here is the short version.
Files consumed at startup but ignored afterward: Your filesystem does not support inotify (common with SMB and NFS). Set PAPERLESS_CONSUMER_POLLING=1 in docker-compose.env, then run docker compose down followed by docker compose up -d.
Files in subfolders never picked up: Set PAPERLESS_CONSUMER_RECURSIVE=1 in the same file, then do the full down and up cycle.
Environment variable changes not taking effect: A simple container restart is not enough. You need a full docker compose down and docker compose up -d so Docker re-reads docker-compose.env.
Files visible inside the container but never consumed: Check that no line in your env file starts with #, confirm boolean values are correct, and read the logs with docker compose logs -f webserver to see if the consumer is even scanning.
If any of those steps raise more questions than they answer, the sections below explain every detail.
What You Need Before You Start
Before installing paperless-ngx, make sure your host system meets a few basic requirements. This setup works on any Linux distribution, and most users run it on a Debian or Ubuntu server, a Proxmox VM, or directly on a NAS appliance like a Synology or TrueNAS box.
You need Docker and Docker Compose installed. Paperless-ngx runs entirely in containers, so there is no need to install Python, Redis, or PostgreSQL directly on your host. The official Docker Compose bundle includes a webserver container, a broker (Redis), a task backend (PostgreSQL or MariaDB), and optional tools like gotenberg and tika for advanced document handling.
You also need a place to store documents. A local directory on the host works perfectly. If you plan to pull files from a scanner or a network share, you will need that share mounted or synced to the host before you start, because Docker volume permissions can get tricky with remote filesystems.
Finally, have a terminal ready. Almost every step in this guide happens at the command line, and most troubleshooting commands use docker exec to inspect what is happening inside the running containers.
Step-by-Step Paperless-ngx Docker Compose Installation
Paperless-ngx ships with an interactive installation script that generates your Docker Compose files automatically. This is the recommended path for new installs and the one I use on every fresh deployment.
Start by cloning or downloading the installation files from the official repository. The script asks a few questions about your target directory, database preference, and port numbers, then creates a tailored docker-compose.yml and docker-compose.env file for your environment.
Step 1: Download the install script. From your host, pull the installation files so you have the latest version of the compose template and env file. You can grab these from the official paperless-ngx GitHub repository.
Step 2: Run the installation script. Execute the script and answer the prompts. It will ask where you want paperless installed, whether to use PostgreSQL or SQLite, what port to expose, and what OCR languages you want. For most setups, PostgreSQL is the recommended database because it handles large libraries better than SQLite.
Step 3: Review the generated files. The script produces two key files. The docker-compose.yml defines the containers and volume mappings. The docker-compose.env holds all your environment variables, including the consume folder settings we will tune shortly.
Step 4: Create your admin user. Before the first boot, the script generates default credentials or lets you set your own. Take note of the superuser login, because you will need it to access the web UI.
Step 5: Start the stack. Run docker compose up -d from the installation directory. Docker pulls the images, creates the containers, and starts them in the background. The first boot takes longer because it downloads and initializes everything.
Step 6: Access the web UI. Open your browser and navigate to your server IP on the port you configured, typically port 8000. Log in with your superuser credentials and you should see the paperless-ngx dashboard.
At this point, paperless-ngx is running. The default directory structure includes separate volumes for media (stored documents), data (database and search index), export, and the consume folder. Understanding this layout matters, because the consume folder volume is where all your file-dropping automation happens.
How to Configure the Consume Folder
The consume folder is a directory that paperless-ngx watches for new files. Any document you place there gets automatically picked up, OCR’d, classified, and added to your library. It is the backbone of a hands-off scanning workflow.
By default, the consume folder lives inside the container at /usr/src/paperless/consume. In your docker-compose.yml, this path is mapped to a directory on your host through a Docker volume. That host directory is where you actually drop files.
Open your docker-compose.yml and find the webserver service definition. Look for a volume entry similar to this:
- ./consume:/usr/src/paperless/consume
The left side of the colon is your host path. The right side is the in-container path, which must always be /usr/src/paperless/consume. You can change the host side to point anywhere on your system, including a mounted network share, but the container side stays fixed.
If you want to change where the consume folder lives on your host, edit that volume mapping. For example, to use a dedicated directory: - /mnt/documents/inbox:/usr/src/paperless/consume. After making this change, run docker compose down and docker compose up -d so Docker picks up the new mapping.
One common mistake is editing the container side of the mapping. Paperless-ngx only watches /usr/src/paperless/consume, so if you change that path in the compose file, the consumer will not find your files. Always edit the host side only.
Key Environment Variables for the Consume Folder
All consume folder behavior is controlled by environment variables in your docker-compose.env file. This is where most users get tripped up, because the settings only take effect under specific conditions.
PAPERLESS_CONSUMER_RECURSIVE tells paperless to scan subdirectories inside the consume folder. Set it to 1 if you want to organize incoming files into subfolders by category or source. Without it, paperless only looks at files in the top level of the consume directory.
PAPERLESS_CONSUMER_POLLING switches the file detection method from inotify to polling. Set it to 1 when your consume folder lives on a network share like SMB or NFS, because inotify does not work reliably on those filesystems.
PAPERLESS_CONSUMER_POLLING_RETRY_COUNT controls how many polling attempts paperless makes before giving up on a file. The default works for most setups, but if you have large files that take time to copy in, you may want to increase this.
PAPERLESS_CONSUMER_POLLING_DELAY sets the number of seconds between polling checks. The default is 5 seconds. If your system handles a lot of files, increasing this reduces load. If you want near-instant consumption, keep it low.
PAPERLESS_CONSUMER_INOTIFY_DELAY sets the delay in seconds after a file event before paperless tries to consume the file. This gives large files time to finish writing. Increase it if you process large PDFs over a slow network.
Here is what a working set of consume variables looks like in docker-compose.env:
PAPERLESS_CONSUMER_RECURSIVE=1PAPERLESS_CONSUMER_POLLING=1PAPERLESS_CONSUMER_POLLING_DELAY=10
Boolean values matter. Use 1 for true and 0 for false. Do not use true, True, or yes unless you have confirmed your version of paperless-ngx accepts them. The safest value is always 1 or 0.
Watch for comment characters. If any line in your env file starts with #, Docker treats the entire line as a comment and silently ignores it. I have seen users spend hours debugging a consume folder that would not scan subdirectories, only to discover a stray # at the start of their PAPERLESS_CONSUMER_RECURSIVE line.
The restart rule. After changing any value in docker-compose.env, you must run docker compose down followed by docker compose up -d. A simple docker compose restart is not enough. Docker only reads the env file when containers are created, not when they are restarted. This is the single most common reason environment variable changes do not take effect.
Your documents and database are safe during a docker compose down and up cycle, because the data lives in Docker volumes that persist independently of the containers. Nothing gets deleted.
inotify vs Polling: Which One Should You Use
Paperless-ngx detects new files in the consume folder using one of two mechanisms: inotify or polling. Understanding the difference is the key to fixing most stuck document problems.
inotify is a Linux kernel feature that watches a directory for filesystem events in real time. When a file is created, modified, or moved, the kernel sends an instant notification. This is the default detection method in paperless-ngx because it is fast and efficient. There is no delay between the file arriving and paperless noticing it.
The problem is that inotify only works on local filesystems. When your consume folder lives on a network share mounted via SMB, CIFS, or NFS, the kernel on your Docker host does not receive those filesystem events. The remote server handles the writes, and the local kernel has no idea anything changed. Files appear in the directory, but paperless never gets notified.
This is why so many users report that files are visible inside the container but never get consumed. The consumer is running and watching, but the filesystem never tells it anything arrived.
Polling is the alternative. When you enable PAPERLESS_CONSUMER_POLLING=1, paperless stops relying on inotify and instead checks the consume folder on a timer. Every PAPERLESS_CONSUMER_POLLING_DELAY seconds, it scans the directory for new files and processes whatever it finds.
Polling works on any filesystem, including network shares, because it does not depend on kernel events. The tradeoff is a small delay between a file arriving and paperless processing it, plus slightly higher disk activity from the repeated scans.
Here is my recommendation based on filesystem type:
Local disk or SSD: Use inotify (the default). It is instant and efficient.
SMB or CIFS network share: Use polling. Set PAPERLESS_CONSUMER_POLLING=1. inotify will not work here.
NFS mount: Use polling. NFS has the same inotify limitations as SMB.
Network share synced to local volume: You can use inotify on the local volume. This is the approach some users take when they want to keep files on a NAS but avoid polling. They set up a sync job that copies files from the NAS to a local directory, and point the consume folder at the local path.
If you are not sure which filesystem your consume folder uses, start with polling. It costs almost nothing in performance for a typical home setup, and it eliminates an entire category of silent failures.
How to Set Up Paperless-ngx and Fix Documents Stuck in the Consume Folder
This section is the core diagnostic workflow. If your consume folder is not picking up files, follow these steps in order. Each one addresses a specific failure mode I have seen repeatedly across GitHub issues, Reddit threads, and the official documentation.
Symptom 1: Files Consumed at Startup but Ignored Afterward
This is the most common complaint. When paperless-ngx starts, it finds existing files in the consume folder and processes them. But new files you add later are completely ignored. No logs, no errors, no activity.
The cause is almost always inotify failing on a network filesystem. At startup, paperless does an initial scan of the consume directory and finds files that are already there. After that initial scan, it relies on inotify to detect new files. On SMB or NFS shares, those events never arrive.
Fix: Set PAPERLESS_CONSUMER_POLLING=1 in docker-compose.env, then run docker compose down and docker compose up -d. This switches to polling, which actively checks for new files instead of waiting for kernel events.
Symptom 2: Files in Subfolders Never Picked Up
You organized your consume folder with subdirectories for different document types, but paperless only processes files in the root. Subfolder contents are ignored entirely.
Fix: Set PAPERLESS_CONSUMER_RECURSIVE=1 in docker-compose.env. Without this variable, the consumer only scans the top level. After setting it, run the full docker compose down and docker compose up -d cycle. Recursive scanning works alongside both inotify and polling.
Symptom 3: Files Visible in Container but Never Consumed
You can docker exec into the webserver container, list the contents of /usr/src/paperless/consume, and see your files sitting there. But the web UI shows no new documents, and the logs show no consumption attempts.
This points to one of several issues. First, check your environment variables. A leading # on any line makes it a comment. Second, verify you are editing the correct file. Paperless-ngx reads configuration from docker-compose.env, not from docker-compose.yml directly for most consumer settings.
Third, confirm the container path is correct. The volume mapping must point to /usr/src/paperless/consume on the container side. If you changed that path, the consumer is watching an empty directory.
Fourth, check for polling. If your files are on a network share and polling is not enabled, switch to polling as described in the previous section.
Symptom 4: Documents Stuck in Queue After Upload
Files are detected and appear in the web UI under File Tasks, but they never move past “queued” or “processing.” They sit there indefinitely with no error message.
This is a different problem from the consume folder not detecting files. The consumer found your document and handed it off to the processing pipeline, but the pipeline stalled. Common causes include missing or failed OCR dependencies, a Redis broker that is not responding, or a worker process that crashed.
Fix: Check the task backend logs with docker compose logs -f celery. Look for errors related to OCR, ghostscript, or tesseract. If the worker crashed, a full docker compose down and docker compose up -d restarts it cleanly.
If you see a NoneType error in the logs, that usually means a required processing step could not find expected data. This can happen when the database and search index are out of sync. Try running the document reindexing command or clearing the failed task and re-uploading the file.
Symptom 5: “Upload Complete, Waiting” That Never Resolves
When you upload a document through the web UI, it shows “Upload complete, waiting” and then never progresses. This is related to the queue issue above and typically means the celery worker is not processing tasks.
Fix: Check that all containers are running with docker compose ps. If the celery worker or Redis containers have stopped, bring the whole stack down and back up. Also verify that Redis is healthy, because the worker depends on it to receive tasks.
The Universal First Step
No matter which symptom you have, always start by checking the logs. Run docker compose logs -f webserver and watch what happens when you drop a new file into the consume folder. If you see consumption activity, the problem is in the processing pipeline. If you see nothing at all, the consumer is not detecting the file, and the issue is with inotify, polling, volume mapping, or environment variables.
Fixing Network Share Issues (SMB and NFS)
Network shares are the number one source of consume folder problems. The issues fall into two categories: inotify failures and permission mismatches.
We already covered the inotify fix. If your consume folder is on an SMB or NFS mount, polling is mandatory. Set PAPERLESS_CONSUMER_POLLING=1 and forget about inotify entirely for network shares.
Permissions are the second layer of trouble. When Docker maps a network share into the container, the files arrive with ownership and permissions set by the remote server. Paperless-ngx runs as a specific user inside the container, and if that user cannot read the files, consumption fails silently.
To check permissions from inside the container, run: docker exec -it webserver ls -la /usr/src/paperless/consume. Look at the owner and group of your files. They need to be readable by the paperless user, which by default runs as UID and GID 1000.
If your files are owned by a different user, you have two options. You can change the PAPERLESS_WEBSERVER user and group IDs in docker-compose.env to match the file owner, or you can adjust the permissions on the network share so UID 1000 has read access.
One approach that eliminates network share problems entirely is the sync method. Instead of mounting the NAS directly into the consume folder, set up a sync job (using rsync, Syncthing, or a similar tool) that copies files from the network share to a local directory on the Docker host. Point the consume folder at that local directory, and inotify works normally because the files are on a local filesystem.
This adds a small delay as files sync, but it removes the entire class of network filesystem issues. Many users in the self-hosting community have switched to this approach after fighting with SMB and NFS permissions for weeks.
How to Verify Your Consume Folder Is Working?
Once you have configured everything, you need to confirm it actually works. Do not assume the setup is correct just because the web UI loads. Run through this checklist every time you change your configuration.
Test 1: Drop a file and watch the logs. Place a small PDF in your consume folder, then run docker compose logs -f webserver. Within seconds (or within your polling delay, if using polling), you should see log entries showing the consumer detecting and processing the file. If you see nothing, the consumer is not detecting the file.
Test 2: Check the web UI File Tasks. Open the paperless-ngx web UI and navigate to the File Tasks section. You should see your document appear with a processing status, then move to success. If it appears and gets stuck, the problem is in the processing pipeline, not the consumer.
Test 3: Test subfolders. If you enabled recursive scanning, create a subdirectory in the consume folder and place a file inside it. The file should be consumed just like one in the root directory. If only root-level files are processed, PAPERLESS_CONSUMER_RECURSIVE is not set correctly.
Test 4: The touch test. Run touch /path/to/consume/testfile.txt on your host and check the logs. Even an empty file triggers a detection event. If you see nothing in the logs after the touch, detection is broken and you need to revisit inotify or polling settings.
Test 5: Verify from inside the container. Run docker exec -it webserver ls -la /usr/src/paperless/consume to confirm files are actually visible from the container’s perspective. If they are not, your volume mapping is wrong.
If all five tests pass, your consume folder is working correctly. Bookmark this checklist and run through it any time you change your Docker or network configuration.
FAQ
Where are paperless-ngx documents stored?
Paperless-ngx stores processed documents in its media directory, which is mapped to a Docker volume on your host. The exact host path is defined in your docker-compose.yml file, typically under the webserver service volume mappings. Original files are renamed, organized by date, and stored alongside generated thumbnails and OCR text files.
Where does paperless-ngx save files by default?
By default, paperless-ngx saves processed documents in the media volume at /usr/src/paperless/media inside the container. On your host, this maps to a local directory specified in docker-compose.yml, usually ./media in the installation folder. Documents are organized into year and month subdirectories automatically.
Is paperless-ngx any good?
Yes, paperless-ngx is widely regarded as one of the best self-hosted document management systems available. It offers automatic OCR in over 100 languages, full-text search, document classification with machine learning, multi-user support, and a clean web interface. It is free, open source, and actively maintained.
What database is recommended for paperless-ngx?
PostgreSQL is the recommended database for paperless-ngx, especially for larger document libraries or multi-user setups. SQLite works fine for small personal collections but can slow down as your library grows. The official Docker Compose install script includes PostgreSQL as an option and handles all the configuration for you.
Why is my consume folder not picking up new files?
The most common cause is that your consume folder is on a network share (SMB or NFS) and inotify does not work on those filesystems. Set PAPERLESS_CONSUMER_POLLING=1 in docker-compose.env, then run docker compose down followed by docker compose up -d to switch to polling mode.
Do I need to restart Docker after changing docker-compose.env?
Yes, but a simple restart is not enough. You need a full docker compose down and docker compose up -d. Docker only reads the env file when containers are created, not when they are restarted. This is the most common reason environment variable changes appear to have no effect.
Conclusion
Setting up paperless-ngx and fixing documents stuck in the consume folder comes down to understanding how file detection works. If your files are on a local disk, inotify handles everything automatically. If they are on a network share, polling is the fix.
The three settings that solve most problems are PAPERLESS_CONSUMER_POLLING=1, PAPERLESS_CONSUMER_RECURSIVE=1, and a full docker compose down and docker compose up -d after every change to docker-compose.env. Get those right, verify with the log test, and your consume folder will work reliably for years.
Your next step is to run through the verification checklist with a test document. If the logs show consumption activity, you are done. If they do not, work through the diagnostic workflow in the troubleshooting section to pinpoint the issue.