Paperless-ngx convierte esa montaña de papeles y PDF en un archivo digital con buscador, y con Docker se instala en unos minutos. En esta guía levantas la aplicación junto a una base de datos PostgreSQL, una cola de tareas con Valkey y los servicios Gotenberg y Tika usando un solo archivo docker-compose.yml. Aprenderás a arrancarlo, a crear tu usuario, a consumir documentos con OCR y etiquetado automático, y a hacer copias de seguridad. La misma explicación está disponible en inglés.

Puntos clave

  • Paperless-ngx es un gestor documental de código abierto que escanea, indexa y archiva tus documentos con búsqueda por texto completo gracias al OCR.
  • El montaje recomendado usa cinco contenedores: la aplicación, una base de datos PostgreSQL, una cola de tareas con Valkey, y Gotenberg más Tika para leer documentos de Office.
  • Todo lo que sueltas en la carpeta consume se procesa solo: se le aplica OCR, se archiva y se le asignan etiquetas según tus reglas.
  • Fija una versión concreta de la imagen (por ejemplo ghcr.io/paperless-ngx/paperless-ngx:2.20) en lugar de :latest; así controlas cuándo actualizas.
  • Los datos viven en volúmenes que tú administras y nunca salen de tu servidor; las copias de seguridad se hacen con la herramienta document_exporter incluida.

¿Qué es Paperless-ngx y para qué sirve?

Paperless-ngx es un sistema de gestión documental (DMS) de código abierto y mantenido por la comunidad. Su objetivo es sencillo: acabar con el cajón de papeles. Escaneas una factura, un contrato o una carta, la sueltas en Paperless-ngx y el programa le aplica OCR (reconocimiento óptico de caracteres), la archiva y la deja lista para que la encuentres escribiendo cualquier palabra que aparezca en ella.

El proyecto tiene una historia de relevos: nació el paperless original, luego llegó paperless-ng y, cuando ese dejó de mantenerse, un grupo de la comunidad tomó el testigo en 2022 y creó paperless-ngx, que es hoy la versión viva y activa. En la práctica funciona como tu propio archivo digital: sustituye a servicios comerciales de gestión documental, pero con los documentos guardados en tu servidor, en volúmenes que tú controlas, sin que nadie los analice.

Su núcleo combina tres ideas: un motor de OCR que extrae el texto de cada página, un índice de búsqueda de texto completo, y un sistema de etiquetas, tipos de documento y corresponsales que puede clasificar solo lo que le llega. Si vienes de esta serie y ya tienes claros los volúmenes y bind mounts en Docker, la persistencia de datos aquí te resultará familiar.

¿Qué requisitos y arquitectura necesita?

Necesitas una máquina Linux con Docker y el plugin Compose instalados. Si aún no los tienes, empieza por la guía para instalar Docker en Ubuntu 24.04. Con 2 GB de RAM y un par de núcleos basta para un uso personal, aunque el OCR de documentos grandes agradece algo más de memoria.

A diferencia de una aplicación de un solo contenedor, Paperless-ngx se apoya en varias piezas que conviene conocer:

  • La aplicación (webserver): la interfaz web y el trabajador que procesa los documentos. Escucha en el puerto 8000.
  • La base de datos (PostgreSQL): guarda los metadatos, las etiquetas y el índice. Es la opción recomendada frente a SQLite.
  • La cola de tareas (Valkey, un derivado de Redis): Paperless-ngx procesa los documentos en segundo plano con Celery, y Valkey es el intermediario que reparte ese trabajo.
  • Gotenberg y Tika: dos servicios opcionales pero muy recomendables. Gotenberg convierte documentos de Office (Word, Excel, LibreOffice) a PDF y Tika extrae su texto, de modo que Paperless-ngx no solo entiende PDF e imágenes.

El OCR lo realiza internamente OCRmyPDF, que a su vez se apoya en el motor Tesseract. El idioma se elige con la variable PAPERLESS_OCR_LANGUAGE, usando los códigos de Tesseract (spa para español, eng para inglés, y puedes combinar varios).

El docker-compose.yml con PostgreSQL y Valkey

