Self-host Paperless-ngx with Docker Compose
Selbstgehostetes Dokumentenmanagement, das Papierkram in ein durchsuchbares Archiv verwandelt.
paperless-ngx
gotenberg
gotenberg/gotenberg:8.25
postgres
postgres:18.3-alpine3.23
postgres-postgres-data-init
busybox
postgres-postgres-socket-init
busybox
redis
redis:7
redis-redis-data-init
busybox
tika
apache/tika:latest
The steps below take a few minutes end to end.
Requirements
You'll need these installed on the machine you're deploying to:
Docker
Packages Paperless-ngx and everything it depends on into an isolated container, so it runs the same way on your machine as it does everywhere else.
Install guideDocker Compose
Reads docker-compose.ymland starts everything in it together. Ships with Docker Desktop. On Linux servers it's usually a separate install.
Install guide1. Docker compose setup and file
Create a folder for Paperless-ngx and save the file below into it as docker-compose.yml. It describes every container the stack needs — Paperless-ngxitself and any supporting services, such as its database — along with the ports, volumes and environment variables each one uses. You'll also need an empty .env file in the same folder; Docker Compose reads it automatically and uses it to fill in the ${VARIABLE}references you'll see in the file below.
docker-compose.yml
version: "3.9"
services:
gotenberg:
image: gotenberg/gotenberg:8.25
restart: unless-stopped
network_mode: service:paperless-ngx
command:
- gotenberg
- --chromium-disable-javascript=true
- --chromium-allow-list=file:///tmp/.*
paperless-ngx:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped
ports:
- 8000:8000
environment:
PAPERLESS_ADMIN_MAIL: admin@bitflake.app
PAPERLESS_ADMIN_PASSWORD: Admin123
PAPERLESS_ADMIN_USER: admin
PAPERLESS_DBHOST: postgres
PAPERLESS_DBNAME: app
PAPERLESS_DBPASS: ${RANDOM_PG_PASSWORD}
PAPERLESS_DBPORT: "5432"
PAPERLESS_DBUSER: app
PAPERLESS_REDIS: redis://:${RANDOM_REDIS_PASSWORD}@redis:6379/0
PAPERLESS_SECRET_KEY: ${RANDOM_PAPERLESS_SECRET_KEY}
PAPERLESS_TIKA_ENABLED: "1"
PAPERLESS_TIKA_ENDPOINT: http://localhost:9998
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://localhost:3000
PAPERLESS_URL: http://paperless-ngx.localhost:8000
RANDOM_REDIS_PASSWORD: ${RANDOM_REDIS_PASSWORD}
volumes:
- data:/usr/src/paperless/data
- media:/usr/src/paperless/media
depends_on:
postgres:
condition: service_started
redis:
condition: service_started
postgres:
image: postgres:18.3-alpine3.23
restart: unless-stopped
environment:
PGDATA: /var/lib/postgresql/data
POSTGRES_PASSWORD: ${RANDOM_PG_PASSWORD}
POSTGRES_USER: app
volumes:
- postgres-data:/var/lib/postgresql/data
- postgres-socket:/var/run/postgresql
depends_on:
postgres-postgres-data-init:
condition: service_completed_successfully
postgres-postgres-socket-init:
condition: service_completed_successfully
postgres-postgres-data-init:
image: busybox
volumes:
- postgres-data:/var/lib/postgresql/data
command:
- chown
- 70:70
- /var/lib/postgresql/data
postgres-postgres-socket-init:
image: busybox
volumes:
- postgres-socket:/var/run/postgresql
command:
- chown
- 70:70
- /var/run/postgresql
redis:
image: redis:7
restart: unless-stopped
environment:
REDIS_PASSWORD: ${RANDOM_REDIS_PASSWORD}
volumes:
- redis-data:/data
depends_on:
redis-redis-data-init:
condition: service_completed_successfully
entrypoint:
- sh
- -c
command:
- redis-server --requirepass $$REDIS_PASSWORD
redis-redis-data-init:
image: busybox
volumes:
- redis-data:/data
command:
- chown
- 999:999
- /data
tika:
image: apache/tika:latest
restart: unless-stopped
network_mode: service:paperless-ngx
volumes:
- tika-tmp:/tmp
volumes:
data: null
media: null
postgres-data: null
postgres-socket: null
redis-data: null
tika-tmp: null
Volumes
Paperless-ngx stores its data in named Docker volumes, so it survives container restarts and updates:
- data mounted at /usr/src/paperless/data: Search index, classification model, and application logs
- media mounted at /usr/src/paperless/media: Original and archived (OCR'd PDF/A) versions of consumed documents
2. Secret generation
Paperless-ngx needs a few randomly generated secrets — for example, database passwords or an internal session key — before it can start. These are referenced from docker-compose.ymlabove but don't live in it, so they need to end up in your .env file. Pick one of the two options below.
Generating secrets…
3. Start Paperless-ngx with Docker Compose
From the folder with docker-compose.yml and .env, run:
Terminal
Start Paperless-ngx and all its supporting services in the background.
docker compose up -dThe -d flag runs the stack in the background so it keeps running after you close the terminal. Docker will pull the images the first time, which can take a minute or two.
To check on it afterwards: docker compose ps shows whether containers are healthy, and docker compose logs -f follows their logs if something looks wrong. Once it's running, open http://localhost:8000 in your browser.