How to Deploy Paperless-ngx – Open-Source Document Management System

Updated on 13 April, 2026
Deploy Paperless-ngx with Docker Compose, enable OCR search, and secure access with HTTPS.
How to Deploy Paperless-ngx – Open-Source Document Management System header image

Paperless-ngx is an open-source document management system that transforms physical documents into a searchable archive. It uses Optical Character Recognition (OCR) to extract text from scanned images and PDFs, enabling full-text search across your document library. The web-based interface provides tagging, custom fields, and automated document processing workflows.

This article explains how to deploy Paperless-ngx on a Linux server using Docker Compose. The setup includes PostgreSQL for metadata storage, Redis for task management, and Traefik as a reverse proxy for automatic HTTPS with Let's Encrypt.

Prerequisites

Before you begin, you need to:

Set Up the Directory Structure, Configuration, and Environment Variables

Paperless-ngx requires persistent directories for document storage, database files, and TLS certificates. Environment variables configure domain routing, database credentials, and application behavior.

  1. Create the required project directories.

    console
    $ mkdir -p ~/paperless-ngx/{data,media,export,consume,pgdata}
    
  2. Navigate to the project directory.

    console
    $ cd ~/paperless-ngx
    
  3. Create an environment file to store configuration values.

    console
    $ nano .env
    
  4. Add the following environment variables:

    ini
    DOMAIN=paperless.example.com
    LETSENCRYPT_EMAIL=admin@example.com
    
    PAPERLESS_SECRET_KEY=CHANGE_TO_RANDOM_STRING
    PAPERLESS_URL=https://paperless.example.com
    PAPERLESS_TIME_ZONE=UTC
    PAPERLESS_OCR_LANGUAGE=eng
    PAPERLESS_DBPASS=STRONG_PASSWORD_HERE
    
    POSTGRES_DB=paperless
    POSTGRES_USER=paperless
    POSTGRES_PASSWORD=STRONG_PASSWORD_HERE
    

    Replace:

    • paperless.example.com with your registered domain name.
    • admin@example.com with your email address for certificate notifications.
    • CHANGE_TO_RANDOM_STRING with a random 32+ character string for Django security.
    • STRONG_PASSWORD_HERE with a strong database password (use the same value for both PAPERLESS_DBPASS and POSTGRES_PASSWORD).

    Save and close the file.

Deploy with Docker Compose

