Paperless-ngx: Gestão Documental Self-Hosted com RGPD

O Paperless-ngx é um sistema de gestão documental self-hosted que digitaliza, indexa e arquiva documentos com OCR automático. Esta guía prática mostra como instalar via Docker Compose, configurar OCR multilingue (incluindo português), estruturar um workflow de ingestão e garantir conformidade com o RGPD através de backups e retenção controlada.

Introdução

O Paperless-ngx é a evolução community-driven do Paperless-ng, um sistema de gestão documental (DMS) self-hosted open-source. Permite digitalizar faturas, recibos, contratos, garantias e qualquer documento em papel, armazenando-os numa base de dados pesquisável com OCR full-text. Cada documento é automaticamente classificado por tipo, correspondente e data, com tags e permissões granulares.

As principais vantagens sobre soluções comerciais SaaS são: controlo total dos dados (essencial para RGPD), sem custos de subscrição, OCR com suporte para mais de 100 idiomas, API REST completa, e integração com scanners de rede via SMB/FTP. Para PMEs portuguesas que precisam de cumprir o RGPD, o Paperless-ngx oferece um repositório documental auditável sem depender de terceiros.

ℹ Requisitos mínimos: Servidor com 2GB RAM (4GB recomendado para OCR de volumes elevados), Docker + Docker Compose instalados, 50GB espaço em disco para 10.000+ documentos com OCR, e um scanner ou app móvel com capacidade de envio por email/SMB.

Instalar via Docker Compose

A instalação recomendada usa Docker Compose com dois containers: o servidor Paperless-ngx e um broker Redis (necessário para filas de processamento). O Gotenberg e Tika são opcionais mas recomendados — Gotenberg converte Office para PDF e Tika extrai texto de formatos binários.

Criar a estrutura de directorias e o ficheiro docker-compose.yml:

mkdir -p ~/paperless-ngx && cd ~/paperless-ngx
mkdir -p {data,export,consume,media}

O ficheiro docker-compose.yml completo:

version: "3.4"
services:
  broker:
    image: docker.io/library/redis:7
    restart: unless-stopped
    volumes:
      - redisdata:/data

  gotenberg:
    image: docker.io/gotenberg/gotenberg:8
    restart: unless-stopped
    environment:
      DISABLE_HEALTH_CHECK: "true"

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

  webserver:
    image: ghcr.io/paperless-ngx/paperless-ngx:latest
    restart: unless-stopped
    depends_on:
      - broker
      - gotenberg
      - tika
    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_TIKA_ENDPOINT: http://tika:9998
      PAPERLESS_GOTENBERG_ENDPOINT: http://gotenberg:3000
      PAPERLESS_SECRET_KEY: "alterar-esta-chave-secreta-32-chars"
      PAPERLESS_URL: "https://docs.empresa.pt"
      PAPERLESS_OCR_LANGUAGE: "por+eng"
      PAPERLESS_TIME_ZONE: "Europe/Lisbon"
      PAPERLESS_CONSUMPTION_DIR: /usr/src/paperless/consume
      PAPERLESS_ADMIN_USER: admin
      PAPERLESS_ADMIN_PASSWORD: "SenhaForteAqui"
      PAPERLESS_ADMIN_MAIL: [email protected]
      USERMAP_UID: 1000
      USERMAP_GID: 1000

volumes:
  redisdata:

Variáveis de ambiente críticas a personalizar:

  • PAPERLESS_SECRET_KEY — chave secreta única (mínimo 32 caracteres aleatórios)
  • PAPERLESS_URL — URL pública usada em links de email e API
  • PAPERLESS_OCR_LANGUAGE — idiomas do OCR separados por + (por+eng para português + inglês)
  • PAPERLESS_ADMIN_PASSWORD — senha do utilizador admin inicial
  • USERMAP_UID / USERMAP_GID — UID/GID do utilizador que detém os ficheiros no host

Iniciar os containers e criar a conta administrador:

cd ~/paperless-ngx
docker compose up -d
docker compose run --rm webserver manage createsuperuser  # se não usou PAPERLESS_ADMIN_USER

Verificar se todos os containers estão a correr:

docker compose ps
# Esperado: 4 containers (broker, gotenberg, tika, webserver) com status Up

Aceder à interface web em http://servidor:8000 e fazer login com as credenciais definidas. Para produção, colocar atrás de um reverse proxy (Caddy, Nginx ou Traefik) com TLS — o Paperless-ngx processa dados pessoais, pelo que HTTPS é obrigatório para conformidade RGPD.

✓ Reverse proxy com Caddy (exemplo): docs.empresa.pt { reverse_proxy localhost:8000 } — o Caddy gere certificados Let’s Encrypt automaticamente.

OCR e Pesquisa

O OCR é o coração do Paperless-ngx. Usa o Tesseract OCR com os dados de treino do idioma definido em PAPERLESS_OCR_LANGUAGE. Para documentos em português, o pacote tesseract-ocr-por já vem incluído na imagem Docker oficial.

