Running Containers on a Synology DS1821+: Install Paperless-ngx with Portainer

Introduction
If you’ve ever struggled with piles of receipts, contracts, or scanned documents, Paperless-ngx can help bring order to the chaos. It’s a powerful, self-hosted document management system that automatically organizes, indexes, and makes your files searchable.
In this guide, we’ll walk through installing Paperless-ngx on a Synology DS1821+ (or similar NAS) using Portainer and Docker Compose. By the end, you’ll have a paperless workflow that can scan, OCR, and archive documents securely on your NAS.
What You’ll Need
- A Synology NAS with Docker and Portainer installed
- Shared folders for persistent storage (e.g.,
/volume1/docker/paperless
) - At least 2GB of free RAM for smooth performance
- A scanner or a folder where digital PDFs/images are stored
Step 1: Prepare Storage Folders
First, create the necessary folders on your NAS to store data:
- Open File Station in DSM.
- Inside your
docker
shared folder, create:paperless_data
paperless_media
paperless_consume
The consume folder is where you’ll drop new documents—Paperless-ngx will automatically import and process them.
Step 2: Create a New Stack in Portainer
- Log into Portainer (
http://<NAS-IP>:9000
). - Click Stacks → + Add Stack.
- Name your stack:
paperless
.
Step 3: Add the Docker Compose File
Paste the following Docker Compose definition:
---
networks:
internal:
external: false
services:
broker:
container_name: paperless-redis
image: redis:7
# If you prefer to use version 6.0
# image: redis:6.0
networks:
- internal
volumes:
# Change to your correct path(s)
- /volume1/paperless/redis:/data
# - /volume2/paperless/redis:/data
restart: unless-stopped
user: "1000:1000" # Your Paperless user/group IDs
sysctls:
- net.core.somaxconn=511
cap_add:
- SYS_RESOURCE
deploy:
resources:
limits:
memory: 256M
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 5s
retries: 3
db:
container_name: paperless-db
image: postgres:16
# Do not simply upgrade or downgrade, as the database will not load anymore.
networks:
- internal
restart: unless-stopped
volumes:
# Enter the correct path here
- /volume1/paperless/db:/var/lib/postgresql/data
# - /volume2/paperless/db:/var/lib/postgresql/data
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: PAPERLESSDB_PASS # Replace with your password
deploy:
resources:
limits:
memory: 512M
healthcheck:
test: ["CMD", "pg_isready", "-U", "paperless"]
interval: 30s
timeout: 5s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
webserver:
container_name: paperless
# image: ghcr.io/paperless-ngx/paperless-ngx:2.13
image: ghcr.io/paperless-ngx/paperless-ngx:latest
networks:
# If the Proxy Manager is on the Synology, then the network from it should also be entered here, instead of opening a port.
- internal
restart: unless-stopped
depends_on:
- db
- broker
ports:
# Delete this part if the Proxy Manager is on the Synology.
# Otherwise, select a port here that is free.
- 8010:8000
# - 8011:8000
# - 8012:8000
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000"]
interval: 30s
timeout: 10s
retries: 5
volumes:
# Enter the correct paths here
- /volume1/paperless/data:/usr/src/paperless/data
- /volume1/paperless/media:/usr/src/paperless/media
- /volume1/paperless/export:/usr/src/paperless/export
- /volume1/homes/timw/paperless-Inbox:/usr/src/paperless/consume
environment:
SSL_CERT_DIR: /etc/ssl/certs/
# PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_REDIS: redis://paperless-redis:6379
PAPERLESS_DBHOST: db
PAPERLESS_DBPASS: PAPERLESSDB_PASS # This is the password from above
USERMAP_UID: 1000 # UserID for the docker user
USERMAP_GID: 1000 # GroupID for the docker user
PAPERLESS_OCR_LANGUAGES: eng deu
# Enter a random key here if you want to make Paperless accessible from outside.
PAPERLESS_SECRET_KEY: PAPERLESS_SECRET
# Enter your own domain behind localhost here if you are using a proxy host, otherwise delete this environment variable.
#PAPERLESS_ALLOWED_HOSTS: "localhost,paperless.domain.de"
PAPERLESS_TIME_ZONE: Europe/London
PAPERLESS_OCR_LANGUAGE: eng
# Adjust here if you want a different folder structure
PAPERLESS_FILENAME_FORMAT: "{{created_year}}/{{ created_month }}/{{correspondent}}/{{title}}"
# Omit the next three lines if you do not want to use Tika/Gotenberg.
PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://paperless-gotenberg:3000/ #or http://gotenberg:3000/forms/libreoffice/convert#
PAPERLESS_TIKA_ENDPOINT: http://paperless-tika:9998
#PAPERLESS_URL: "https://paperless.domain.de" # Remove or adjust if not using a proxy
PAPERLESS_EMAIL_PARSE_DEFAULT_LAYOUT: 3
deploy:
resources:
limits:
memory: 2048M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
db-backup:
container_name: paperless-db-backup
# Possibly adjust the image to match the one above
image: postgres:16
volumes:
# Enter the correct path here
- /volume1/paperless/db-backup:/dump
- /etc/localtime:/etc/localtime:ro
environment:
PGHOST: db
PGDATABASE: paperless
PGUSER: paperless
PGPASSWORD: PAPERLESSDB_PASS # This is the password from above
BACKUP_NUM_KEEP: 10
BACKUP_FREQUENCY: 7d # Every 7 days, can be adjusted
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
deploy:
resources:
limits:
memory: 256M
# Omit this part if you do not want conversion of Office documents, emails.
gotenberg:
container_name: paperless-gotenberg
image: gotenberg/gotenberg:8
restart: unless-stopped
# environment:
# CHROMIUM_DISABLE_ROUTES: 1
command:
- "gotenberg"
- "--chromium-disable-javascript=true"
- "--chromium-allow-list=file:///tmp/.*"
- "--api-timeout=600s"
- "--libreoffice-start-timeout=300s"
- "--libreoffice-restart-after=0"
networks:
- internal
deploy:
resources:
limits:
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
tika:
container_name: paperless-tika
image: apache/tika:2.9.2.1
restart: unless-stopped
networks:
- internal
deploy:
resources:
limits:
memory: 512M
Notes:
- Adjust
/volume1/docker/...
paths if your shared folder is elsewhere. - Update the
PAPERLESS_DBPASS
with a secure password.
Step 4: Deploy the Stack
- Scroll down and click Deploy the stack.
- Wait while the containers for Redis, PostgreSQL, and Paperless-ngx start up.
- In Portainer, verify all containers are running (
paperless-web
,paperless-db
,paperless-redis
).
Step 5: Access Paperless-ngx
Open your browser and go to:
http://<NAS-IP>:8000
- Log in with the default credentials (admin/admin).
- Immediately change the password under User Settings.
Step 6: Start Organizing
- Drop scanned documents or PDFs into the consume folder (
/volume1/docker/paperless_consume
). - Paperless-ngx will OCR, tag, and archive them automatically.
- Use the web UI to search, categorize, and download documents.
Optional Improvements
- HTTPS Access: Use DSM’s built-in Reverse Proxy to secure Paperless with a domain and SSL certificate.
- Automated Scans: Configure your scanner or phone app to save directly into the
consume
folder. - Link Paperless-ngx to firefly iii with Node Red.
Conclusion
By installing Paperless-ngx on your Synology NAS, you’ve taken the first step toward a fully digital, searchable, and organized archive of your documents. Combined with Synology’s storage reliability, Paperless-ngx makes going paperless secure and hassle-free.
About the author
Tim Wilkes is a UK-based security architect with over 15 years of experience in electronics, Linux, and Unix systems administration. Since 2021, he's been designing secure systems for a telecom company while indulging his passions for programming, automation, and 3D printing. Tim shares his projects, tinkering adventures, and tech insights here - partly as a personal log, and partly in the hopes that others will find them useful.
Want to connect or follow along?
LinkedIn: [phpsytems]
Twitter / X: [@timmehwimmy]
Mastodon: [@timmehwimmy@infosec.exchange]
If you've found a post helpful, consider supporting the blog - it's a part-time passion that your support helps keep alive.
⚠️ Disclaimer
This post may contain affiliate links. If you choose to purchase through them, I may earn a small commission at no extra cost to you. I only recommend items and services I’ve personally read or used and found valuable.
As an Amazon Associate I earn from qualifying purchases.