Crea una carpeta para el proyecto (por ejemplo paperless/) y guarda dentro este docker-compose.yml. Antes de arrancar, sustituye las contraseñas de ejemplo y genera una PAPERLESS_SECRET_KEY propia:

services:
  broker:
    image: docker.io/valkey/valkey:9-alpine
    restart: unless-stopped
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "valkey-cli", "ping"]
      interval: 30s
      timeout: 5s
      retries: 5

  db:
    image: docker.io/library/postgres:18
    restart: unless-stopped
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: paperless
      POSTGRES_USER: paperless
      POSTGRES_PASSWORD: cambia_esta_clave_db
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U paperless"]
      interval: 30s
      timeout: 5s
      retries: 5

  gotenberg:
    image: docker.io/gotenberg/gotenberg:8.34
    restart: unless-stopped
    command:
      - "gotenberg"
      - "--chromium-disable-javascript=true"
      - "--chromium-allow-list=file:///tmp/.*"

  tika:
    image: docker.io/apache/tika:3.3.1.0
    restart: unless-stopped

  webserver:
    image: ghcr.io/paperless-ngx/paperless-ngx:2.20
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      broker:
        condition: service_healthy
      gotenberg:
        condition: service_started
      tika:
        condition: service_started
    ports:
      - "8000:8000"
    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_DBENGINE: postgresql
      PAPERLESS_DBHOST: db
      PAPERLESS_DBNAME: paperless
      PAPERLESS_DBUSER: paperless
      PAPERLESS_DBPASS: cambia_esta_clave_db
      PAPERLESS_SECRET_KEY: cambia_esta_clave_secreta_larga
      PAPERLESS_URL: https://archivo.midominio.com
      PAPERLESS_TIME_ZONE: Europe/Madrid
      PAPERLESS_OCR_LANGUAGE: spa
      PAPERLESS_TIKA_ENABLED: 1
      PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
      PAPERLESS_TIKA_ENDPOINT: http://tika:9998
      PAPERLESS_ADMIN_USER: admin
      PAPERLESS_ADMIN_PASSWORD: cambia_esta_clave_admin

volumes:
  redisdata:
  pgdata:
  data:
  media:

Fíjate en un par de detalles. La aplicación no arranca hasta que la base de datos y la cola pasan su healthcheck, gracias a depends_on con la condición service_healthy. El puerto 8000 del contenedor se publica en el 8000 del anfitrión, así que la interfaz quedará en http://localhost:8000. Las carpetas export y consume son bind mounts a tu disco (las verás junto al docker-compose.yml), mientras que los datos y los ficheros originales viven en los volúmenes con nombre data y media.

Genera la clave secreta con este comando y pégala en PAPERLESS_SECRET_KEY:

python3 -c "import secrets; print(secrets.token_urlsafe(64))"

Con el archivo listo, arranca la pila en segundo plano y sigue el registro del arranque:

docker compose up -d
docker compose ps
docker compose logs -f webserver

¿Cómo hago el primer arranque y creo el usuario?

La primera vez, la aplicación aplica las migraciones de la base de datos y prepara el índice, así que el arranque tarda un poco más de lo habitual. Como definimos PAPERLESS_ADMIN_USER y PAPERLESS_ADMIN_PASSWORD en el Compose, Paperless-ngx crea el superusuario automáticamente; cuando el registro deje de moverse, abre http://localhost:8000 y entra con esas credenciales.

Si prefieres no dejar la contraseña en el archivo, borra esas dos variables y crea el usuario a mano una sola vez con el comando interactivo:

docker compose run --rm webserver createsuperuser

Una vez dentro verás un panel vacío. Antes de subir nada, entra en Ajustes y revisa el idioma de la interfaz y la zona horaria; el OCR ya está fijado en español por la variable PAPERLESS_OCR_LANGUAGE: spa.

¿Cómo se consumen documentos y funciona el etiquetado automático?

Aquí está la magia de Paperless-ngx: la carpeta consume. Todo lo que copies dentro del bind mount ./consume se detecta y se procesa solo. Prueba a arrastrar un PDF escaneado:

