How to Install Paperless with Nginx on Debian

Paperless is a Python application that ingests scanned documents, indexes them, and presents them in a user-friendly web interface. In this tutorial, we will be installing Paperless with an Nginx HTTPS reverse proxy on Debian 10.


  • A Debian 10 system on which you have root access.
  • A registered domain name is pointing to your server.

All commands shown in this document should be executed as root unless indicated otherwise.

Set the $VISUAL environment variable to a text editor of your choice. For example, to use nano:

echo "export VISUAL=nano" >> ~/.bashrc
. ~/.bashrc

Step 1: Installing Dependencies

Paperless requires several software components for its installation and operation. Install them as follows:

apt update
apt install -y gnupg2 python3 python3-dev python3-pip python3-virtualenv tesseract-ocr tesseract-ocr-eng unpaper imagemagick libpoppler-cpp-dev optipng git gcc g++

If you're going to be working with documents in languages other than english, install the matching Tesseract language files. For example, for french and spanish:

apt install -y tesseract-ocr-fra tesseract-ocr-spa

You can list all available tesseract packages using:

apt list tesseract-ocr-*

If you're unsure which 3-letter code corresponds to the desired language, refer to this ISO 639-2 Code List.

Step 2: Creating a System User

While it is possible to run paperless as root, using a user with low privileges and disabled login is strongly recommended. Create a user and group named paperless:

useradd -d /opt/paperless -M -r -s /bin/bash -U -p x paperless

Step 3: Installing Paperless

Clone the Paperless Github repository to /opt/paperless

git clone /opt/paperless

Give the paperless user ownership of that directory:

chown -R paperless:paperless /opt/paperless

Copy the included configuration sample as a starting point:

cp /opt/paperless/paperless.conf.example /etc/paperless.conf

And open it in your text editor:

$VISUAL /etc/paperless.conf

Choose a directory from which Paperless will ingest scanned documents and set the PAPERLESS_CONSUMPTION_DIR parameter accordingly:


Find, uncomment (by removing the # character) and change the values of the following lines to something secure:


If your scanner supports emailing scanned documents, you can have paperless ingest them from the receiving inbox automatically. To enable this feature, set the PAPERLESS_CONSUME_MAIL_* options. For security reasons, creating a mail account dedicated to Paperless is recommended. For example:


Save your changes and exit, then change the owner of this file to paperless and tighten its permissions:

chown paperless:paperless /etc/paperless.conf
chmod 0400 /etc/paperless.conf

Switch to the paperless user:

su - paperless

Create the consumption directory:

mkdir /opt/paperless/paper_in

Create a python virtual environment. This will provide a stable and isolated environment where we can install the specific python modules and versions required by Paperless.

python3 -m virtualenv --python=/usr/bin/python3 venv

Activate it:

. venv/bin/activate

Install the python modules required by paperless:

pip3 install -r requirements.txt

This command may take a while. Once it finishes, run the following commands to initialize the database and create the static files for the web service:

cd src/
./ migrate
./ collectstatic

Create login credentials for the web interface administrator account by running the following command and answering the prompts:

./ createsuperuser

Step 4: Initial Testing

Before setting up a proper web server and systemd services, we'll try running paperless manually. At this point, you should still be logged in as the paperless in the virtual python environment.

Start the web server and document consumer in the background:

./ runserver &
./ document_consumer &

Place any scanned document in the consumption directory configured in Step 3. For example:

wget -O /opt/paperless/paper_in/test1.jpg

Browse to http://IP_or_DOMAIN:8000/ and login with the credentials chosen in Step 3. In the "DOCUMENTS" menu, click on "Documents" to view the document list. Within a few minutes, the scanned document should be processed and available.

Stop paperless before proceeding to the next step:

pkill -f

Step 5: Systemd Services

We'll create systemd unit files so we can properly manage the web and consumer services. Exit back to your root shell:


Create a unit file for the web service:

$VISUAL /etc/systemd/system/paperless-webserver.service

And enter the following:

Description=Paperless Gunicorn Web Server
ExecStart=/opt/paperless/venv/bin/gunicorn --pythonpath=/opt/paperless/src paperless.wsgi -w 3 -b

NOTE: You may want to modify the number of worker processes in the ExecStart command. The service shown here starts Gunicorn with 3 workers (-w 3).

Next, create another unit file for the document consumer process:

$VISUAL /etc/systemd/system/paperless-consumer.service

And enter the following:

Description=Paperless Document Consumer
ExecStart=/opt/paperless/venv/bin/python3 /opt/paperless/src/ document_consumer

Start these services:

systemctl daemon-reload
systemctl start paperless-webserver.service paperless-consumer.service

Make sure both of them are running:

systemctl status paperless-webserver.service paperless-consumer.service

If you'd like paperless to start automatically at system startup, execute the command:

systemctl enable paperless-webserver.service paperless-consumer.service

Step 6: Nginx Reverse Proxy and HTTPS

Install Nginx and certbot:

apt update
apt install -y nginx certbot

Ensure Nginx is enabled and running:

systemctl enable --now nginx.service

Obtain a Let's Encrypt certificate for your domain with certbot:

certbot certonly --webroot --webroot-path /var/www/html -d your_domain

Disable the default Nginx configuration file and open a new one:

rm /etc/nginx/sites-enabled/default
$VISUAL /etc/nginx/sites-available/paperless

Input the following, replace your_domain with your domain name:

server {
    listen 80;
    server_name your_domain;
    return 301 https://$server_name$request_uri;
    access_log /var/log/nginx/paperless_access.log;
    error_log /var/log/nginx/paperless_error.log;
server {
    listen 443 ssl;
    server_name your_domain;
    index index.html index.htm index.php;
    access_log /var/log/nginx/paperless_access.log;
    error_log /var/log/nginx/paperless_error.log;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
    location /static {
        autoindex on;
        alias /opt/paperless/static;
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

Enable this configuration by linking to it in the sites-enabled Nginx directory, and check for any errors:

ln -s /etc/nginx/sites-available/paperless /etc/nginx/sites-enabled
nginx -t

Then load the changes:

systemctl reload nginx.service

Your Paperless instance should now be accessible at https://your_domain.

Step 7: Enhancements

Since the paperless system user doesn't need access to a working shell after the initial setup, we can change it to /usr/sbin/nologin:

usermod -s /usr/sbin/nologin paperless


If the Gunicorn webserver fails to start with the error message [ERROR] Connection in use, check for any processes already bound to port 8000/tcp:

ss -lntp

Kill/Disable the offending process if necessary, or modify /etc/systemd/system/paperless-webserver.service and /etc/nginx/sites-enabled/paperless to use another network port for Gunicorn.

Share this page:

0 Comment(s)