User Tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
en:install_paperless-ngx_on_debian_without_docker [2026-08-17 17:33] – created iacchien:install_paperless-ngx_on_debian_without_docker [2026-09-02 10:45] (current) – iacchi
Line 1: Line 1:
 ====== Install paperless-ngx on Debian without Docker ====== ====== 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).+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 =====+===== Install dependencies and configure the system =====
  
-First, we'll need to install all required dependencies:+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):
  
 <code bash> <code bash>
-apt install python3 python3-pip python3-dev fonts-liberation imagemagick libmagic-dev poppler-utils build-essential python3-setuptools python3-wheel valkey-server+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 
 </code> </code>
  
Line 14: Line 14:
  
 <code bash> <code bash>
-apt install unpaper ghostscript icc-profiles-free qpdf liblept5 libxml2 pngquant zlib1g tesseract-ocr tesseract-ocr-//xxx//+apt install unpaper ghostscript icc-profiles-free qpdf libleptonica6 libxml2 pngquant zlib1g tesseract-ocr tesseract-ocr-//xxx//
 </code> </code>
  
-where //xxx// is the language code for the languages your documents will be in (eng, ita, deu, etc.).+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'': Now it's time to add a service system user and group for the application, which will be installed in ''/opt/paperless'':
Line 25: Line 25:
 </code> </code>
  
 +===== 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'':
  
 <code bash> <code bash>
 +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
 </code> </code>
  
 +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:
  
 +<code>
 +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"]'
 +</code>
  
-<code bash>+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:
  
 +<code bash>
 +sudo -u paperless makedir venv
 +sudo -u paperless python3 -m venv venv
 +sudo -u paperless venv/bin/pip3 install -r requirements.txt
 </code> </code>
  
 +Time to populate the database:
  
 <code bash> <code bash>
 +cd src 
 +sudo -u paperless ../venv/bin/python3 manage.py migrate
 </code> </code>
  
 +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'':
  
 +<code>
 +PAPERLESS_ENABLE_NLTK=true
 +PAPERLESS_NLTK_DIR=/opt/paperless/nltk_data
 +</code>
 +
 +Then, download the required packages:
  
 <code bash> <code bash>
 +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
 +</code>
  
 +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:
 +
 +<code bash>
 +cd src
 +sudo -u paperless ../venv/bin/python3 manage.py runserver
 </code> </code>
  
 +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
 +<code>
 +[Unit]
 +Description=Paperless consumer
 +Requires=redis.service
  
-<code bash>+[Service] 
 +User=paperless 
 +Group=paperless 
 +WorkingDirectory=/opt/paperless/src 
 +ExecStart=/opt/paperless/venv/bin/python3 manage.py document_consumer
  
 +[Install]
 +WantedBy=multi-user.target
 </code> </code>
  
 +paperless-scheduler.service
 +<code>
 +[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
  
-<code bash>+[Install] 
 +WantedBy=multi-user.target 
 +</code> 
 + 
 +paperless-task-queue.service 
 +<code> 
 +[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
 </code> </code>
  
 +paperless-webserver.service
 +<code>
 +[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
  
-<code bash>+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
 </code> </code>
  
 +Now that we have the unit files ready, we need to enable and start them:
  
 <code bash> <code bash>
 +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
 +</code>
  
 +All that is left to do now is configure the Nginx reverse proxy:
 +
 +<code bash>
 +cd /etc/nginx/sites-available/
 +nano docs.mydomain.tld
 </code> </code>
  
 +This is the content of the docs.mydomain.tld file:
  
 +<code>
 +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;
  
-<code bash>+    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;
 +    }
 +}
 </code> </code>
  
 +And now it's time to enable the configuration:
  
 <code bash> <code bash>
 +ln -s /etc/nginx/sites-available/docs.mydomain.tld /etc/nginx/sites-enabled/ 
 +systemctl restart nginx
 </code> </code>
  
 +===== 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:
  
 <code bash> <code bash>
 +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
 +</code>
  
 +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):
 +
 +<code bash>
 +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
 </code> </code>
  
 +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.
  
 +<code bash>
 +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
 +</code>
 +
 +It is now possible to restart the services.
  
 <code bash> <code bash>
 +systemctl start paperless-consumer paperless-scheduler paperless-task-queue paperless-webserver
 +</code>
  
 +If everything works, we can clean up:
 +
 +<code bash>
 +cd /opt
 +rm -R paperless.bak paperless-ngx
 </code> </code>