Paperless-ngx — scan, index, OCR, and archive your physical documents into a searchable digital library with tags, correspondents, and full-text search. Deployed as an all-in-one host-networked Nomad job: a Redis broker sidecar plus the Paperless app on SQLite, with data/media/consume volumes.
Needs nomad-pack on PATH. The script only adds the nomploy registry and runs this pack.
Source ↗ Project ↗ ★ 46.9k ⚑ Report an issue
Save as values.hcl, edit, then run:
# The name of the Nomad job.
job_name = "paperless-ngx"
# The Nomad namespace to deploy into.
namespace = "default"
# The datacenters to deploy to.
datacenters = ["*"]
# The Paperless-ngx container image. Pin a tag in production.
image = "ghcr.io/paperless-ngx/paperless-ngx:latest"
# The Redis broker image.
redis_image = "redis:7-alpine"
# Host port for the Paperless web UI (PAPERLESS_PORT).
port = 8000
# Host port for the co-located Redis broker.
redis_port = 6379
# Superuser created on first start (PAPERLESS_ADMIN_USER).
admin_user = "admin"
# Superuser password (PAPERLESS_ADMIN_PASSWORD). CHANGE THIS.
admin_password = "changeme-please"
# Django secret key (PAPERLESS_SECRET_KEY). Generate a long random value for production.
secret_key = "change-me-to-a-long-random-secret-key"
# Time zone (PAPERLESS_TIME_ZONE).
timezone = "Etc/UTC"
# Tesseract OCR language (PAPERLESS_OCR_LANGUAGE), e.g. "eng", "deu", "eng+deu".
ocr_language = "eng"
# Public URL Paperless is served at (PAPERLESS_URL). Empty = not set. Required if exposed on a domain.
url = ""
# Named volume for the SQLite database and index (/usr/src/paperless/data).
data_volume = "paperless_data"
# Named volume for archived documents (/usr/src/paperless/media). Critical — back it up.
media_volume = "paperless_media"
# Named volume watched for new documents to import (/usr/src/paperless/consume).
consume_volume = "paperless_consume"
# Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []
# Resources for the Paperless app task (OCR is CPU-heavy).
resources = {
cpu = 2000
memory = 1024
}
# Resources for the Redis broker task.
redis_resources = {
cpu = 200
memory = 128
}
| Name | Type | Default | Description |
|---|---|---|---|
| job_name | string | "paperless-ngx" | The name of the Nomad job. |
| namespace | string | "default" | The Nomad namespace to deploy into. |
| datacenters | list | ["*"] | The datacenters to deploy to. |
| image | string | "ghcr.io/paperless-ngx/paperless-ngx:latest" | The Paperless-ngx container image. Pin a tag in production. |
| redis_image | string | "redis:7-alpine" | The Redis broker image. |
| port | number | 8000 | Host port for the Paperless web UI (PAPERLESS_PORT). |
| redis_port | number | 6379 | Host port for the co-located Redis broker. |
| admin_user | string | "admin" | Superuser created on first start (PAPERLESS_ADMIN_USER). |
| admin_password set me | string | "changeme-please" | Superuser password (PAPERLESS_ADMIN_PASSWORD). CHANGE THIS. |
| secret_key set me | string | "change-me-to-a-long-random-secret-key" | Django secret key (PAPERLESS_SECRET_KEY). Generate a long random value for production. |
| timezone | string | "Etc/UTC" | Time zone (PAPERLESS_TIME_ZONE). |
| ocr_language | string | "eng" | Tesseract OCR language (PAPERLESS_OCR_LANGUAGE), e.g. "eng", "deu", "eng+deu". |
| url | string | "" | Public URL Paperless is served at (PAPERLESS_URL). Empty = not set. Required if exposed on a domain. |
| data_volume | string | "paperless_data" | Named volume for the SQLite database and index (/usr/src/paperless/data). |
| media_volume | string | "paperless_media" | Named volume for archived documents (/usr/src/paperless/media). Critical — back it up. |
| consume_volume | string | "paperless_consume" | Named volume watched for new documents to import (/usr/src/paperless/consume). |
| constraints | list | [] | Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true". |
| resources | object | {
cpu = 2000
memory = 1024
} | Resources for the Paperless app task (OCR is CPU-heavy). |
| redis_resources | object | {
cpu = 200
memory = 128
} | Resources for the Redis broker task. |
No variables match.
This pack stores data in 3 Docker named volumes:
paperless_datapaperless_mediapaperless_consume
⚠ This pack bundles a database. A cold copy of the volume can be inconsistent — for a reliable backup, dump the DB (pg_dump / mysqldump) or stop the job while backing up.
restic
# Run on the node hosting this pack. Point restic at your repo first: # export RESTIC_REPOSITORY="s3:https://<account>.r2.cloudflarestorage.com/<bucket>" # export RESTIC_PASSWORD="<repo-password>" # export AWS_ACCESS_KEY_ID=<key> AWS_SECRET_ACCESS_KEY=<secret> restic backup \ /var/lib/docker/volumes/paperless_data/_data \ /var/lib/docker/volumes/paperless_media/_data \ /var/lib/docker/volumes/paperless_consume/_data
rclone (sync to S3/R2)
rclone sync /var/lib/docker/volumes/paperless_data/_data backup:<bucket>/paperless_data rclone sync /var/lib/docker/volumes/paperless_media/_data backup:<bucket>/paperless_media rclone sync /var/lib/docker/volumes/paperless_consume/_data backup:<bucket>/paperless_consume
Paths assume the default Docker volume location (/var/lib/docker/volumes). Restore by stopping the job, restoring files into the same volume, and re-running the pack.
Paperless-ngx — scan, index, OCR, and archive your physical documents into a searchable digital library with tags, correspondents, document types, and full-text search.
All-in-one host-networked Nomad job: a Redis broker prestart sidecar plus the Paperless app on SQLite (no separate database server). The Paperless image runs its own startup migration and ownership fix, so no chown init is needed.
nomad-pack registry add nomploy https://github.com/Nomploy/nomad-packs
nomad-pack run paperless-ngx --registry=nomploy
| Variable | Default | Description |
|---|---|---|
port |
8000 |
Web UI port (PAPERLESS_PORT). |
redis_port |
6379 |
Co-located Redis broker port. |
admin_user / admin_password |
admin / changeme-please |
Superuser created on first start. Change the password. |
secret_key |
placeholder | PAPERLESS_SECRET_KEY — set a long random value. |
ocr_language |
eng |
Tesseract language(s), e.g. deu, eng+deu. |
timezone |
Etc/UTC |
PAPERLESS_TIME_ZONE. |
url |
"" |
PAPERLESS_URL; required if exposed on a domain. |
data_volume |
paperless_data |
/usr/src/paperless/data — SQLite DB + index. |
media_volume |
paperless_media |
/usr/src/paperless/media — archived docs (back up). |
consume_volume |
paperless_consume |
/usr/src/paperless/consume — drop files to import. |
resources |
{ cpu = 2000, memory = 1024 } |
Paperless task resources (OCR is CPU-heavy). |
Drop documents into the consume volume (or upload via the UI) and Paperless will OCR and file
them. Pin the job to the node holding the volumes with constraints.