The Docker Compose stack runs Paperless-ngx with PostgreSQL for metadata storage and Redis for task queuing. Traefik handles TLS termination and automatic certificate provisioning.

  1. Create the Docker Compose file.

    console
    $ nano docker-compose.yaml
    
  2. Add the following manifest:

    yaml
    services:
      traefik:
        image: traefik:v3.6
        container_name: traefik
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
          - "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
          - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "./letsencrypt:/letsencrypt"
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
        restart: unless-stopped
    
      db:
        image: postgres:16
        container_name: paperless-db
        environment:
          POSTGRES_DB: ${POSTGRES_DB}
          POSTGRES_USER: ${POSTGRES_USER}
          POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
        volumes:
          - "./pgdata:/var/lib/postgresql/data"
        healthcheck:
          test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}"]
          interval: 10s
          timeout: 5s
          retries: 5
        restart: unless-stopped
    
      redis:
        image: redis:7
        container_name: paperless-redis
        restart: unless-stopped
    
      paperless:
        image: ghcr.io/paperless-ngx/paperless-ngx:2.20.6
        container_name: paperless
        depends_on:
          db:
            condition: service_healthy
        environment:
          PAPERLESS_REDIS: redis://redis:6379
          PAPERLESS_DBHOST: db
          PAPERLESS_SECRET_KEY: ${PAPERLESS_SECRET_KEY}
          PAPERLESS_URL: ${PAPERLESS_URL}
          PAPERLESS_TIME_ZONE: ${PAPERLESS_TIME_ZONE}
          PAPERLESS_OCR_LANGUAGE: ${PAPERLESS_OCR_LANGUAGE}
          PAPERLESS_DBPASS: ${PAPERLESS_DBPASS}
        volumes:
          - "./data:/usr/src/paperless/data"
          - "./media:/usr/src/paperless/media"
          - "./export:/usr/src/paperless/export"
          - "./consume:/usr/src/paperless/consume"
        expose:
          - "8000"
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.paperless.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.paperless.entrypoints=websecure"
          - "traefik.http.routers.paperless.tls.certresolver=letsencrypt"
          - "traefik.http.services.paperless.loadbalancer.server.port=8000"
        restart: unless-stopped
    

    Save and close the file.

    In the above manifest:

    • services: Launches four containers managed by Docker Compose:
      • traefik: Acts as the reverse proxy, router, and TLS termination layer.
      • db: Hosts the PostgreSQL database for storing document metadata and user accounts.
      • redis: Provides a message broker for background task processing and caching.
      • paperless: Runs the Paperless-ngx application server with OCR processing.
    • image: Specifies the container image for each service.
    • container_name: Assigns fixed names to containers for easier identification in logs and management commands.
    • command (Traefik): Configures Docker discovery, HTTP and HTTPS entry points, automatic HTTP-to-HTTPS redirection, and Let's Encrypt certificate provisioning via HTTP-01 challenge.
    • ports (Traefik): Publishes ports 80 and 443 on the host for external traffic handling.
    • environment: Passes configuration variables from the .env file to each service.
    • healthcheck (db): Verifies PostgreSQL is ready to accept connections before Paperless starts.
    • depends_on (paperless): Delays the Paperless container startup until the db container passes its healthcheck, using the condition: service_healthy constraint to prevent connection errors during initialization.
    • expose (paperless): Makes port 8000 accessible to Traefik without publishing it directly to the host.
    • volumes:
      • The ./letsencrypt bind mount stores TLS certificates persistently across container rebuilds.
      • The Docker socket (/var/run/docker.sock) grants Traefik the ability to discover services and update routes dynamically.
      • Host bind mounts (./data, ./media, ./export, ./consume, ./pgdata) persist application data, uploaded documents, exports, consumption directory, and database files.
    • labels (paperless): Registers the container with Traefik and defines routing rules for HTTPS traffic based on the domain name.
    • restart: unless-stopped: Ensures containers recover automatically after failures or system restarts unless manually stopped.
  3. Launch the containers in detached mode.

    console
    $ docker compose up -d
    
  4. Verify that all services are running.

    console
    $ docker compose ps
    

    Verify from the output that all containers are in the running state and report a healthy status.

  5. View the logs for the services.

    console
    $ docker compose logs
    

    For more information on managing a Docker Compose stack, see the How To Use Docker Compose article.

  6. Create a superuser account to access the dashboard.

    console
    $ docker compose exec -it paperless python3 manage.py createsuperuser
    

    Follow the prompts to set a username, email address, and password for the administrator account.

Access and Configure Paperless-ngx

The Paperless-ngx web interface provides document upload, tagging, search, and automation workflows. After logging in with the superuser account, you can configure correspondents, document types, and custom fields.

  1. Open your web browser and navigate to Paperless-ngx. Replace paperless.example.com with your registered domain name.

    https://paperless.example.com
  2. Enter the superuser credentials created in the previous step and click Login.

  3. The dashboard loads with the following panels:

    • Documents: The main view showing uploaded documents in a grid or list format.
    • Sidebar: Quick filters for tags, correspondents, document types, and storage paths.
    • Search: Full-text search across all document content extracted via OCR.
    • Upload: Document upload interface accessible from the top navigation bar.

Upload and Process a Document

Paperless-ngx automatically processes uploaded documents using OCR to extract searchable text. The following example demonstrates uploading a scanned document.

  1. Click Upload documents in the top-right corner of the dashboard.

  2. Select a PDF or image file from your local machine and click Open to begin the upload.

    Paperless-ngx automatically queues the document for OCR processing using Tesseract with the language defined in your environment configuration. Once processing completes (typically 5-30 seconds depending on document size), the document appears in the main dashboard view.

  3. Click the document thumbnail to open the detail view.

  4. Verify that the Content tab displays the extracted text from the OCR process.

    Paperless-ngx document viewer showing OCR-extracted text from a scanned image

    The interface shows the original document on the right with the OCR-extracted text on the left, confirming that the document is now searchable.

Conclusion

You have successfully deployed Paperless-ngx with Docker Compose and enabled automatic HTTPS using Traefik. The platform now provides OCR-based document processing, full-text search, and persistent storage backed by PostgreSQL and Redis. Your configuration ensures data remains intact across container restarts and updates. For advanced configuration options and feature details, visit the official Paperless-ngx documentation.

Comments