How to install Paperless-ngx on a VPS
Install document management Paperless-ngx with Docker on a VPS.
Table of Contents
- Introduction
- Step 1: Rent a server
- Step 2: Rent a domain
- Step 3: Configure domain
- Step 4: Reinstall server
- Step 5: Establish SSH connection
- Step 6: Install Docker and Docker-Compose
- Step 7: Prepare Caddy
- Step 8: Install WG-Easy
- Step 9: Configure proxy
- Step 10: Establish Wireguard connection
- Step 11: Block external connections
- Step 12: Install Paperless-ngx
- Step 13: Add user
- Step 14: Configure paperless-ngx proxy
- Step 15: Configure Paperless-ngx
- Step 16: Archive documents
- Step 17: Back up Paperless-ngx
- Step 18: Update
- Conclusion
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
Aspect | Details |
---|---|
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 & Software | Docker for easy installation, Caddy as reverse proxy, Wireguard for secure connection. |
Prerequisites | Requires 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.
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:
- rent an additional domain
- 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β.
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).
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).
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.
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.