O pipeline de OCR processa cada documento em três fases:

  1. Conversão para imagem — se o documento for PDF, cada página é convertida em imagem a 300 DPI usando Ghostscript
  2. Reconhecimento de texto — Tesseract analisa cada imagem e extrai o texto no idioma configurado
  3. Indexação — o texto extraído é armazenado numa base de dados Whoosh full-text, pesquisável instantaneamente

Configurações avançadas de OCR no docker-compose.env ou no ambiente do container:

# Idiomas do OCR (português + inglês + francês)
PAPERLESS_OCR_LANGUAGE=por+eng+fra

# Modo OCR: skip (não re-processar PDFs já com texto)
PAPERLESS_OCR_MODE=skip

# Limpar páginas com texto vs todas as páginas
PAPERLESS_OCR_CLEAN=clean

# DPI para conversão de PDF (padrão 300, baixar para 200 em hardware limitado)
PAPERLESS_OCR_OUTPUT_TYPE=pdf

A pesquisa full-text funciona directamente na barra de pesquisa da interface web. Suporta operadores booleanos (AND, OR, NOT), pesquisa exacta com aspas ("fatura 2025"), e filtros por tipo, correspondente, data e tags.

Exemplos de pesquisa avançada:

# Pesquisar por conteúdo + filtro de tipo
content:"iva" AND type:fatura

# Documentos de um correspondente específico
correspondent:"EDP" AND created:[2025-01-01 TO 2025-12-31]

# Excluir documentos com certa tag
content:"contrato" NOT tag:arquivado

Para volumes elevados (mais de 20.000 documentos), o Paperless-ngx recomenda migrar de Whoosh para PostgreSQL com pg_trgm, que oferece pesquisa fuzzy mais rápida. A migração faz-se definindo PAPERLESS_DBENGINE=pgsql e configurando a ligação PostgreSQL no ambiente.

Workflow Ingestão

O Paperless-ngx oferece múltiplos métodos de ingestão. O mais comum é a pasta de consumo (consume/) — qualquer ficheiro lá colocado é automaticamente processado, OCR’d e removido da pasta. Para automatização, configurar o scanner de rede para enviar directamente para esta pasta via SMB/NFS.

Outros métodos de ingestão:

  • Email — configurar uma conta IMAP; o Paperless lê emails com anexos e importa-os automaticamente
  • API RESTPOST /api/documents/post_document/ com o ficheiro em multipart/form-data
  • App móvel — apps como Paperless Mobile ou Genius Scan enviam para a pasta de consumo via WebDAV
  • Watcher de pasta remota — o container monitoriza PAPERLESS_CONSUMPTION_DIR a cada 5 segundos

Configurar ingestão por email IMAP:

PAPERLESS_CONSUMER_ENABLE_POLLING=true
PAPERLESS_CONSUMER_POLLING=10

# Email IMAP (exemplo com Gmail App Password)
PAPERLESS_CONSUMER_POLLING=60
PAPERLESS_EMAIL_ENABLED=true
PAPERLESS_EMAIL_HOST=imap.gmail.com
PAPERLESS_EMAIL_PORT=993
[email protected]
PAPERLESS_EMAIL_PASS=senha-app-gmail
PAPERLESS_EMAIL_USE_TLS=true
PAPERLESS_EMAIL_DEFAULT_CORRESPONDENT=scanner

O workflow automático (Workflows) é uma funcionalidade que permite aplicar regras automáticas aos documentos ingeridos — atribuir tipo, correspondente, tags e datas com base em padrões no conteúdo ou no nome do ficheiro. Configurar via Settings > Workflows na interface web.

Exemplo de workflow automático: faturas da EDP. Criar uma regra que corresponda a documentos cujo conteúdo inclua “EDP Comercial” e atribua automaticamente: correspondente EDP, tipo Fatura, tag energia. Documentos ingeridos pela pasta de consumo ou email são classificados sem intervenção manual.

ℹ Dica: O Paperless-ngx suporta matching automático baseado em aprendizagem — depois de classificar manualmente 10-15 documentos de um correspondente, o sistema sugere a classificação correcta automaticamente para novos documentos.

Backup e RGPD

O Paperless-ngx armazena dados pessoais (NIFs, moradas, extractos bancários contidos nos documentos), pelo que a conformidade com o RGPD exige medidas técnicas específicas: encriptação, backups regulares, retenção controlada e registos de acesso.

Backup documental

O comando document_exporter exporta todos os documentos com metadados para a pasta export/:

# Export completo (documentos + metadados + manifest.json)
docker compose exec webserver document_exporter /usr/src/paperless/export -c -z

# -c  inclui ficheiros CSV com metadados
# -z  comprime em .tar.gz

# Restaurar a partir de export
docker compose exec webserver document_importer /usr/src/paperless/export

Script de backup automatizado (cron diário) que exporta e envia para armazenamento remoto:

#!/bin/bash
# /etc/cron.daily/paperless-backup
cd ~/paperless-ngx
docker compose exec -T webserver document_exporter \
  /usr/src/paperless/export -c -z
