Deployn

How to install Paperless-ngx on a VPS

Install document management Paperless-ngx with Docker on a VPS.

How to install Paperless-ngx on a VPS-heroimage

Introduction

This post outlines the process of setting up Paperless-ngx on a VPS. A complementary German video tutorial is available on YouTube:

Install Paperless-ngx on a VPS (Link to Youtube)

A summary of the steps detailed in the video is provided below.

The process involves renting a server, acquiring a domain, configuring the domain for Paperless-ngx, installing necessary software such as Docker, Docker-Compose, Caddy, and WG-Easy, as well as setting up Paperless-ngx itself.

Specific steps include configuring the domain to point to your server, installing Docker and Docker-Compose on the server, preparing a reverse proxy with Caddy, and setting up a secure VPN connection with WG-Easy. You will also learn how to block external connections for added security and conclude with installing Paperless-ngx, adding a user, configuring proxy settings, and backing up your Paperless-ngx instance. Regular updates are essential to maintain system security and integrity.

For those interested in setting up Paperless-ngx on a Synology NAS, instructions are available here: Install Paperless-ngx on a Synology NAS.

Key Takeaways

AspectDetails
WWhat is Paperless-ngx?An open-source document management system for digital files.
Why use a VPS?Access documents anywhere, secure data centers, scalable resources, and professional hosting.
Other Tools & SoftwareDocker for easy installation, Caddy as reverse proxy, Wireguard for secure connection.
PrerequisitesRequires a computer with Wireguard and Visual Studio Code, a Docker-compatible server, a domain with subdomains, and optionally, a mail server with SMTP support.

Paperless-ngx

Paperless-ngx is an open-source document management system that makes it easy for users to scan, organize, and find their documents. Paperless-ngx is the successor to the Paperless project and was developed with the modern user in mind. It offers a range of features that make paperless working easier.

Development history