cp ~/facturas/factura-enero.pdf ./consume/
docker compose logs -f webserver

El registro irá mostrando cómo aplica el OCR, extrae el texto, genera una miniatura y archiva el documento; a los pocos segundos aparecerá en la interfaz, ya buscable por su contenido. Si tu carpeta consume está en un recurso de red (NFS o SMB) donde no funcionan las notificaciones del sistema de ficheros, activa el sondeo periódico añadiendo PAPERLESS_CONSUMER_POLLING: 30 (en segundos) al entorno del webserver.

El etiquetado automático se apoya en dos mecanismos. El primero son las reglas de coincidencia: defines una etiqueta (por ejemplo, "Banco") y le dices que se asigne cuando el texto contenga cierta palabra, una expresión regular o una coincidencia difusa. El segundo es el algoritmo Auto, un clasificador que aprende de tus correcciones: cuanto más etiquetas a mano, mejor predice las etiquetas, el tipo de documento y el corresponsal de los siguientes. Lo mismo aplica a los tipos de documento (factura, contrato, nómina) y a los corresponsales (quién lo envía).

¿Cómo hago copias de seguridad?

La forma recomendada de respaldar Paperless-ngx es el exportador incluido, document_exporter, que vuelca todos los documentos y sus metadatos a la carpeta export:

docker compose exec webserver document_exporter ../export

Ese comando crea en ./export una copia autocontenida (los ficheros originales, el texto y un manifiesto en JSON) que puedes restaurar en cualquier instalación nueva con document_importer. Es la opción más portátil porque no depende de la versión de PostgreSQL.

Como alternativa de bajo nivel, puedes respaldar directamente los volúmenes data y media junto con un volcado de la base de datos con pg_dump. Sea cual sea el método, automatiza la copia y guárdala fuera del servidor; más adelante en esta serie lo haremos con Duplicati. Para actualizar Paperless-ngx, cambia la etiqueta de la imagen a la nueva versión y recrea los contenedores:

docker compose pull
docker compose up -d

Preguntas frecuentes

¿Necesito de verdad Gotenberg y Tika?

No son imprescindibles, pero merecen mucho la pena. Sin ellos, Paperless-ngx procesa PDF e imágenes con normalidad. Con ellos, además, entiende documentos de Office (Word, Excel, LibreOffice): Gotenberg los convierte a PDF y Tika extrae su texto para el buscador. Si solo vas a archivar PDF escaneados, puedes omitir ambos servicios y quitar las tres variables PAPERLESS_TIKA_*.

¿Por qué usa Valkey en lugar de Redis?

Valkey es un derivado de Redis creado por la comunidad y la Linux Foundation en 2024, compatible con su protocolo. Paperless-ngx lo usa como intermediario de la cola de tareas de Celery, que es la que procesa los documentos en segundo plano. La variable de conexión se sigue llamando PAPERLESS_REDIS por compatibilidad, aunque apunte al contenedor de Valkey.

¿Puedo usar SQLite en lugar de PostgreSQL?

Sí, Paperless-ngx arranca con SQLite si no defines una base de datos, pero solo se recomienda para pruebas o instalaciones muy pequeñas. Para un archivo que va a crecer con los años, PostgreSQL ofrece mejor rendimiento en las búsquedas y mayor robustez. Cambiar de SQLite a PostgreSQL después no es inmediato, así que es mejor empezar directamente con PostgreSQL.

Conclusión

Con un único docker-compose.yml tienes un gestor documental completo: OCR, buscador de texto completo y etiquetado automático, con los documentos guardados en volúmenes que no salen de tu servidor. El siguiente paso lógico es exponerlo a Internet con seguridad detrás de Traefik, afinar tus reglas de etiquetas y programar la copia de seguridad periódica con document_exporter. A partir de ahí, cada papel que entre por tu puerta acabará escaneado, buscable y archivado sin que tengas que ordenarlo a mano.

Fuentes

  1. Documentación oficial de Paperless-ngx
  2. Repositorio de Paperless-ngx en GitHub
  3. Documentación de Gotenberg

Ruta: Productividad y documentos self-hosted con Docker