Document Management
    OCR + Full-text

    Deploy Paperless-ngx on a VPS

    Self-host Paperless-ngx, a document management system with OCR, tagging, and full-text search, on a RamNode VPS with the official Docker Compose stack.

    Paperless-ngx is a document management system that scans, OCRs, tags, and indexes your paperwork. This is a heavier stack than Apprise — it uses Redis, a database, and optionally Gotenberg/Tika for Office document conversion. This guide uses the official Docker Compose setup.

    1. Prerequisites

    • A RamNode VPS with at least 2 vCPUs / 4 GB RAM and 40+ GB disk (OCR and indexing are resource-hungry; more documents = more RAM/disk)
    • Ubuntu 22.04/24.04
    • A domain name (recommended, since Paperless benefits a lot from being reachable over HTTPS for mobile scanning apps)

    2. Initial server setup

    shell
    ssh youruser@your-vps-ip
    sudo apt update && sudo apt upgrade -y
    sudo timedatectl set-timezone UTC

    Firewall:

    shell
    sudo apt install -y ufw
    sudo ufw allow OpenSSH
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw enable

    3. Install Docker and Docker Compose

    shell
    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
    sudo usermod -aG docker $USER
    newgrp docker

    4. Download the official Paperless-ngx Compose files

    shell
    mkdir -p ~/paperless-ngx
    cd ~/paperless-ngx
    
    curl -O https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.sqlite.yml
    curl -O https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/.env
    curl -o docker-compose.yml docker-compose.sqlite.yml

    There are a few variants available upstream:

    • docker-compose.sqlite.yml — simplest, fine for small/single-user setups
    • docker-compose.postgres.yml — recommended if you want more robustness or expect a large document count

    For a small-to-medium personal/team install, SQLite is fine and simplest. If you want Postgres instead, download docker-compose.postgres.yml in place of the sqlite one and add a db service block (the file already includes it).

    5. Configure environment variables

    Edit the .env file:

    shell
    nano .env

    Set at least:

    shell
    PAPERLESS_URL=https://paperless.yourdomain.com
    PAPERLESS_SECRET_KEY=generate-a-long-random-string-here
    PAPERLESS_TIME_ZONE=America/New_York
    PAPERLESS_OCR_LANGUAGE=eng
    USERMAP_UID=1000
    USERMAP_GID=1000

    Generate a strong secret key:

    shell
    openssl rand -base64 48

    If you're using multiple OCR languages (e.g., English + Spanish), set:

    shell
    PAPERLESS_OCR_LANGUAGE=eng+spa

    6. Review the compose file

    Open docker-compose.yml and confirm the webserver service maps port 8000:

    shell
      webserver:
        image: ghcr.io/paperless-ngx/paperless-ngx:latest
        restart: unless-stopped
        depends_on:
          - db
          - broker
        ports:
          - "8000:8000"
        ...

    The stack typically includes:

    • broker — Redis, used for the task queue
    • db — Postgres or SQLite volume
    • webserver — the Paperless-ngx app itself
    • gotenberg and tika — optional, enable Office document (docx/xlsx) to PDF conversion

    If you want Office file support, uncomment/add the gotenberg and tika services (present in the official compose templates) and add these to the webserver's environment:

    shell
    PAPERLESS_TIKA_ENABLED=1
    PAPERLESS_TIKA_GOTENBERG_ENDPOINT=http://gotenberg:3000
    PAPERLESS_TIKA_ENDPOINT=http://tika:9998

    7. Start the stack

    shell
    docker compose up -d

    Watch the first boot (it runs DB migrations):

    shell
    docker compose logs -f webserver

    8. Create your admin superuser

    shell
    docker compose exec webserver python manage.py createsuperuser

    Follow the prompts for username, email, and password.

    9. Access Paperless

    Visit http://your-vps-ip:8000 and log in with the superuser account you just created.

    10. Put it behind HTTPS with Caddy

    shell
    sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    sudo apt update
    sudo apt install -y caddy

    /etc/caddy/Caddyfile:

    shell
    paperless.yourdomain.com {
        reverse_proxy localhost:8000
    }
    shell
    sudo systemctl restart caddy
    sudo ufw delete allow 8000

    Make sure PAPERLESS_URL in your .env matches this HTTPS domain, then restart:

    shell
    docker compose down
    docker compose up -d

    11. Document intake

    Paperless watches a "consume" folder. Files dropped in ~/paperless-ngx/consume (mapped in the compose file) get picked up, OCR'd, and filed automatically. You can also:

    • Email documents to an inbox Paperless monitors (configure PAPERLESS_EMAIL_* variables)
    • Use the mobile app or web upload
    • Use tools like a scanner's "scan to folder/SMB" feature pointed at the consume directory

    12. Backups

    Paperless has a built-in exporter that dumps documents, thumbnails, and metadata:

    shell
    docker compose exec webserver document_exporter ../export

    Back up these three things regularly:

    1. The consume, media, and export directories
    2. The database volume (or the sqlite file under data/)
    3. Your .env file (contains your secret key)
    shell
    tar czf paperless-backup-$(date +%F).tar.gz ~/paperless-ngx/data ~/paperless-ngx/media ~/paperless-ngx/export ~/paperless-ngx/.env

    13. Updating

    shell
    cd ~/paperless-ngx
    docker compose pull
    docker compose up -d

    Check the Paperless-ngx changelog before major version jumps — occasionally there are one-time migration steps.