A brief overview of the development of Paperless and Paperless-ngx (many releases have been omitted to keep the overview):

  • First commit

    Project Paperless published on GitHub.

  • v0.3.0

    First official release of Paperless.

  • v1.0.0

    Version 1.0.0 of Paperless released. Possibility for automatic tags introduced.

  • v1.2.0

    Possibility to skip OCR, better automatic data extraction

  • v2.1.0

    UI improvements

  • v2.2.0

    Upgrade to Django 2.0 and Python 3.7, better tagging

  • v2.3.0

    Support for text files, possibility to view documents online

  • v2.4.0

    Batch editing of documents possible

  • v2.5.0

    Optimized thumbnail generation with optipng

  • v2.7.0

    Latest release of Paperless

  • v0.9 ng

    First release of Paperless-ng

  • v0.9.2 ng

    UI revised

  • v0.9.4 ng

    Search and UI improved.

  • v0.9.5 ng

    OCR improved (OCRmyPDF), the originals as well as the archive files are saved, tags can be set by subfolders in the Consume directory, API with token authentication, many frontend improvements.

  • v1.0.0 ng

    Version 1.0.0 of Paperless-ng released.

  • v1.2.1 ng

    Latest release of Paperless-ng

  • v1.6.0 ngx

    First release of Paperless-ngx

  • v1.7.0 ngx

    Drag'n'drop, download buttons, update check, password prompt for PDFs, extended filter options, interactive tags, additional pagination, barcode splitting, loading screen, progress bar, text filter criteria, navigation in documents, date input and color themes have been optimized. Workflow completion groups have also been introduced and adjustments have been made to color contrasts and email tag rules.

  • v1.11.0 ngx

    Email texts can be archived, settings moved for easier setup.

  • v1.14.0 ngx

    Multi-user support

  • v2.0.0 ngx

    Version 2.0.0 of Paperless-ngx released. Django 4.2.5 and Python 3.11 are used. Links to documents can be shared.

  • v2.3.0 ngx

    Workflows and workflow rules

  • v2.4.0 ngx

    Current major version of Paperless-ngx at this time. Extension of caching for suggestions and metadata, introduction of help tooltips, warning function for outdated documentation and possibility of brand customization of the app.

  • Features of the Paperless-ngx DMS

    With Paperless-ngx you can:

    • Label documents for easy identification.
    • Search content effortlessly.

    Paperless-ngx is equipped with OCR (Optical Character Recognition) technology, which enables scanned documents to be converted into searchable PDFs. The software also supports the automatic classification of documents and the automatic recognition of metadata.

    When running on a server, Paperless-ngx can be accessed from any device as long as a browser is available.

    Reasons for installing on a VPS

    Installing on a VPS is particularly convenient for several reasons.

    Central access

    A VPS allows you to access your documents from anywhere with an internet connection. This means you are not restricted to the local network.

    Data security

    VPS providers usually offer highly secure data centers, which protects you from data loss due to physical damage such as fire or theft.

    Scalability

    With a VPS, you can adjust the server resources as your requirements grow - this means more storage space or computing power when needed.

    Professional hosting environment

    A VPS offers a professional hosting environment with dedicated IP addresses and a fast internet connection.

    These aspects make the use of a VPS for Paperless an attractive option for companies and individuals looking for an efficient and secure solution for their document management.

    Other tools

    However, we do not limit ourselves to Paperless, but integrate additional software to optimize the process. A central tool here is Docker, which makes the installation and configuration of Paperless much easier. I also use Caddy as a reverse proxy to make the application more easily and securely available. We use Wireguard to ensure a secure connection to our VPS.

    After following this guide, you should be able to set up a paperless office.

    Requirements

    • Computer with:

      • Wireguard: For the secure server connection.
      • Visual Studio Code: For working on the server.
    • Docker-compatible server: Paperless-ngx will be installed on it.

    • Domain with the option to create subdomains: To access Paperless-ngx.

    • Mail server with SMTP support: Optional, to archive files directly via email.

    Let me take you through the individual steps to implement your digital document management.

    Step 1: Rent a server

    First of all, we need a server. I recommend renting a VPS from a provider of your choice. I personally use Netcup. This is a quick and easy way to rent a VPS.

    You can also look here for vouchers.

    The costs currently start at €3.25 per month. Root servers (from €9.81 per month) offer significantly better performance due to the dedicated CPU cores, but you don’t need this if you only use the server for Paperless-ngx.

    If you have rented a VPS, you can find the IP address in the CCP. Otherwise, it should also be in the email.

    Netcup Control Panel

    Step 2: Rent a domain

    Next, we need a domain. Here, too, you should use a provider of your choice. The domain and server do not have to be with the same provider. However, I also use Netcup for this. At this point, you have two options:

    1. rent an additional domain
    2. rent a web hosting package with an inclusive domain

    The additional domain has the advantage that it is cheaper (currently €5.04 per year for a .de domain). However, the web hosting packages (from €2.17 per month) offer you additional functions, such as email inboxes and web space.

    Step 3: Configure domain

    After you have rented the domain, you need to configure it. To do this, log into the CCP and click on “Domains”. Select your domain and click on “DNS”.

    Netcup DNS

    There you add two new A-Records. The host is ”@” (for the main domain) and ”*” (for all subdomains). Enter the IP address of your server as the destination.

    If you have the web hosting package, first delete the entries for ”@” and ”*” in both the A records and the AAAA records. The rest must remain as it is so that the email inboxes and the web space work.

    Now you have to wait until the DNS changes have been propagated everywhere. This can take up to 24 hours. You can test it in the terminal with ping your-domain.com. If the IP address of your server comes back, the domain is ready.

    Step 4: Reinstall server

    You can now log in to the Server control panel and select your server. Under “Media” and then “Images” you can select a new operating system. I recommend Ubuntu 22.04 LTS (updates until 2027).

    Reinstall Netcup Server

    During the installation you should create a user.

    Step 5: Establish SSH connection

    After the installation is complete, you can connect to your server via SSH. We use VSCode for this. Install the Remote-SSH-Plugin and click on the icon in the bottom left corner. There you can select “Remote-SSH: Connect to Host…” and configure your SSH connection. The command ssh user@ip should also connect you.

    Once the connection is established, you can open your user’s home folder in Explorer and edit your files there. You can also use the terminal to execute commands:

    sudo apt update
    sudo apt upgrade

    Step 6: Install Docker and Docker-Compose

    Next, we install Docker. To do this, we execute the following commands:

    sudo apt-get install ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc
    
    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
      $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    Step 7: Prepare Caddy

    We use Caddy as a reverse proxy to make Paperless-ngx and Wireguard accessible via HTTPS and later reject external connections.

    We first need a network to connect Caddy to the other containers:

    sudo docker network create proxy

    Now we create a folder for Caddy and create the files:

    mkdir caddy
    cd caddy
    mkdir data config
    touch docker-compose.yml Caddyfile

    In the docker-compose.yml file we enter the following:

    version: "3.7"
    
    networks:
        proxy:
            external: true
            name: proxy
    
    services:
        caddy:
            image: caddy:2
            container_name: caddy
            restart: unless-stopped
            ports:
                - 80:80
                - 443:443
            volumes:
                - ./data:/data
                - ./config:/config
                - ./caddyfile:/etc/caddy/Caddyfile:ro
            networks:
                - proxy

    Step 8: Install WG-Easy

    Now we install WG-Easy to establish a secure connection to our server. To do this, we execute the following commands:

    cd ~
    mkdir wireguard
    cd wireguard
    mkdir data
    touch docker-compose.yml

    We enter the following into the docker-compose.yml file:

    version: "3.8"
    
    networks:
        proxy:
            name: proxy
            external: true
    
    services:
        wg-easy:
            environment:
                - WG_HOST=wireguard.pixan.de
                - PASSWORD=somepassword
        image: ghcr.io/wg-easy/wg-easy:10
            container_name: wg-easy
            volumes:
                - ./data:/etc/wireguard
        ports:
            - "51820:51820/udp"
        restart: unless-stopped
        cap_add:
            - NET_ADMIN
            - SYS_MODULE
        sysctls:
            - net.ipv4.ip_forward=1
            - net.ipv4.conf.all.src_valid_mark=1
        networks:
            - proxy

    Change the environment variables WG_HOST and PASSWORD according to your wishes. Now the container can be started:

    sudo docker-compose up -d

    Step 9: Configure proxy

    Now we enter the configuration for Caddy. To do this, we open the Caddyfile file and enter the following:

    {
        acme_ca https://acme-v02.api.letsencrypt.org/directory
        email mail@domain.com
    }
    
    wireguard.pixan.com {
        reverse_proxy wg-easy:51821
    }

    Replace the e-mail address and the domain according to your wishes. Now Caddy can be started:

    sudo docker-compose up -d

    Step 10: Establish Wireguard connection

    Now you can visit the domain you have just defined. The WG Easy website should appear there. A new client can be created via the interface. The configuration file can be downloaded (or displayed as a QR code).

    WG-Easy

    You can import the configuration file to your device. You will need the Wireguard app for this. Once you have imported the configuration file, you can establish the connection.

    Step 11: Block external connections

    Finally, we block external connections to our server. To do this, we change the Caddyfile:

    {
        acme_ca https://acme-v02.api.letsencrypt.org/directory
        email mail@domain.com
    }
    
    wireguard.pixan.com {
        @blocked not remote_ip private_ranges
        respond @blocked 403
        reverse_proxy wg-easy:51821
    }

    And we restart Caddy:

    cd ~/caddy
    sudo docker-compose down
    sudo docker-compose up -d

    Step 12: Install Paperless-ngx

    Now we can install Paperless-ngx. To do this, we create a new folder and create the files:

    cd ~
    mkdir paperless
    cd paperless
    mkdir consume db export media data redis db-backup
    touch docker-compose.yml

    We still need our user ID for the permissions:

    id username

    The output should look like this:

    uid=1000(username) gid=1000(username) groups=1000(user)

    We enter the following in the docker-compose.yml file:

    version: "3.4"
    
    networks:
        internal:
            external: false
        proxy:
            name: proxy
            external: true
    
    services:
        broker:
            container_name: paperless-redis
            image: redis:7
            networks:
                - internal
            restart: unless-stopped
            volumes:
                - ./redis:/data
    
        db:
            container_name: paperless-db
            image: postgres:16
            networks:
                - internal
            restart: unless-stopped
            volumes:
                - ./db:/var/lib/postgresql/data
            environment:
                POSTGRES_DB: paperless
                POSTGRES_USER: paperless
                POSTGRES_PASSWORD: password # change in three places if necessary
    
        webserver:
            container_name: paperless
            image: ghcr.io/paperless-ngx/paperless-ngx:2.4
            networks:
                - internal
                - proxy
            restart: unless-stopped
            depends_on:
                - db
                - broker
            healthcheck:
                test: ["CMD", "curl", "-f", "http://localhost:8000"]
                interval: 30s
                timeout: 10s
                retries: 5
            volumes:
                - ./data:/usr/src/paperless/data
                - ./media:/usr/src/paperless/media
                - ./export:/usr/src/paperless/export
                - ./consume:/usr/src/paperless/consume
            environment:
                PAPERLESS_REDIS: redis://broker:6379
                PAPERLESS_DBHOST: db
                PAPERLESS_DBPASS: password # change in three places if necessary
                USERMAP_UID: 1000 # change if necessary
                USERMAP_GID: 1000 # change if necessary
                PAPERLESS_OCR_LANGUAGES: eng deu # change if necessary
                PAPERLESS_SECRET_KEY: pa6lHUuc1W8PQWdsP6wXViH1cJoKV38zj9ixRkDeTv3Q0iX8O9pti6tr5edgeheim # change if necessary
                PAPERLESS_ALLOWED_HOSTS: "localhost,paperless.pixan.de" # change
                PAPERLESS_TIME_ZONE: Europe/Berlin # change if necessary
                PAPERLESS_OCR_LANGUAGE: eng # change if necessary
                PAPERLESS_FILENAME_FORMAT: "{created_year}/{correspondent}/{title}" # change if necessary
                PAPERLESS_TIKA_ENABLED: 1
                PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000/
                PAPERLESS_TIKA_ENDPOINT: http://tika:9998
                PAPERLESS_URL: "https://paperless.pixan.de" # change
    
        db-backup:
            container_name: paperless-db-backup
            image: postgres:16
            volumes:
                - ./db-backup:/dump
                - /etc/localtime:/etc/localtime:ro
            environment:
                PGHOST: db
                PGDATABASE: paperless
                PGUSER: paperless
                PGPASSWORD: einPasswort # change in three places if necessary
                BACKUP_NUM_KEEP: 10
                BACKUP_FREQUENCY: 7d
            entrypoint: |
                bash -c 'bash -s <<EOF
                trap "break;exit" SIGHUP SIGINT SIGTERM
                sleep 2m
                while /bin/true; do
                    pg_dump -Fc > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.psql
                    (ls -t /dump/dump*.psql|head -n $$BACKUP_NUM_KEEP;ls /dump/dump*.psql)|sort|uniq -u|xargs rm -- {}
                    sleep $$BACKUP_FREQUENCY
                done
                EOF'
            networks:
                - internal
    
        gotenberg:
            image: gotenberg/gotenberg:8
            restart: unless-stopped
            environment:
                CHROMIUM_DISABLE_ROUTES: 1
            command:
                - "gotenberg"
                - "--chromium-disable-javascript=true"
                - "--chromium-allow-list=file:///tmp/.*"
            networks:
                - internal
    
        tika:
            image: apache/tika:2.9.1.0
            restart: unless-stopped
            networks:
                - internal

    Adapt the environment variables to your circumstances. The PAPERLESS_SECRET_KEY should be a random string. The PAPERLESS_URL should be your domain. The PAPERLESS_ALLOWED_HOSTS should contain your domain and localhost.

    Now the container can be started:

    sudo docker-compose up -d

    Step 13: Add user

    We need a user to be able to log into Paperless-ngx. To do this, we execute the following command:

    sudo docker exec -it paperless python manage.py createsuperuser

    Or:

    sudo docker exec -it paperless sh
    python manage.py createsuperuser
    exit

    Step 14: Configure paperless-ngx proxy

    Finally, we enter the configuration for Paperless-ngx in the caddyfile:

    {
        acme_ca https://acme-v02.api.letsencrypt.org/directory
        email mail@domain.com
    }
    
    wireguard.pixan.com {
        @blocked not remote_ip private_ranges
        respond @blocked 403
        reverse_proxy wg-easy:51821
    }
    
    paperless.pixan.de {
        @blocked not remote_ip private_ranges
        respond @blocked 403
        reverse_proxy paperless:8000
    }

    And we restart Caddy:

    cd ~/caddy
    sudo docker-compose down
    sudo docker-compose up -d

    Step 15: Configure Paperless-ngx

    Now you can log in to Paperless-ngx and adjust the configuration. To do this, go to your domain and log in with your user. There you can adjust the settings and add documents.

    It is important to set up the mail server so that you can archive files directly via email.

    e-mail server

    Don’t forget to set up a rule for this as well.

    You can also add more users and give them rights.

    Step 16: Archive documents

    Now you can add and archive documents. You have several options:

    • Drag & drop files into the user interface
    • Place files in the consume folder on the server (e.g. via SFTP)
    • Send files by email to your Paperless ngx address
    • Use Paperless Share on your Android smartphone

    PDFs, Office documents, text files and emails are supported.

    Step 17: Back up Paperless-ngx

    Finally, you should back up your Paperless-ngx instance. To do this, you can back up the database and the files in the Media folder.

    You can also use the document_exporter to export the documents.

    sudo docker exec -it paperless python manage.py document_exporter

    The export folder must then be backed up. This is possible with Borg or Rclone, for example.

    Step 18: Update

    You should install updates regularly.

    Update the server:

    sudo apt update
    sudo apt upgrade

    Update images:

    cd ~/caddy
    sudo docker-compose pull
    sudo docker-compose down && sudo docker-compose up -d
    cd ~/wireguard
    sudo docker-compose pull
    sudo docker-compose down && sudo docker-compose up -d
    cd ~/paperless
    sudo docker-compose pull
    sudo docker-compose down && sudo docker-compose up -d

    You can also use something like Watchtower to do this automatically. If the tags are set according to Semvar, an update should not cause any problems.

    Basically, the first number indicates the main version. This may contain major changes that can lead to incompatibilities. The second number indicates changes (new functionalities) that are downward compatible. The third number indicates bug fixes and security updates that are backwards compatible.

    In Paperless, version 2.4 is used according to the configuration created above. This can be 2.4.0 as well as 2.4.1 etc. If you want to use 2.5, you have to adapt the image in the docker-compose.yml file.

    You must first adapt the image in the docker-compose.yml file.

    With Postgres, you should not simply update the version without performing a migration.

    It is not necessary to use the latest major version as long as there are security updates. You must also check whether the latest version is supported at all.

    Conclusion

    Congratulations! You have installed Paperless-ngx on a VPS. Now you can access your documents from anywhere and manage them securely. If you have any questions or comments, feel free to leave them in the comments.


    This website uses cookies. These are necessary for the functionality of the website. You can find more information in the privacy policy