Only media/consume/export/trash stay on the UNAS share; SQLite over NFS risks lock contention and corruption.
116 lines
3.4 KiB
Markdown
116 lines
3.4 KiB
Markdown
# Paperless-ngx
|
|
|
|
Document management system that scans, indexes, and archives paper documents
|
|
with full-text OCR search. Runs with the bundled SQLite database and a Redis
|
|
task broker.
|
|
|
|
## Persistent Data
|
|
|
|
Split between local disk and the UNAS `paperless_data` share (see
|
|
[nfs-mounts](../../docs/unas/nfs-mounts.md)):
|
|
|
|
- `paperless_data` named volume (local disk) — SQLite database, search index,
|
|
and classification model. Kept off NFS because SQLite file locking over NFS
|
|
risks corruption and slow queries.
|
|
- Share dirs, NFS-mounted on the Proxmox host and bind-mounted into the LXC
|
|
at `PAPERLESS_DATA_ROOT`:
|
|
- `media/` — original and archived documents.
|
|
- `consume/` — watched for new documents; safe to empty once ingested.
|
|
- `export/` — target for `document_exporter` backups.
|
|
- `trash/` — deleted documents until emptied.
|
|
|
|
The share binds use `create_host_path: false`, so the stack refuses to start
|
|
if the share is not mounted. Redis broker state is in the
|
|
`paperless_redis_data` named volume.
|
|
|
|
## Installation
|
|
|
|
1. Create `.env` if it does not exist:
|
|
|
|
```bash
|
|
cp -n .env.sample .env
|
|
```
|
|
|
|
2. Set the required values in `.env`:
|
|
|
|
```dotenv
|
|
TZ=Africa/Johannesburg
|
|
PAPERLESS_URL=https://paperless-ngx.home.example.com
|
|
PAPERLESS_SECRET_KEY=<random-secret> # openssl rand -base64 48
|
|
PAPERLESS_DATA_ROOT=/mnt/unas/paperless_data
|
|
PUID=1000
|
|
PGID=1000
|
|
|
|
DOCKERLOGGING_MAXFILE=3
|
|
DOCKERLOGGING_MAXSIZE=10m
|
|
```
|
|
|
|
`PAPERLESS_URL` must match the URL used in the browser, otherwise CSRF
|
|
checks fail behind the reverse proxy.
|
|
|
|
3. Ensure the share is bind-mounted into the LXC and owned by the container
|
|
user (host-side UID for an unprivileged LXC is `LXC_IDMAP_BASE + PUID`):
|
|
|
|
```bash
|
|
# On the Proxmox host
|
|
pct set <vmid> -mp0 /mnt/unas/paperless_data,mp=/mnt/unas/paperless_data
|
|
mkdir -p /mnt/unas/paperless_data/{data,media,consume,export,trash}
|
|
chown -R 101000:101000 /mnt/unas/paperless_data
|
|
```
|
|
|
|
4. Deploy with `make`:
|
|
|
|
```bash
|
|
make deploy-paperless
|
|
```
|
|
|
|
Manual equivalent:
|
|
|
|
```bash
|
|
./substitute_env.sh docker-compose-files/paperless-ngx/template.yaml docker-compose.paperless.yml .env
|
|
docker compose -f docker-compose.paperless.yml config --quiet
|
|
docker compose -f docker-compose.paperless.yml up -d
|
|
```
|
|
|
|
5. Create the first user, unless `PAPERLESS_ADMIN_USER` is set in `.env`:
|
|
|
|
```bash
|
|
docker exec -it paperless createsuperuser
|
|
```
|
|
|
|
6. Verify the containers and open `http://<host-ip>:8000`:
|
|
|
|
```bash
|
|
docker compose -f docker-compose.paperless.yml ps
|
|
docker compose -f docker-compose.paperless.yml logs --tail=100 paperless
|
|
```
|
|
|
|
## Reverse Proxy
|
|
|
|
The Caddyfile proxies `paperless-ngx.<domain>` to this host on port 8000 with
|
|
`header_up Host {host}` so CSRF origin checks pass. After changing the port,
|
|
update `docker-compose-files/caddy/Caddyfile_template` and run
|
|
`make reload-caddy`.
|
|
|
|
## Backup
|
|
|
|
Run the built-in exporter, then back up `PAPERLESS_DATA_ROOT/export` (it
|
|
contains documents plus a manifest that restores tags, correspondents, and
|
|
metadata):
|
|
|
|
```bash
|
|
docker exec paperless document_exporter /usr/src/paperless/export --zip
|
|
```
|
|
|
|
## Useful Commands
|
|
|
|
```bash
|
|
# Tail logs
|
|
docker compose -f docker-compose.paperless.yml logs -f paperless
|
|
|
|
# Retrain the document classifier
|
|
docker exec paperless document_create_classifier
|
|
|
|
# Re-run OCR on a document
|
|
docker exec paperless document_archiver --overwrite --document <id>
|
|
```
|