# Sincronizar para armazenamento off-site (ex: rsync para NAS)
rsync -avz --delete ./export/ [email protected]:/backup/paperless/
# Rotação: manter 30 dias localmente
find ./export -name "*.tar.gz" -mtime +30 -delete

Encriptação em repouso

O Paperless-ngx não encripta ficheiros nativamente, mas o armazenamento pode ser encriptado ao nível do sistema de ficheiros com LUKS ou ao nível do Docker com volumes encriptados. Para conformidade RGPD, recomenda-se LUKS na partição onde reside a pasta data/ e media/.

Retenção e direito ao esquecimento

O RGPD exige que os dados pessoais sejam retainable apenas pelo tempo necessário. O Paperless-ngx permite configurar políticas de retenção por tipo de documento — por exemplo, faturas retidas 10 anos (obrigação fiscal), recibos 5 anos, garantias 2 anos. Configurar via Settings > Document Retention.

Para o direito ao esquecimento (Art. 17.º RGPD), eliminar todos os documentos de uma pessoa através da API:

# Listar documentos de um correspondente
curl -s -H "Authorization: Token API_TOKEN" \
  "https://docs.empresa.pt/api/documents/?correspondent__id=N" \
  | python3 -c "import sys,json; [print(d['id']) for d in json.load(sys.stdin)['results']]"

# Eliminar cada documento (remove ficheiro + OCR + metadados)
curl -X DELETE -H "Authorization: Token API_TOKEN" \
  "https://docs.empresa.pt/api/documents/ID/"

⚠ Atenção RGPD: A eliminação de documentos no Paperless-ngx remove permanentemente o ficheiro, o texto OCR e os metadados. No entanto, se existirem backups anteriores, esses backups contêm os dados. Para conformidade total, documentar o procedimento de eliminação e garantir que os backups com dados pessoais eliminados sejam purgados no próximo ciclo de retenção de backups.

Controlo de acessos e auditoria

O Paperless-ngx suporta múltiplos utilizadores com permissões granulares por documento. Para conformidade RGPD, criar contas separadas por utilizador (evitar contas partilhadas), activar registo de auditoria e configurar 2FA para todas as contas com acesso a dados pessoais.

# Activar 2FA obrigatório via ambiente
PAPERLESS_ENABLE_UPDATES=true
# Forçar 2FA via Django admin ou API:
docker compose exec webserver manage shell -c \
  "from django.contrib.auth.models import User; \
   u=User.objects.get(username='admin'); \
   u.totpdevice_set.create()"  # configurar depois na UI

Erros Comuns

Durante a instalação e operação do Paperless-ngx, surgem problemas recorrentes. A tabela seguinte resume os mais frequentes, a causa e a solução:

Sintoma Causa provável Solução
OCR não detecta texto português PAPERLESS_OCR_LANGUAGE não inclui por Definir PAPERLESS_OCR_LANGUAGE=por+eng e reprocessar com document_archiver --overwrite
Container webserver reinicia em loop PAPERLESS_SECRET_KEY ausente ou demasiado curta Gerar chave com python3 -c "import secrets; print(secrets.token_urlsafe(32))" e reiniciar
Ficheiros na pasta consume não são processados Permissões incorrectas — UID/GID não corresponde ao USERMAP chown -R 1000:1000 consume/ e verificar docker compose logs webserver
Pesquisa full-text não retorna resultados Índice Whoosh corrompido após paragem abrupta docker compose exec webserver manage document_index rebuild
Erro “Gotenberg connection refused” Container Gotenberg não iniciou ou endpoint incorrecto Verificar docker compose ps e PAPERLESS_GOTENBERG_ENDPOINT=http://gotenberg:3000
PDF com texto não é OCR’d (fica sem conteúdo pesquisável) PAPERLESS_OCR_MODE=skip ignora PDFs com texto existente Usar PAPERLESS_OCR_MODE=force para reprocessar ou skip_noabort para avisar
Email IMAP não importa anexos App Password incorrecta ou TLS mal configurado Verificar docker compose logs webserver | grep mail e testar ligação IMAP manualmente
Backup document_exporter falha com “permission denied” Pasta export/ sem permissões de escrita para o UID do container chown -R 1000:1000 export/ antes de executar o export
Consumo de CPU 100% constante PAPERLESS_CONSUMER_POLLING demasiado baixo (1-2s) Aumentar para PAPERLESS_CONSUMER_POLLING=10 ou usar inotify

Para diagnosticar qualquer problema, o primeiro passo é sempre consultar os logs do container: docker compose logs -f webserver. O Paperless-ngx tem logging detalhado que identifica a maioria dos problemas em segundos.

O Paperless-ngx é uma solução robusta para PMEs que precisam de gestão documental com conformidade RGPD sem custos de licenciamento. Com Docker Compose, OCR multilingue e backups automatizados, oferece um repositório documental pesquisável que coloca o controlo dos dados nas mãos da organização — não de terceiros SaaS.