====== Install paperless-ngx on Debian without Docker ====== Caveat: this guide assumes a non-Raspberry pi machine, and SQLite as database (which is ok for small installations). The service will be behind an Nginx proxy. ===== Install dependencies and configure the system ===== First, we'll need to install all required dependencies (there are also dependencies for MariaDB and PostgreSQL; even if we won't use them, not installing them would require to edit the requirements.txt file later, which I don't want to do just in case it breaks something): apt install valkey-server python3 python3-pip python3-dev fonts-liberation imagemagick libmagic-dev poppler-utils build-essential python3-setuptools python3-wheel python3-venv pkg-config default-libmysqlclient-dev libpq-dev If you're planning on sending gpg-encrypted emails to paperless, you'll also need to add ''gnupg'' to the list of packages. You can use ''redis-server'' instead of ''valkey-server'' if you prefer. The following packages are needed if you want to run OCR on your documents: apt install unpaper ghostscript icc-profiles-free qpdf libleptonica6 libxml2 pngquant zlib1g tesseract-ocr tesseract-ocr-//xxx// where ''//xxx//'' is the language code for the languages your documents will be in (eng, ita, deu, etc.). Now it's time to add a service system user and group for the application, which will be installed in ''/opt/paperless'': adduser paperless --system --home /opt/paperless --group ===== Download, install and paperless-ngx ===== We need to download the latest paperless release from the github repo (replace ''x.x.x'' with the latest release number). Do not clone the git repo, but download the release, which contains some compiled code absent in the repo. This is the sequence of inputs to download the release file, extract it, and move everything inside ''/opt/paperless'': cd /opt/paperless sudo -u paperless wget https://github.com/paperless-ngx/paperless-ngx/releases/download/vx.x.x/paperless-ngx-vx.x.x.tar.xz sudo -u paperless tar xf paperless-ngx-vx.x.x.tar.xz mv paperless-ngx/* . mv paperless-ngx/.* . rmdir paperless-ngx rm paperless-ngx-vx.x.x.tar.x At this point we need to edit the ''paperless.conf'' file to adapt it to our installation. It is important to uncomment and properly set these variables: PAPERLESS_REDIS PAPERLESS_DBENGINE=sqlite # It may not be necessary to create this for sqlite, but just in case... PAPERLESS_CONSUMPTION_DIR PAPERLESS_DATA_DIR PAPERLESS_MEDIA_ROOT # If needed it can be the same directory as PAPERLESS_DATA_DIR PAPERLESS_STATICDIR=../static PAPERLESS_SECRET_KEY PAPERLESS_URL PAPERLESS_OCR_LANGUAGE PAPERLESS_TIME_ZONE PAPERLESS_USE_X_FORWARD_HOST=true PAPERLESS_USE_X_FORWARD_PORT=true PAPERLESS_PROXY_SSL_HEADER='["HTTP_X_FORWARDED_PROTO", "https"]' Make sure you create the folders you have assigned in the config file and chown them to the paperless:paperless user and group. To install all the required python packages with pip (Debian doesn't have a lot of them in its repo, plus specific versions are required) it is necessary to create a python virtual environment owned by the user paperless. It will then be possible to install the packages: sudo -u paperless makedir venv sudo -u paperless python3 -m venv venv sudo -u paperless venv/bin/pip3 install -r requirements.txt Time to populate the database: cd src sudo -u paperless ../venv/bin/python3 manage.py migrate As a last installation step, something undocumented on paperless-ngx's documentation: to enable better document search (which I believe is active by default), we need to download some more python packages. First of all, enable this feature explicitly in ''paperless.conf'': PAPERLESS_ENABLE_NLTK=true PAPERLESS_NLTK_DIR=/opt/paperless/nltk_data Then, download the required packages: cd /opt/paperless sudo -u paperless venv/bin/python3 -m nltk.downloader punkt_tab sudo -u paperless venv/bin/python3 -m nltk.downloader punkt sudo -u paperless venv/bin/python3 -m nltk.downloader stopwords Before testing the server to see if it works, we need to temporarily enable debug mode. Add ''PAPERLESS_DEBUG=true'' to ''paperless.conf'', then run: cd src sudo -u paperless ../venv/bin/python3 manage.py runserver It's now time to set up all the systemd services. Script examples are in the ''script'' folder and we're going to edit those and link them to the systemd folder. paperless-consumer.service [Unit] Description=Paperless consumer Requires=redis.service [Service] User=paperless Group=paperless WorkingDirectory=/opt/paperless/src ExecStart=/opt/paperless/venv/bin/python3 manage.py document_consumer [Install] WantedBy=multi-user.target paperless-scheduler.service [Unit] Description=Paperless Celery Beat Requires=redis.service [Service] User=paperless Group=paperless WorkingDirectory=/opt/paperless/src ExecStart=/opt/paperless/venv/bin/celery --app paperless beat --loglevel INFO [Install] WantedBy=multi-user.target paperless-task-queue.service [Unit] Description=Paperless Celery Workers Requires=redis.service [Service] User=paperless Group=paperless WorkingDirectory=/opt/paperless/src ExecStart=/opt/paperless/venv/bin/celery --app paperless worker --loglevel INFO [Install] WantedBy=multi-user.target paperless-webserver.service [Unit] Description=Paperless webserver After=network.target Wants=network.target Requires=valkey.service #Requires=paperless-webserver.socket [Service] User=paperless Group=paperless WorkingDirectory=/opt/paperless/src Environment=GRANIAN_HOST=:: Environment=GRANIAN_PORT=8000 Environment=GRANIAN_WORKERS=1 ExecStart=/bin/sh -c '\ # Host: GRANIAN_HOST -> PAPERLESS_BIND_ADDR -> default \ [ -n "$PAPERLESS_BIND_ADDR" ] && export GRANIAN_HOST=$PAPERLESS_BIND_ADDR; \ # Port: GRANIAN_PORT -> PAPERLESS_PORT -> default \ [ -n "$PAPERLESS_PORT" ] && export GRANIAN_PORT=$PAPERLESS_PORT; \ # Workers: GRANIAN_WORKERS -> PAPERLESS_WEBSERVER_WORKERS -> default \ [ -n "$PAPERLESS_WEBSERVER_WORKERS" ] && export GRANIAN_WORKERS=$PAPERLESS_WEBSERVER_WORKERS; \ # URL path prefix: only set if PAPERLESS_FORCE_SCRIPT_NAME exists \ [ -n "$PAPERLESS_FORCE_SCRIPT_NAME" ] && export GRANIAN_URL_PATH_PREFIX=$PAPERLESS_FORCE_SCRIPT_NAME; \ exec /opt/paperless/venv/bin/granian --interface asginl --ws --loop uvloop "paperless.asgi:application"' [Install] WantedBy=multi-user.target Now that we have the unit files ready, we need to enable and start them: cd scripts systemctl enable paperless-task-queue.service systemctl enable paperless-scheduler.service systemctl enable paperless-consumer.service systemctl enable paperless-server.service systemctl start paperless-task-queue.service systemctl start paperless-scheduler.service systemctl start paperless-consumer.service systemctl start paperless-server.service All that is left to do now is configure the Nginx reverse proxy: cd /etc/nginx/sites-available/ nano docs.mydomain.tld This is the content of the docs.mydomain.tld file: server { listen 443 ssl; listen [::]:443 ssl; http2 on; ssl_certificate /path/to/cert.crt; ssl_certificate_key /path/to/cert.key; server_name docs.mydomain.tld; access_log /var/log/nginx/docs.mydomain.tld-access.log; error_log /var/log/nginx/docs.mydomain.tld-error.log; client_max_body_size 20M; large_client_header_buffers 4 8k; add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;"; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; location = /accounts/login/ { proxy_pass http://localhost:8000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Forwarded-Proto $scheme; proxy_hide_header Referrer-Policy; add_header Referrer-Policy "same-origin" always; } location / { proxy_pass http://localhost:8000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_set_header Host $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-Host $server_name; proxy_set_header X-Forwarded-Proto $scheme; proxy_hide_header Referrer-Policy; add_header Referrer-Policy "no-referrer" always; } } And now it's time to enable the configuration: ln -s /etc/nginx/sites-available/docs.mydomain.tld /etc/nginx/sites-enabled/ systemctl restart nginx ===== Updating paperless-ngx ===== Paperless-ngx's documentation suggests to delete almost all previous files and copy the new ones in place, so we'll do just that. Before starting, we backup the current folder for safety purposes, and we stop all paperless services. Here is the sequence of commands: systemctl stop paperless-consumer paperless-scheduler paperless-task-queue paperless-webserver cd /opt cp -R paperless paperless.bak wget https://github.com/paperless-ngx/paperless-ngx/releases/download/vx.x.x/paperless-ngx-vx.x.x.tar.xz tar xf paperless-ngx-vx.x.x.tar.xz chown -R paperless:paperless paperless.bak paperless-ngx At this point it's good to stop for a second and check that the systemd unit files in the ''scripts'' directory have not changed, so that we can keep the old ones, or modify them accordingly. Once done with the check, it's time for the update. From the original installation we need to keep the ''.env'', ''paperless.conf'', ''scripts'', and ''venv'' files and folders, so we'll delete everything but those (and of course we'll remove just those from the directory of the new version): cd /opt/paperless rm -r `ls -a | grep -v ".env\|paperless.conf\|scripts\|venv"` cd /opt/paperless-ngx rm -r .env paperless.conf scripts mv ./* ../paperless Now, with all the files in place, we update the python dependencies. In principle we should also manually remove all dependencies that are no longer required, but meh, we'll think about it if errors occur. cd /opt/paperless sudo -u paperless venv/bin/pip3 install -r requirements.txt cd src sudo -u paperless ../venv/bin/python3 manage.py migrate # (1) sudo -u paperless ../venv/bin/python3 manage.py document_index reindex --if-needed sudo -u paperless ../venv/bin/python3 manage.py document_llmindex migrate It is now possible to restart the services. systemctl start paperless-consumer paperless-scheduler paperless-task-queue paperless-webserver If everything works, we can clean up: cd /opt rm -R paperless.bak paperless-ngx